You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2013/06/19 00:34:28 UTC

[3/8] git commit: Use a simple pre-processor to split t5-core-dom.coffee into jquery and prototype variations

Use a simple pre-processor to split t5-core-dom.coffee into jquery and prototype variations


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/56a24f59
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/56a24f59
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/56a24f59

Branch: refs/heads/master
Commit: 56a24f59b27d6778e0a0b677b8d1bae15aacfeac
Parents: 18d96cf
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Tue Jun 18 13:44:17 2013 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Tue Jun 18 13:44:17 2013 -0700

----------------------------------------------------------------------
 .../groovy/t5build/CompileCoffeeScript.groovy   |  11 +-
 .../t5build/PreprocessCoffeeScript.groovy       | 101 +++
 tapestry-core/build.gradle                      |  11 +-
 .../META-INF/modules/t5/core/messages.coffee    |  38 +-
 .../apache/tapestry5/t5-core-dom-jquery.coffee  | 538 -----------
 .../tapestry5/t5-core-dom-prototype.coffee      | 608 -------------
 .../org/apache/tapestry5/t5-core-dom.coffee     | 895 +++++++++++++++++++
 7 files changed, 1025 insertions(+), 1177 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/56a24f59/buildSrc/src/main/groovy/t5build/CompileCoffeeScript.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/t5build/CompileCoffeeScript.groovy b/buildSrc/src/main/groovy/t5build/CompileCoffeeScript.groovy
index f125a13..19bc8aa 100644
--- a/buildSrc/src/main/groovy/t5build/CompileCoffeeScript.groovy
+++ b/buildSrc/src/main/groovy/t5build/CompileCoffeeScript.groovy
@@ -6,15 +6,6 @@ import ro.isdc.wro.extensions.processor.support.coffeescript.*
 import org.gradle.api.*
 import org.gradle.api.tasks.*
 
-class CustomizedProcessor extends RhinoCoffeeScriptProcessor {
-
-    protected CoffeeScript newCoffeeScript() {
-        CoffeeScript engine = new CoffeeScript()
-        engine.options = ["bare"]
-        return engine
-    }
-}
-
 class CompileCoffeeScript extends DefaultTask {
 
     {
@@ -44,7 +35,7 @@ class CompileCoffeeScript extends DefaultTask {
             include '**/*.coffee'
         }
 
-        def processor = new CustomizedProcessor()
+        def processor = new RhinoCoffeeScriptProcessor()
 
         tree.visit { visit ->
             if (visit.directory) return

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/56a24f59/buildSrc/src/main/groovy/t5build/PreprocessCoffeeScript.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/t5build/PreprocessCoffeeScript.groovy b/buildSrc/src/main/groovy/t5build/PreprocessCoffeeScript.groovy
new file mode 100644
index 0000000..0b12b65
--- /dev/null
+++ b/buildSrc/src/main/groovy/t5build/PreprocessCoffeeScript.groovy
@@ -0,0 +1,101 @@
+package t5build
+
+import org.gradle.api.*
+import org.gradle.api.tasks.*
+
+/**
+ * Used by the tapestry-core module, to split t5-core-dom into two flavors: one for prototype, one for jQuery.
+ */
+class PreprocessCoffeeScript extends DefaultTask {
+
+    {
+        description = "Splits CoffeeScript source files into multiple flavors."
+        group = "build"
+    }
+
+    def flavors = ["prototype", "jquery"]
+    def srcDir = "src/main/preprocessed-coffeescript"
+    def outputDir = "${project.buildDir}/postprocessed-coffeescript"
+
+    @InputDirectory
+    File getSrcDir() { project.file(srcDir) }
+
+    @OutputDirectory
+    File getOutputDir() { project.file(outputDir) }
+
+    @TaskAction
+    void doSplit() {
+        logger.info "Splitting CoffeeScript sources from $srcDir into $outputDir ($flavors)"
+
+        def outputDirFile = getOutputDir()
+        // Recursively delete output directory if it exists
+        outputDirFile.deleteDir()
+
+        def tree = project.fileTree srcDir, {
+            include '**/*.coffee'
+        }
+
+        tree.visit { visit ->
+            if (visit.directory) return
+
+            def inputFile = visit.file
+            def inputPath = visit.path
+
+            flavors.each { flavor ->
+
+                def dotx = inputPath.lastIndexOf "."
+
+                def outputPath = inputPath.substring(0, dotx) + "-${flavor}.coffee"
+
+                def outputFile = new File(outputDirFile, outputPath)
+
+                logger.info "Generating ${outputPath} from ${inputPath}"
+
+                outputFile.parentFile.mkdirs()
+
+                split inputFile, outputFile, flavor
+            }
+        }
+    }
+
+    // Very sloppy; doesn't actually differentiate between #if and #elseif (nesting is not actually
+    // supported). Some more C Macro support would be nice, too.
+    def ifPattern = ~/^#(else)?if\s+(\w+)$/
+
+    void split(File inputFile, File outputFile, String flavor) {
+
+        def ignoring = false
+
+        outputFile.withPrintWriter { pw ->
+
+            inputFile.eachLine { line ->
+
+                def matcher = ifPattern.matcher line
+
+                if (matcher.matches()) {
+
+                    // ignore the block unless it matches the flavor
+                    ignoring = matcher[0][2] != flavor
+
+                    // And don't copy the "#if" line at all.
+                    return;
+                }
+
+                // Note that we don't check for nested #if, and those aren't supported.
+
+                if (line == "#endif") {
+                    ignoring = false;
+                    return;
+                }
+
+                if (ignoring) {
+                    return;
+                }
+
+                // Copy the line to the output:
+
+                pw.println line
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/56a24f59/tapestry-core/build.gradle
----------------------------------------------------------------------
diff --git a/tapestry-core/build.gradle b/tapestry-core/build.gradle
index bf94b14..76536fc 100644
--- a/tapestry-core/build.gradle
+++ b/tapestry-core/build.gradle
@@ -26,7 +26,7 @@ dependencies {
 
     // Transitive will bring in the unwanted string template library as well
     compile "org.antlr:antlr-runtime:3.3", {
-        exclude group:"org.antlr", module:"stringtemplate"
+        exclude group: "org.antlr", module: "stringtemplate"
     }
 
     // Antlr3 tool path used with the antlr3 task
@@ -53,12 +53,16 @@ task generateGrammarSource(type: JavaExec) {
     }
 }
 
+task preprocessCoffeeScript(type: PreprocessCoffeeScript) {
+}
+
 task compileCoffeeScript(type: CompileCoffeeScript) {
     outputDir "${mainGeneratedDir}/compiled-coffeescript"
 }
 
 task compileProcessedCoffeescript(type: CompileCoffeeScript) {
-    srcDir "src/main/preprocessed-coffeescript"
+    dependsOn preprocessCoffeeScript
+    srcDir preprocessCoffeeScript.outputDir
     outputDir "${mainGeneratedDir}/compiled-processed-coffeescript"
 }
 
@@ -72,6 +76,9 @@ sourceSets {
         output.dir(compileCoffeeScript.outputDir, builtBy: compileCoffeeScript)
         output.dir(compileProcessedCoffeescript.outputDir, builtBy: compileProcessedCoffeescript)
         output.dir(antlrOutput, builtBy: generateGrammarSource)
+        java {
+            srcDir antlrOutput
+        }
     }
     test {
         output.dir(compileTestCoffeeScript.outputDir, builtBy: compileTestCoffeeScript)

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/56a24f59/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/messages.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/messages.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/messages.coffee
index 75d170b..2f4ec67 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/messages.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/messages.coffee
@@ -1,4 +1,4 @@
-# Copyright 2012 The Apache Software Foundation
+# Copyright 2012-2013 The Apache Software Foundation
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -29,27 +29,27 @@
 # presence of the `%` character.  In addition, any message key that begins with "private-" is
 # assumed to contain sensitive data (such as database URLs or passwords) and will not be
 # exposed to the client.
-do ->
-  # In the unexpected case that the data-locale attribute is missing, assume English
-  locale = (document.documentElement.getAttribute "data-locale") or "en"
 
-  define ["./messages/#{locale}", "underscore", "./console"],
-    (messages, _, console) ->
+# In the unexpected case that the data-locale attribute is missing, assume English
+locale = (document.documentElement.getAttribute "data-locale") or "en"
 
-      # Returns the application message catalog message for the given key. Returns
-      # a placeholder if the key is not found.
-      get = (key) ->
-        value = messages[key]
+define ["./messages/#{locale}", "underscore", "./console"],
+  (messages, _, console) ->
 
-        if value
-          return value
-        else
-          console.error "No value for message catalog key '#{key}' exists."
-          return "[[Missing Key: '#{key}']]"
+    # Returns the application message catalog message for the given key. Returns
+    # a placeholder if the key is not found.
+    get = (key) ->
+      value = messages[key]
 
-      # Returns all keys that are defined by the underlying catalog, in no specific order.
-      get.keys = -> _.keys messages
+      if value
+        return value
+      else
+        console.error "No value for message catalog key '#{key}' exists."
+        return "[[Missing Key: '#{key}']]"
 
+    # Returns all keys that are defined by the underlying catalog, in no specific order.
+    get.keys = -> _.keys messages
 
-      # Export get as the main function.
-      return get
+
+    # Export get as the main function.
+    return get

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/56a24f59/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-jquery.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-jquery.coffee b/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-jquery.coffee
deleted file mode 100644
index b1ddbfc..0000000
--- a/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-jquery.coffee
+++ /dev/null
@@ -1,538 +0,0 @@
-# Copyright 2012-2013 The Apache Software Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http:#www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# ## t5/core/dom (jQuery)
-#
-# This is the abstraction layer that allows the majority of components to operate without caring whether the
-# underlying infrastructure framework is Prototype, jQuery, or something else.  This implementation is specific
-# to jQuery, but Tapestry can be adapted to any infrastructure framework by re-implementing this module.
-#
-# The abstraction layer has a number of disadvantages:
-#
-# * It adds a number of layers of wrapper around the infrastructure framework objects
-# * It is leaky; some behaviors will vary slightly based on the active infrastructure framework
-# * The abstraction is alien to both Prototype and jQuery developers; it mixes some ideas from both
-# * It is much less powerful or expressive than either infrastructure framework used directly
-#
-# It is quite concievable that some components will require direct access to the infrastructure framework, especially
-# those that are wrappers around third party libraries or plugins; however many simple components may need no more than
-# the abstract layer and gain the valuable benefit of not caring about the infrastructure framework.
-#
-# Changes to this library should be coordinated with the Prototype version.
-define ["underscore", "./utils", "jquery", "./events"], (_, utils, $, events) ->
-
-  # Converts content (provided to `ElementWrapper.update()` or `append()`) into an appropriate type. This
-  # primarily exists to validate the value, and to "unpack" an ElementWrapper into a DOM element.
-  convertContent = (content) ->
-    if _.isString content
-      return content
-
-    if _.isElement content
-      return content
-
-    if content instanceof ElementWrapper
-      return content.$
-
-    throw new Error "Provided value <#{content}> is not valid as DOM element content."
-
-  # Generic view of an DOM event that is passed to a handler function.
-  #
-  # Properties:
-  #
-  # * nativeEvent - the native Event object, which may provide additional information.
-  # * memo - the object passed to `ElementWrapper.trigger()`.
-  # * type - the name of the event that was triggered.
-  # * char - the character value of the pressed key, if a printable character, as a string.
-  # * key -The key value of the pressed key. This is the same as the `char` property for printable keys,
-  #  or a key name for others.
-  class EventWrapper
-
-    constructor: (event, memo) ->
-      @nativeEvent = event
-      @memo = memo
-
-      # This is to satisfy YUICompressor which doesn't seem to like 'char', even
-      # though it doesn't appear to be a reserved word.
-      this[name] = event[name] for name in ["type", "char", "key"]
-
-    # Stops the event which prevents further propagation of the DOM event,
-    # as well as DOM event bubbling.
-    stop: ->
-      @nativeEvent.stopImmediatePropagation()
-      @nativeEvent.preventDefault()
-
-  # Interface between the dom's event model, and jQuery's.
-  #
-  # * jqueryObject - jQuery wrapper around one or more DOM elements
-  # * eventNames - space-separated list of event names
-  # * match - selector to match bubbled elements, or null
-  # * handler - event handler function to invoke; it will be passed an `EventWrapper` instance as the first parameter,
-  #   and the memo as the second parameter. `this` will be the `ElementWrapper` for the matched element.
-  #
-  # Event handlers may return false to stop event propogation; this prevents an event from bubbling up, and
-  # prevents any browser default behavior from triggering.  This is often easier than accepting the `EventWrapper`
-  # object as the first parameter and invoking `stop()`.
-
-  onevent = (jqueryObject, eventNames, match, handler) ->
-    throw new Error "No event handler was provided." unless handler?
-
-    wrapped = (jqueryEvent, memo) ->
-      # Set `this` to be the matched ElementWrapper, rather than the element on which the event is observed
-      # (which is often further up the hierarchy).
-      elementWrapper = new ElementWrapper $(jqueryEvent.target)
-      eventWrapper = new EventWrapper jqueryEvent, memo
-
-      result = handler.call elementWrapper, eventWrapper, memo
-
-      # If an event handler returns exactly false, then stop the event.
-      if result is false
-        eventWrapper.stop()
-
-      return
-
-    jqueryObject.on eventNames, match, wrapped
-
-    return
-
-  # Wraps a DOM element and jQuery object, providing some common behaviors.
-  # Exposes the DOM element as property `element`.
-  class ElementWrapper
-
-  # Passed the DOM Element
-    constructor: (query) ->
-      @$ = query
-      @element = query[0]
-
-    # Some coders would use some JavaScript cleverness to automate more of the mapping from the ElementWrapper API
-    # to the jQuery API, but that eliminates a chance to write some very necessary documentation.
-
-    toString: ->
-      markup = @element.outerHTML
-
-      "ElementWrapper[#{markup.substring 0, (markup.indexOf ">") + 1}]"
-
-    # Hides the wrapped element, setting its display to 'none'.
-    hide: ->
-      @$.hide()
-
-      triggerReflow()
-
-      return this
-
-    # Displays the wrapped element if hidden.
-    show: ->
-      @$.show()
-
-      triggerReflow()
-
-      return this
-
-    # Gets or sets a CSS property. jQuery provides a lot of mapping of names to canonical names.
-    css: (name, value) ->
-
-      if arguments.length is 1
-        return @$.css name
-
-      @$.css name, value
-
-      return this
-
-    # Returns the offset of the object relative to the document. The returned object has
-    # keys `top`' and `left`'.
-    offset: ->
-      @$.offset()
-
-    # Removes the wrapped element from the DOM.  It can later be re-attached.
-    remove: ->
-      # jQuery's remove() will remove event handlers which we don't want.
-      @$.detach()
-
-      triggerReflow()
-
-      return this
-
-    # Reads or updates an attribute. With one argument, returns the current value
-    # of the attribute. With two arguments, updates the attribute's value, and returns
-    # the previous value. Setting an attribute to null is the same as removing it.
-    #
-    # Alternately, the first attribute can be an object in which case all the keys
-    # and values of the object are applied as attributes, and this `ElementWrapper` is returned.
-    #
-    # * name - the attribute to read or update, or an object of keys and values
-    # * value - (optional) the new value for the attribute
-    attribute: (name, value) ->
-
-      if _.isObject name
-        @$.attr name
-        return this
-
-      current = @$.attr name
-      if arguments.length > 1
-        @$.attr name, value
-
-      return current
-
-    # Moves the cursor to the field.
-    focus: ->
-      @$.focus()
-
-      return this
-
-    # Returns true if the element has the indicated class name, false otherwise.
-    hasClass: (name) ->
-      @$.hasClass name
-
-    # Removes the class name from the element.
-    removeClass: (name) ->
-      @$.removeClass name
-
-      return this
-
-    # Adds the class name to the element.
-    addClass: (name) ->
-      @$.addClass name
-
-      return this
-
-    # Updates this element with new content, replacing any old content. The new content may be HTML text, or a DOM
-    # element, or an ElementWrapper, or null (to remove the body of the element).
-    update: (content) ->
-      @$.empty()
-
-      if content
-        @$.append (convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Appends new content (Element, ElementWrapper, or HTML markup string) to the body of the element.
-    append: (content) ->
-      @$.append (convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Prepends new content (Element, ElementWrapper, or HTML markup string) to the body of the element.
-    prepend: (content) ->
-      @$.prepend (convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Inserts new content (Element, ElementWrapper, or HTML markup string) into the DOM immediately before
-    # this ElementWrapper's element.
-    insertBefore: (content) ->
-      @$.before (convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Inserts new content (Element, ElementWrapper, or HTML markup string) into the DOM immediately after
-    # this ElementWrapper's element.
-    insertAfter: (content) ->
-      @$.after (convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Runs an animation to fade-in the element over the specified duration.
-    #
-    # * duration - animation duration time, in seconds
-    # * callback - function invoked after the animation is complete
-    fadeIn: (duration, callback) ->
-      @$.fadeIn duration * 1000, ->
-        triggerReflow()
-        callback and callback()
-
-      return this
-
-    # Runs an animation to fade out an element over the specified duration. The element should already
-    # be visible and fully opaque.
-    #
-    # * duration - animation duration time, in seconds
-    # * callback - function invoked after the animation is complete
-    fadeOut: (duration, callback) ->
-      @$.fadeOut duration * 1000, ->
-        triggerReflow()
-        callback and callback()
-
-      return this
-
-    # Finds the first child element that matches the CSS selector, wrapped as an ElementWrapper.
-    # Returns null if not found.
-    findFirst: (selector) ->
-      match = @$.find selector
-
-      if match.length
-        # At least one element was matched, just keep the first
-        new ElementWrapper match.first()
-      else
-        return null
-
-    # Finds _all_ child elements matching the CSS selector, returning them
-    # as an array of ElementWrappers.
-    find: (selector) ->
-      matches = @$.find selector
-
-      return [] if matches.length is 0
-
-      for i in [0..(matches.length - 1)]
-        new ElementWrapper matches.eq i
-
-    # Find the first container element that matches the selector (wrapped as an ElementWrapper),
-    # or returns null.
-    findParent: (selector) ->
-      parents = @$.parents selector
-
-      return null unless parents.length
-
-      new ElementWrapper parents.eq(0)
-
-    # Returns this ElementWrapper if it matches the selector; otherwise, returns the first container element (as an ElementWrapper)
-    # that matches the selector. Returns null if no container element matches.
-    closest: (selector) ->
-
-      match = @$.closest selector
-
-      switch
-        when match.length is 0 then return null
-        when match[0] is @element then return this
-        else return new ElementWrapper match
-
-    # Returns an ElementWrapper for this element's containing element.
-    # Returns null if this element has no parent (either because this element is the document object, or
-    # because this element is not yet attached to the DOM).
-    parent: ->
-      parent = @$.parent()
-
-      return null unless parent.length
-
-      new ElementWrapper parent
-
-    # Returns true if this element is visible, false otherwise. This does not check to see if all containers of the
-    # element are visible.
-    visible: ->
-      @$.css("display") isnt "none"
-
-    # Returns true if this element is visible, and all parent elements are also visible, up to the document body.
-    deepVisible: ->
-      cursor = this
-      while cursor
-        return false unless cursor.visible()
-        cursor = cursor.parent()
-
-        return true if cursor and cursor.element is document.body
-
-      # Bound not reached, meaning that the Element is not currently attached to the DOM.
-      return false
-
-    # Fires a named event, passing an optional _memo_ object to event handler functions. This must support
-    # common native events (exact list TBD), as well as custom events (in Prototype, custom events must have
-    # a prefix that ends with a colon).
-    #
-    # * eventName - name of event to trigger on the wrapped Element
-    # * memo - optional value assocated with the event; available as WrappedeEvent.memo in event handler functions (must
-    #   be null for native events). The memo, when provided, should be an object; it is an error if it is a string or other
-    #  non-object type..
-    #
-    # Returns true if the event fully executed, or false if the event was canceled.
-    trigger: (eventName, memo) ->
-      throw new Error "Attempt to trigger event with null event name" unless eventName?
-
-      unless (_.isNull memo) or (_.isObject memo) or (_.isUndefined memo)
-        throw new Error "Event memo may be null or an object, but not a simple type."
-
-      jqEvent = $.Event eventName
-
-      @$.trigger jqEvent, memo
-
-      # Not sure if this is sufficient to ensure that event was cancelled:
-      return jqEvent.isImmediatePropagationStopped()
-
-    # With no parameters, returns the current value of the element (which must be a form control element, such as `<input>` or
-    # `<textarea>`). With one parameter, updates the field's value, and returns the previous value. The underlying
-    # foundation is responsible for mapping this correctly based on the type of control element.
-    # TODO: Define behavior for multi-named elements, such as `<select>`.
-    #
-    # * newValue - (optional) new value for field
-    value: (newValue) ->
-      current = @$.val()
-
-      if arguments.length > 0
-        @$.val newValue
-
-      return current
-
-    # Returns true if a checkbox is checked
-    checked: ->
-      return @$.is(':checked')
-
-    # Stores or retrieves meta-data on the element. With one parameter, the current value for the name
-    # is returned (or undefined). With two parameters, the meta-data is updated and the previous value returned.
-    # For Prototype, the meta data is essentially empty (except, perhaps, for some internal keys used to store
-    # event handling information).  For jQuery, the meta data may be initialized from data- attributes.
-    #
-    # * name - name of meta-data value to store or retrieve
-    # * value - (optional) new value for meta-data
-    meta: (name, value) ->
-      current = @$.data name
-
-      if arguments.length > 1
-        @$.data name, value
-
-      return current
-
-    # Adds an event handler for one or more events.
-    #
-    # * events - one or more event names, separated by spaces
-    # * match - optional: CSS expression used as a filter; only events that bubble
-    #   up to the wrapped element from an originating element that matches the CSS expression
-    #   will invoke the handler.
-    # * handler - function invoked; the function is passed an `EventWrapper` object, and the
-    #   context (`this`) is the `ElementWrapper` for the matched element.
-    on: (events, match, handler) ->
-      exports.on @element, events, match, handler
-      return this
-
-    # Returns the text of the element (and its children).
-    text: -> @$.text()
-
-  # Wrapper around the `jqXHR` object
-  class ResponseWrapper
-
-    constructor: (@jqxhr, data) ->
-
-      @status = jqxhr.status
-      @statusText = jqxhr.statusText
-      @json = data # Mostly right?  Need a content type check?
-      @text = jqxhr.responseText
-
-    # Retrieves a response header by name
-    header: (name) ->
-      @jqxhr.getResponseHeader name
-
-  # Performs an asynchronous Ajax request, invoking callbacks when it completes.
-  #
-  # This is very low level; most code will want to go through the `t5/core/ajax` module instead,
-  # which adds better handling of exceptions and failures, and handles Tapestry's partial page
-  # render reponse keys.
-  #
-  # * options.method - "post", "get", etc., default: "post".
-  # * options.contentType - default "context "application/x-www-form-urlencoded"
-  # * options.parameters - optional, additional key/value pairs
-  # * options.success - handler to invoke on success. Passed the ResponseWrapper object.
-  #   Default does nothing.
-  # * options.failure - handler to invoke on failure (server responds with a non-2xx code).
-  #   Passed the response. Default will throw the exception
-  # * options.exception - handler to invoke when an exception occurs (often means the server is unavailable).
-  #   Passed the exception. Default will generate an exception message and throw an `Error`.
-  #   Note: not really supported under jQuery, a hold-over from Prototype.
-  ajaxRequest = (url, options = {}) ->
-
-    $.ajax
-      url: url
-      type: options.method?.toUpperCase() or "POST"
-      contentType: options.contentType
-      traditional: true
-      data: options.parameters
-      # jQuery doesn't have the equivalent of Protoype's onException
-      error: (jqXHR, textStatus, errorThrown) ->
-        message = "Request to #{url} failed with status #{textStatus}"
-        text = jqXHR.statusText
-        if not _.isEmpty text
-          message += " -- #{text}"
-        message += "."
-
-        if options.failure
-          options.failure (new ResponseWrapper jqXHR), message
-        else
-          throw new Error message
-
-        return
-
-      success: (data, textStatus, jqXHR) ->
-
-        options.success and options.success(new ResponseWrapper jqXHR, data)
-        return
-
-    return exports
-
-  triggerReflow = _.debounce (-> $(document).trigger events.document.reflow), 250
-
-  # The main export is a function that wraps a DOM element as an ElementWrapper; additional functions are attached as
-  # properties.
-  #
-  # * element - a DOM element, or a string id of a DOM element
-  #
-  # Returns the ElementWrapper, or null if no element with the id exists
-  exports = wrapElement = (element) ->
-    if _.isString element
-      element = document.getElementById element
-      return null unless element
-      return new ElementWrapper ($ element)
-    else
-      throw new Error "Attempt to wrap a null DOM element" unless element
-
-    # Assume the object is a DOM element, document or window; something that is compatible with the
-    # jQuery API (especially with respect to events).
-    new ElementWrapper ($ element)
-
-  _.extend exports,
-    wrap: wrapElement
-
-    # Escape's HTML markup in the string.
-    escapeHTML: _.escape
-
-    triggerReflow: triggerReflow
-
-    ajaxRequest: ajaxRequest
-
-    # Used to add an event handler to an element (possibly from elements below it in the hierarch).
-    #
-    # * selector - CSS selector used to select elements to attach handler to; alternately,
-    #   a single DOM element, or an array of DOM elements. The document is considered an element
-    #   for these purposes.
-    # * events - one or more event names, separated by spaces
-    # * match - optional: CSS expression used as a filter; only events that bubble
-    # * up to a selected element from an originating element that matches the CSS expression
-    #   will invoke the handler.
-    # * handler - function invoked; the function is passed an `EventWrapper` object, and the context (`this`)
-    #   is the `ElementWrapper` for the matched element
-    on: (selector, events, match, handler) ->
-      unless handler?
-        handler = match
-        match = null
-
-      onevent ($ selector), events, match, handler
-      return
-
-    # onDocument() is used to add an event handler to the document object; this is used
-    # for global (or default) handlers.
-    onDocument: (events, match, handler) ->
-      exports.on document, events, match, handler
-
-    # Returns a wrapped version of the document.body element. Because all Tapestry JavaScript occurs
-    # inside a block at the end of the document, inside the `<body`> element, it is assumed that
-    # it is always safe to get the body.
-    body: -> wrapElement document.body
-
-  $(window).on "resize", exports.triggerReflow
-
-  return exports
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/56a24f59/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-prototype.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-prototype.coffee b/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-prototype.coffee
deleted file mode 100644
index db88bbb..0000000
--- a/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom-prototype.coffee
+++ /dev/null
@@ -1,608 +0,0 @@
-# Copyright 2012-2013 The Apache Software Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http:#www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# ## t5/core/dom (prototype)
-#
-# This is the abstraction layer that allows the majority of components to operate without caring whether the
-# underlying infrastructure framework is Prototype, jQuery, or something else.  This implementation is specific
-# to Prototype, but Tapestry can be adapted to any infrastructure framework by re-implementing this module.
-#
-# The abstraction layer has a number of disadvantages:
-#
-# * It adds a number of layers of wrapper around the infrastructure framework objects
-# * It is leaky; some behaviors will vary slightly based on the active infrastructure framework
-# * The abstraction is alien to both Prototype and jQuery developers; it mixes some ideas from both
-# * It is much less powerful or expressive than either infrastructure framework used directly
-#
-# It is quite concievable that some components will require direct access to the infrastructure framework, especially
-# those that are wrappers around third party libraries or plugins; however many simple components may need no more than
-# the abstract layer and gain the valuable benefit of not caring about the infrastructure framework.
-#
-# Changes to this library should be coordinated with the jQuery version.
-define ["underscore", "./utils", "./events", "prototype"], (_, utils, events) ->
-
-  # Save a local reference to Prototype.$ ... see notes about some challenges using Prototype, jQuery,
-  # and RequireJS together, here: https://github.com/jrburke/requirejs/issues/534
-  $ = window.$
-
-  # Fires a native event; something that Prototype does not normally do.
-  # Returns true if the event completed normally, false if it was canceled.
-  fireNativeEvent = (element, eventName) ->
-    if document.createEventObject
-      # IE support:
-      event = document.createEventObject()
-      return element.fireEvent "on#{eventName}", event
-
-    # Everyone else:
-    event = document.createEvent "HTMLEvents"
-    event.initEvent eventName, true, true
-    element.dispatchEvent event
-    return not event.defaultPrevented
-
-  # Converts content (provided to `ElementWrapper.update()` or `append()`) into an appropriate type. This
-  # primarily exists to validate the value, and to "unpack" an ElementWrapper into a DOM element.
-  convertContent = (content) ->
-    if _.isString content
-      return content
-
-    if _.isElement content
-      return content
-
-    if content instanceof ElementWrapper
-      return content.element
-
-    throw new Error "Provided value <#{content}> is not valid as DOM element content."
-
-  # Currently don't want to rely on Scriptaculous, since our needs are pretty minor.
-  animate = (element, styleName, initialValue, finalValue, duration, callbacks) ->
-    styles = {}
-    range = finalValue - initialValue
-    initialTime = Date.now()
-    first = true
-    animator = ->
-      elapsed = Date.now() - initialTime
-      if elapsed >= duration
-        styles[styleName] = finalValue
-        element.setStyle styles
-        window.clearInterval timeoutID
-        triggerReflow()
-        callbacks.oncomplete and callbacks.oncomplete()
-
-      # TODO: Add an easein/easeout function
-
-      newValue = initial + range * (elapsed / duration)
-
-      element.setStyle styles
-
-      if first
-        callbacks.onstart and callbacks.onstart()
-        first = false
-
-    timeoutID = window.setInterval animator
-
-    styles[styleName] = initialValue
-    element.setStyle styles
-
-  # Generic view of an DOM event that is passed to a handler function.
-  #
-  # Properties:
-  #
-  # * nativeEvent - the native Event object, which may provide additional information.
-  # * memo - the object passed to `ElementWrapper.trigger()`.
-  # * type - the name of the event that was triggered.
-  # * char - the character value of the pressed key, if a printable character, as a string.
-  # * key -The key value of the pressed key. This is the same as the `char` property for printable keys,
-  #  or a key name for others.
-  class EventWrapper
-
-    constructor: (event) ->
-      @nativeEvent = event
-
-      # This is to satisfy YUICompressor which doesn't seem to like 'char', even
-      # though it doesn't appear to be a reserved word.
-      this[name] = event[name] for name in ["memo", "type", "char", "key"]
-
-    # Stops the event which prevents further propagation of the DOM event,
-    # as well as DOM event bubbling.
-    stop: ->
-      @nativeEvent.stop()
-
-  # Interface between the dom's event model, and Prototype's.
-  #
-  # * elements - array of DOM elements (or the document object)
-  # * eventNames - array of event names
-  # * match - selector to match bubbled elements, or null
-  # * handler - event handler function to invoke; it will be passed an `EventWrapper` instance as the first parameter,
-  #   and the memo as the second parameter. `this` will be the `ElementWrapper` for the matched element.
-  #
-  # Event handlers may return false to stop event propogation; this prevents an event from bubbling up, and
-  # prevents any browser default behavior from triggering.  This is often easier than accepting the `EventWrapper`
-  # object as the first parameter and invoking `stop()`.
-
-  onevent = (elements, eventNames, match, handler) ->
-      throw new Error "No event handler was provided." unless handler?
-
-      wrapped = (prototypeEvent) ->
-        # Set `this` to be the matched ElementWrapper, rather than the element on which the event is observed
-        # (which is often further up the hierarchy).
-        elementWrapper = new ElementWrapper prototypeEvent.findElement()
-        eventWrapper = new EventWrapper prototypeEvent
-
-        result = handler.call elementWrapper, eventWrapper, eventWrapper.memo
-
-        # If an event handler returns exactly false, then stop the event.
-        if result is false
-          prototypeEvent.stop()
-
-        return
-
-      for element in elements
-        for eventName in eventNames
-          Event.on element, eventName, match, wrapped
-
-      return
-
-  # Wraps a DOM element, providing some common behaviors.
-  # Exposes the original element as property `element`.
-  class ElementWrapper
-
-  # Passed the DOM Element
-    constructor: (@element) ->
-
-    toString: ->
-      markup = @element.outerHTML
-
-      "ElementWrapper[#{markup.substring 0, (markup.indexOf ">") + 1}]"
-
-    # Hides the wrapped element, setting its display to 'none'.
-    hide: ->
-      @element.hide()
-
-      triggerReflow()
-
-      return this
-
-    # Displays the wrapped element if hidden.
-    show: ->
-      @element.show()
-
-      triggerReflow()
-
-      return this
-
-    # Gets or sets a CSS property.
-    css: (name, value) ->
-
-      if arguments.length is 1
-        return @element.getStyle name
-
-      @element.setStyle name: value
-
-      return this
-
-    # Returns the offset of the object relative to the document. The returned object has
-    # keys `top`' and `left`'.
-    offset: ->
-      @element.viewportOffset()
-
-    # Removes the wrapped element from the DOM.  It can later be re-attached.
-    remove: ->
-      @element.remove()
-
-      triggerReflow()
-
-      return this
-
-    # Reads or updates an attribute. With one argument, returns the current value
-    # of the attribute. With two arguments, updates the attribute's value, and returns
-    # the previous value. Setting an attribute to null is the same as removing it.
-    #
-    # Alternately, the first attribute can be an object in which case all the keys
-    # and values of the object are applied as attributes, and this `ElementWrapper` is returned.
-    #
-    # * name - the attribute to read or update, or an object of keys and values
-    # * value - (optional) the new value for the attribute
-    attribute: (name, value) ->
-
-      if _.isObject name
-        for name, value of name
-            @element.writeAttribute name, value
-        return this
-
-      current = @element.readAttribute name
-      if arguments.length > 1
-        @element.writeAttribute name, value
-
-      return current
-
-    # Moves the cursor to the field.
-    focus: ->
-      @element.focus()
-
-      return this
-
-    # Returns true if the element has the indicated class name, false otherwise.
-    hasClass: (name) ->
-      @element.hasClassName name
-
-    # Removes the class name from the element.
-    removeClass: (name) ->
-      @element.removeClassName name
-
-      return this
-
-    # Adds the class name to the element.
-    addClass: (name) ->
-      @element.addClassName name
-
-      return this
-
-    # Updates this element with new content, replacing any old content. The new content may be HTML text, or a DOM
-    # element, or null (to remove the body of the element). Passing null will remove all content.
-    update: (content) ->
-      @element.update (content and convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Appends new content (Element, ElementWrapper, or HTML markup string) to the body of the element.
-    append: (content) ->
-      @element.insert bottom: (convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Prepends new content (Element, ElementWrapper, or HTML markup string) to the body of the element.
-    prepend: (content) ->
-      @element.insert top: (convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Inserts new content (Element, ElementWrapper, or HTML markup string) into the DOM immediately before
-    # this ElementWrapper's element.
-    insertBefore: (content) ->
-      @element.insert before: (convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Inserts new content (Element, ElementWrapper, or HTML markup string) into the DOM immediately after
-    # this ElementWrapper's element.
-    insertAfter: (content) ->
-      @element.insert after: (convertContent content)
-
-      triggerReflow()
-
-      return this
-
-    # Runs an animation to fade-in the element over the specified duration. The element may be hidden (via `hide()`)
-    # initially, and will be made visible (with initial opacity 0, which will increase over time) when the animation
-    # starts.
-    #
-    # * duration - animation duration time, in seconds
-    # * callback - function invoked after the animation is complete
-    fadeIn: (duration, callback) ->
-      animate @element, "opacity", 0, 1, duration * 1000,
-        onstart: => @element.show()
-        oncomplete: callback
-
-      return this
-
-    # Runs an animation to fade out an element over the specified duration. The element should already
-    # be visible and fully opaque.
-    #
-    # * duration - animation duration time, in seconds
-    # * callback - function invoked after the animation is complete
-    fadeOut: (duration, callback) ->
-      animate @element, "opacity", 1, 0, duration * 1000,
-        oncomplete: callback
-
-      return this
-
-    # Finds the first child element that matches the CSS selector, wrapped as an ElementWrapper.
-    # Returns null if not found.
-    findFirst: (selector) ->
-      match = @element.down selector
-
-      # Prototype returns undefined if not found, we want to return null.
-      if match
-        new ElementWrapper match
-      else
-        return null
-
-    # Finds _all_ child elements matching the CSS selector, returning them
-    # as an array of ElementWrappers.
-    find: (selector) ->
-      matches = @element.select selector
-
-      _.map matches, (e) -> new ElementWrapper e
-
-    # Find the first container element that matches the selector (wrapped as an ElementWrapper),
-    # or returns null.
-    findParent: (selector) ->
-      parent = @element.up selector
-
-      return null unless parent
-
-      new ElementWrapper parent
-
-    # Returns this ElementWrapper if it matches the selector; otherwise, returns the first container element (as an ElementWrapper)
-    # that matches the selector. Returns null if no container element matches.
-    closest: (selector) ->
-
-      if @element.match selector
-        return this
-
-      return @findParent selector
-
-    # Returns an ElementWrapper for this element's immediate containing element.
-    # Returns null if this element has no parent (either because this element is the document object, or
-    # because this element is not yet attached to the DOM).
-    parent: ->
-      parent = @element.parentNode
-
-      return null unless parent
-
-      new ElementWrapper parent
-
-    # Returns true if this element is visible, false otherwise. This does not check to see if all containers of the
-    # element are visible.
-    visible: ->
-      @element.visible()
-
-    # Returns true if this element is visible, and all parent elements are also visible, up to the document body.
-    deepVisible: ->
-      cursor = this
-      while cursor
-        return false unless cursor.visible()
-        cursor = cursor.parent()
-
-        return true if cursor and cursor.element is document.body
-
-      # Bound not reached, meaning that the Element is not currently attached to the DOM.
-      return false
-
-    # Fires a named event, passing an optional _memo_ object to event handler functions. This must support
-    # common native events (exact list TBD), as well as custom events (in Prototype, custom events must have
-    # a prefix that ends with a colon).
-    #
-    # * eventName - name of event to trigger on the wrapped Element
-    # * memo - optional value assocated with the event; available as WrappedeEvent.memo in event handler functions (must
-    #   be null for native events). The memo, when provided, should be an object; it is an error if it is a string or other
-    #  non-object type..
-    #
-    # Returns true if the event fully executed, or false if the event was canceled.
-    trigger: (eventName, memo) ->
-      throw new Error "Attempt to trigger event with null event name" unless eventName?
-
-      unless (_.isNull memo) or (_.isObject memo) or (_.isUndefined memo)
-        throw new Error "Event memo may be null or an object, but not a simple type."
-
-      if (eventName.indexOf ':') > 0
-        # Custom event is supported directly by Prototype:
-        event = @element.fire eventName, memo
-        return not event.defaultPrevented
-
-      # Native events take some extra work:
-      if memo
-        throw new Error "Memo must be null when triggering a native event"
-
-      fireNativeEvent @element, eventName
-
-    # With no parameters, returns the current value of the element (which must be a form control element, such as `<input>` or
-    # `<textarea>`). With one parameter, updates the field's value, and returns the previous value. The underlying
-    # foundation is responsible for mapping this correctly based on the type of control element.
-    # TODO: Define behavior for multi-named elements, such as `<select>`.
-    #
-    # * newValue - (optional) new value for field
-    value: (newValue) ->
-      current = @element.getValue()
-
-      if arguments.length > 0
-        @element.setValue newValue
-
-      return current
-      
-    # Returns true if a checkbox is checked
-    checked: ->
-      return @element.checked
-
-    # Stores or retrieves meta-data on the element. With one parameter, the current value for the name
-    # is returned (or undefined). With two parameters, the meta-data is updated and the previous value returned.
-    # For Prototype, the meta data is essentially empty (except, perhaps, for some internal keys used to store
-    # event handling information).  For jQuery, the meta data may be initialized from data- attributes.
-    #
-    # * name - name of meta-data value to store or retrieve
-    # * value - (optional) new value for meta-data
-    meta: (name, value) ->
-      current = @element.retrieve name
-
-      if arguments.length > 1
-        @element.store name, value
-
-      return current
-
-    # Adds an event handler for one or more events.
-    #
-    # * events - one or more event names, separated by spaces
-    # * match - optional: CSS expression used as a filter; only events that bubble
-    #   up to the wrapped element from an originating element that matches the CSS expression
-    #   will invoke the handler.
-    # * handler - function invoked; the function is passed an `EventWrapper` object, and the
-    #   context (`this`) is the `ElementWrapper` for the matched element.
-    on: (events, match, handler) ->
-      exports.on @element, events, match, handler
-      return this
-
-    # Returns the text of the element (and its children).
-    text: -> @element.textContent or @element.innerText
-
-  # converts a selector to an array of DOM elements
-  parseSelectorToElements = (selector) ->
-    if _.isString selector
-      return $$ selector
-
-    # Array is assumed to be array of DOM elements
-    if _.isArray selector
-      return selector
-
-    # Assume its a single DOM element
-
-    [selector]
-
-  # Wrapper around the Prototype `Ajax.Response` object
-  class ResponseWrapper
-
-    constructor: (@res) ->
-
-      @status = res.status
-      @statusText = res.statusText
-      @json = res.responseJSON
-      @text = res.responseText
-
-    # Retrieves a response header by name
-    header: (name) ->
-      @res.getHeader name
-
-  # Performs an asynchronous Ajax request, invoking callbacks when it completes.
-  #
-  # This is very low level; most code will want to go through the `t5/core/ajax` module instead,
-  # which adds better handling of exceptions and failures, and handles Tapestry's partial page
-  # render reponse keys.
-  #
-  # * options.method - "post", "get", etc., default: "post".
-  #   Adds a "_method" parameter and uses "post" to handle "delete", etc.
-  # * options.contentType - default "context "application/x-www-form-urlencoded"
-  # * options.parameters - optional, additional key/value pairs
-  # * options.success - handler to invoke on success, passed the ResponseWrapper
-  #   Default does nothing.
-  # * options.failure - handler to invoke on failure (server responds with a non-2xx code),
-  #   Passed the ResponseWrapper and an error message. Defaults throws an Error.
-  # * options.exception - handler to invoke when an exception occurs (often means the server is unavailable).
-  #   Passed the exception. Default re-throws the underlying exception.
-  #
-  # Returns the module's exports
-  ajaxRequest = (url, options = {}) ->
-    finalOptions =
-      method: options.method or "post"
-      contentType: options.contentType or "application/x-www-form-urlencoded"
-      parameters: options.parameters or {}
-      onException: (ajaxRequest, exception) ->
-        if options.exception
-          options.exception exception
-        else
-          throw exception
-
-        return
-
-      onFailure: (response) ->
-        message = "Request to #{url} failed with status #{response.getStatus()}"
-        text = response.getStatusText()
-        if not _.isEmpty text
-          message += " -- #{text}"
-        message += "."
-
-        if options.failure
-          options.failure (new ResponseWrapper response), message
-        else
-          throw new Error message
-
-        return
-
-      onSuccess: (response) ->
-
-        # Prototype treats status == 0 as success, even though it may
-        # indicate that the server didn't respond.
-        if (not response.getStatus()) or (not response.request.success())
-          finalOptions.onFailure(new ResponseWrapper response)
-          return
-
-        # Tapestry 5.3 includes lots more exception catching ... that just got in the way
-        # of identifying the source of problems.  That's been stripped out.
-        options.success and options.success(new ResponseWrapper response)
-        return
-
-    new Ajax.Request(url, finalOptions)
-
-    return exports
-
-  # The main export is a function that wraps a DOM element as an ElementWrapper; additional functions are attached as
-  # properties.
-  #
-  # * element - a DOM element, or a string id of a DOM element
-  #
-  # Returns the ElementWrapper, or null if no element with the id exists
-  exports = wrapElement = (element) ->
-    if _.isString element
-      element = $ element
-      return null unless element
-    else
-      throw new Error "Attempt to wrap a null DOM element" unless element
-
-    # Assume the object is a DOM element, document or window; something that is compatible with the
-    # Prototype API (especially with respect to events).
-    new ElementWrapper element
-
-  triggerReflow = _.debounce (-> $(document).fire events.document.reflow), 250
-
-  _.extend exports,
-    wrap: wrapElement
-
-    # Escape's HTML markup in the string.
-    escapeHTML: (str) -> str.escapeHTML()
-
-    triggerReflow: triggerReflow
-
-    ajaxRequest: ajaxRequest
-
-    # Used to add an event handler to an element (possibly from elements below it in the hierarch).
-    #
-    # * selector - CSS selector used to select elements to attach handler to; alternately,
-    #   a single DOM element, or an array of DOM elements. The document is considered an element
-    #   for these purposes.
-    # * events - one or more event names, separated by spaces
-    # * match - optional: CSS expression used as a filter; only events that bubble
-    # * up to a selected element from an originating element that matches the CSS expression
-    #   will invoke the handler.
-    # * handler - function invoked; the function is passed an `EventWrapper` object, and the context (`this`)
-    #   is the `ElementWrapper` for the matched element
-    on: (selector, events, match, handler) ->
-      unless handler?
-        handler = match
-        match = null
-
-      elements = parseSelectorToElements selector
-
-      onevent elements, (utils.split events), match, handler
-      return
-
-    # onDocument() is used to add an event handler to the document object; this is used
-    # for global (or default) handlers.
-    onDocument: (events, match, handler) ->
-      exports.on document, events, match, handler
-
-    # Returns a wrapped version of the document.body element. Because all Tapestry JavaScript occurs
-    # inside a block at the end of the document, inside the `<body`> element, it is assumed that
-    # it is always safe to get the body.
-    body: -> wrapElement document.body
-
-  Event.observe window, "resize", triggerReflow
-
-  return exports
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/56a24f59/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom.coffee b/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom.coffee
new file mode 100644
index 0000000..3eb33c1
--- /dev/null
+++ b/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom.coffee
@@ -0,0 +1,895 @@
+# Copyright 2012-2013 The Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http:#www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# ## t5/core/dom
+#
+# This is the abstraction layer that allows the majority of components to operate without caring whether the
+# underlying infrastructure framework is Prototype, jQuery, or something else.
+#
+# The abstraction layer has a number of disadvantages:
+#
+# * It adds a number of layers of wrapper around the infrastructure framework objects
+# * It is leaky; some behaviors will vary slightly based on the active infrastructure framework
+# * The abstraction is alien to both Prototype and jQuery developers; it mixes some ideas from both
+# * It is much less powerful or expressive than either infrastructure framework used directly
+#
+# It is quite concievable that some components will require direct access to the infrastructure framework, especially
+# those that are wrappers around third party libraries or plugins; however many simple components may need no more than
+# the abstract layer and gain the valuable benefit of not caring about the infrastructure framework.
+
+define ["underscore", "./utils", "./events"
+#if prototype
+  , "prototype"
+#elseif jquery
+  , "jquery"
+#endif
+  ],
+(_, utils, events
+#if jquery
+  , $
+#endif
+  ) ->
+
+#if prototype
+  # Save a local reference to Prototype.$ ... see notes about some challenges using Prototype, jQuery,
+  # and RequireJS together, here: https://github.com/jrburke/requirejs/issues/534
+  $ = window.$
+
+  # Fires a native event; something that Prototype does not normally do.
+  # Returns true if the event completed normally, false if it was canceled.
+  fireNativeEvent = (element, eventName) ->
+    if document.createEventObject
+      # IE support:
+      event = document.createEventObject()
+      return element.fireEvent "on#{eventName}", event
+
+    # Everyone else:
+    event = document.createEvent "HTMLEvents"
+    event.initEvent eventName, true, true
+    element.dispatchEvent event
+    return not event.defaultPrevented
+
+  # Currently don't want to rely on Scriptaculous, since our needs are pretty minor.
+  animate = (element, styleName, initialValue, finalValue, duration, callbacks) ->
+    styles = {}
+    range = finalValue - initialValue
+    initialTime = Date.now()
+    first = true
+    animator = ->
+      elapsed = Date.now() - initialTime
+      if elapsed >= duration
+        styles[styleName] = finalValue
+        element.setStyle styles
+        window.clearInterval timeoutID
+        triggerReflow()
+        callbacks.oncomplete and callbacks.oncomplete()
+
+      # TODO: Add an easein/easeout function
+
+      newValue = initial + range * (elapsed / duration)
+
+      element.setStyle styles
+
+      if first
+        callbacks.onstart and callbacks.onstart()
+        first = false
+
+    timeoutID = window.setInterval animator
+
+    styles[styleName] = initialValue
+    element.setStyle styles
+
+  # converts a selector to an array of DOM elements
+  parseSelectorToElements = (selector) ->
+    if _.isString selector
+      return $$ selector
+
+    # Array is assumed to be array of DOM elements
+    if _.isArray selector
+      return selector
+
+    # Assume its a single DOM element
+
+    [selector]
+#endif
+
+  # Converts content (provided to `ElementWrapper.update()` or `append()`) into an appropriate type. This
+  # primarily exists to validate the value, and to "unpack" an ElementWrapper into a DOM element.
+  convertContent = (content) ->
+    if _.isString content
+      return content
+
+    if _.isElement content
+      return content
+
+    if content instanceof ElementWrapper
+#if jquery
+      return content.$
+#elseif prototype
+      return content.element
+#endif
+
+    throw new Error "Provided value <#{content}> is not valid as DOM element content."
+
+  # Generic view of an DOM event that is passed to a handler function.
+  #
+  # Properties:
+  #
+  # * nativeEvent - the native Event object, which may provide additional information.
+  # * memo - the object passed to `ElementWrapper.trigger()`.
+  # * type - the name of the event that was triggered.
+  # * char - the character value of the pressed key, if a printable character, as a string.
+  # * key -The key value of the pressed key. This is the same as the `char` property for printable keys,
+  #  or a key name for others.
+  class EventWrapper
+
+#if jquery
+    constructor: (event, memo) ->
+      @nativeEvent = event
+      @memo = memo
+#elseif prototype
+    constructor: (event) ->
+      @nativeEvent = event
+      @memo = event.memo
+#endif
+      # This is to satisfy YUICompressor which doesn't seem to like 'char', even
+      # though it doesn't appear to be a reserved word.
+      this[name] = event[name] for name in ["type", "char", "key"]
+
+    # Stops the event which prevents further propagation of the DOM event,
+    # as well as DOM event bubbling.
+    stop: ->
+#if jquery
+      @nativeEvent.stopImmediatePropagation()
+      @nativeEvent.preventDefault()
+#elseif prototype
+      @nativeEvent.stop()
+#endif
+
+#if jquery
+  # Interface between the dom's event model, and jQuery's.
+  #
+  # * jqueryObject - jQuery wrapper around one or more DOM elements
+  # * eventNames - space-separated list of event names
+  # * match - selector to match bubbled elements, or null
+  # * handler - event handler function to invoke; it will be passed an `EventWrapper` instance as the first parameter,
+  #   and the memo as the second parameter. `this` will be the `ElementWrapper` for the matched element.
+  #
+  # Event handlers may return false to stop event propogation; this prevents an event from bubbling up, and
+  # prevents any browser default behavior from triggering.  This is often easier than accepting the `EventWrapper`
+  # object as the first parameter and invoking `stop()`.
+
+  onevent = (jqueryObject, eventNames, match, handler) ->
+    throw new Error "No event handler was provided." unless handler?
+
+    wrapped = (jqueryEvent, memo) ->
+      # Set `this` to be the matched ElementWrapper, rather than the element on which the event is observed
+      # (which is often further up the hierarchy).
+      elementWrapper = new ElementWrapper $(jqueryEvent.target)
+      eventWrapper = new EventWrapper jqueryEvent, memo
+
+      result = handler.call elementWrapper, eventWrapper, memo
+
+      # If an event handler returns exactly false, then stop the event.
+      if result is false
+        eventWrapper.stop()
+
+      return
+
+    jqueryObject.on eventNames, match, wrapped
+
+    return
+#elseif prototype
+  # Interface between the dom's event model, and Prototype's.
+  #
+  # * elements - array of DOM elements (or the document object)
+  # * eventNames - array of event names
+  # * match - selector to match bubbled elements, or null
+  # * handler - event handler function to invoke; it will be passed an `EventWrapper` instance as the first parameter,
+  #   and the memo as the second parameter. `this` will be the `ElementWrapper` for the matched element.
+  #
+  # Event handlers may return false to stop event propogation; this prevents an event from bubbling up, and
+  # prevents any browser default behavior from triggering.  This is often easier than accepting the `EventWrapper`
+  # object as the first parameter and invoking `stop()`.
+
+  onevent = (elements, eventNames, match, handler) ->
+      throw new Error "No event handler was provided." unless handler?
+
+      wrapped = (prototypeEvent) ->
+        # Set `this` to be the matched ElementWrapper, rather than the element on which the event is observed
+        # (which is often further up the hierarchy).
+        elementWrapper = new ElementWrapper prototypeEvent.findElement()
+        eventWrapper = new EventWrapper prototypeEvent
+
+        result = handler.call elementWrapper, eventWrapper, eventWrapper.memo
+
+        # If an event handler returns exactly false, then stop the event.
+        if result is false
+          prototypeEvent.stop()
+
+        return
+
+      for element in elements
+        for eventName in eventNames
+          Event.on element, eventName, match, wrapped
+
+      return
+#endif
+
+  # Wraps a DOM element, providing some common behaviors.
+  # Exposes the DOM element as property `element`.
+  class ElementWrapper
+
+#if jquery
+    # Passed the jQuery object
+    constructor: (query) ->
+      @$ = query
+      @element = query[0]
+#elseif prototype
+    constructor: (@element) ->
+#endif
+
+    # Some coders would use some JavaScript cleverness to automate more of the mapping from the ElementWrapper API
+    # to the jQuery API, but that eliminates a chance to write some very necessary documentation.
+
+    toString: ->
+      markup = @element.outerHTML
+
+      "ElementWrapper[#{markup.substring 0, (markup.indexOf ">") + 1}]"
+
+    # Hides the wrapped element, setting its display to 'none'.
+    hide: ->
+#if jquery
+      @$.hide()
+#elseif prototype
+      @element.hide()
+#endif
+
+      triggerReflow()
+
+      return this
+
+    # Displays the wrapped element if hidden.
+    show: ->
+#if jquery
+      @$.show()
+#elseif prototype
+      @element.show()
+#endif
+      triggerReflow()
+
+      return this
+
+    # Gets or sets a CSS property. jQuery provides a lot of mapping of names to canonical names.
+    css: (name, value) ->
+
+      if arguments.length is 1
+#if jquery
+        return @$.css name
+#elseif prototype
+        return @element.getStyle name
+#endif
+
+#if jquery
+      @$.css name, value
+#elseif prototype
+      @element.setStyle name: value
+#endif
+
+      return this
+
+    # Returns the offset of the object relative to the document. The returned object has
+    # keys `top`' and `left`'.
+    offset: ->
+#if jquery
+      @$.offset()
+#elseif prototype
+      @element.viewportOffset()
+#endif
+
+    # Removes the wrapped element from the DOM.  It can later be re-attached.
+    remove: ->
+#if jquery
+      @$.detach()
+#elseif prototype
+      @element.remove()
+#endif
+
+      triggerReflow()
+
+      return this
+
+    # Reads or updates an attribute. With one argument, returns the current value
+    # of the attribute. With two arguments, updates the attribute's value, and returns
+    # the previous value. Setting an attribute to null is the same as removing it.
+    #
+    # Alternately, the first attribute can be an object in which case all the keys
+    # and values of the object are applied as attributes, and this `ElementWrapper` is returned.
+    #
+    # * name - the attribute to read or update, or an object of keys and values
+    # * value - (optional) the new value for the attribute
+    attribute: (name, value) ->
+
+      if _.isObject name
+#if jquery
+        @$.attr name
+#elseif prototype
+        for name, value of name
+          @element.writeAttribute name, value
+#endif
+        return this
+
+#if jquery
+      current = @$.attr name
+      if arguments.length > 1
+        @$.attr name, value
+#elseif prototype
+      current = @element.readAttribute name
+      if arguments.length > 1
+        @element.writeAttribute name, value
+#endif
+
+      return current
+
+    # Moves the cursor to the field.
+    focus: ->
+#if jquery
+      @$.focus()
+#elseif prototype
+      @element.focus()
+#endif
+
+      return this
+
+    # Returns true if the element has the indicated class name, false otherwise.
+    hasClass: (name) ->
+#if jquery
+      @$.hasClass name
+#elseif prototype
+      @element.hasClassName name
+#endif
+
+    # Removes the class name from the element.
+    removeClass: (name) ->
+#if jquery
+      @$.removeClass name
+#elseif prototype
+      @element.removeClassName name
+#endif
+
+      return this
+
+    # Adds the class name to the element.
+    addClass: (name) ->
+#if jquery
+      @$.addClass name
+#elseif prototype
+      @element.addClassName name
+#endif
+
+      return this
+
+    # Updates this element with new content, replacing any old content. The new content may be HTML text, or a DOM
+    # element, or an ElementWrapper, or null (to remove the body of the element).
+    update: (content) ->
+#if jquery
+      @$.empty()
+
+      if content
+        @$.append (convertContent content)
+#elseif prototype
+      @element.update (content and convertContent content)
+#endif
+
+      triggerReflow()
+
+      return this
+
+    # Appends new content (Element, ElementWrapper, or HTML markup string) to the body of the element.
+    append: (content) ->
+#if jquery
+      @$.append (convertContent content)
+#elseif prototype
+      @element.insert bottom: (convertContent content)
+#endif
+
+      triggerReflow()
+
+      return this
+
+    # Prepends new content (Element, ElementWrapper, or HTML markup string) to the body of the element.
+    prepend: (content) ->
+#if jquery
+      @$.prepend (convertContent content)
+#elseif prototype
+      @element.insert top: (convertContent content)
+#endif
+
+      triggerReflow()
+
+      return this
+
+    # Inserts new content (Element, ElementWrapper, or HTML markup string) into the DOM immediately before
+    # this ElementWrapper's element.
+    insertBefore: (content) ->
+#if jquery
+      @$.before (convertContent content)
+#elseif prototype
+      @element.insert before: (convertContent content)
+#endif
+
+      triggerReflow()
+
+      return this
+
+    # Inserts new content (Element, ElementWrapper, or HTML markup string) into the DOM immediately after
+    # this ElementWrapper's element.
+    insertAfter: (content) ->
+#if jquery
+      @$.after (convertContent content)
+#elseif prototype
+      @element.insert after: (convertContent content)
+#endif
+
+      triggerReflow()
+
+      return this
+
+    # Runs an animation to fade-in the element over the specified duration.
+    #
+    # * duration - animation duration time, in seconds
+    # * callback - function invoked after the animation is complete
+    fadeIn: (duration, callback) ->
+#if jquery
+      @$.fadeIn duration * 1000, ->
+        triggerReflow()
+        callback and callback()
+#elseif prototype
+      animate @element, "opacity", 0, 1, duration * 1000,
+        onstart: => @element.show()
+        oncomplete: callback
+#endif
+
+      return this
+
+    # Runs an animation to fade out an element over the specified duration. The element should already
+    # be visible and fully opaque.
+    #
+    # * duration - animation duration time, in seconds
+    # * callback - function invoked after the animation is complete
+    fadeOut: (duration, callback) ->
+#if jquery
+      @$.fadeOut duration * 1000, ->
+        triggerReflow()
+        callback and callback()
+#elseif prototype
+      animate @element, "opacity", 1, 0, duration * 1000,
+        oncomplete: callback
+#endif
+
+      return this
+
+    # Finds the first child element that matches the CSS selector, wrapped as an ElementWrapper.
+    # Returns null if not found.
+    findFirst: (selector) ->
+#if jquery
+      match = @$.find selector
+
+      if match.length
+        # At least one element was matched, just keep the first
+        new ElementWrapper match.first()
+#elseif prototype
+      match = @element.down selector
+
+      # Prototype returns undefined if not found, we want to return null.
+      if match
+        new ElementWrapper match
+#endif
+      else
+        return null
+
+    # Finds _all_ child elements matching the CSS selector, returning them
+    # as an array of ElementWrappers.
+    find: (selector) ->
+#if jquery
+      matches = @$.find selector
+
+      return [] if matches.length is 0
+
+      for i in [0..(matches.length - 1)]
+        new ElementWrapper matches.eq i
+#elseif prototype
+      matches = @element.select selector
+
+      _.map matches, (e) -> new ElementWrapper e
+#endif
+
+    # Find the first container element that matches the selector (wrapped as an ElementWrapper),
+    # or returns null.
+    findParent: (selector) ->
+#if jquery
+      parents = @$.parents selector
+
+      return null unless parents.length
+
+      new ElementWrapper parents.eq(0)
+#elseif prototype
+      parent = @element.up selector
+
+      return null unless parent
+
+      new ElementWrapper parent
+#endif
+
+    # Returns this ElementWrapper if it matches the selector; otherwise, returns the first container element (as an ElementWrapper)
+    # that matches the selector. Returns null if no container element matches.
+    closest: (selector) ->
+#if jquery
+      match = @$.closest selector
+
+      switch
+        when match.length is 0 then return null
+        when match[0] is @element then return this
+        else return new ElementWrapper match
+#elseif prototype
+      if @element.match selector
+        return this
+
+      return @findParent selector
+#endif
+
+    # Returns an ElementWrapper for this element's containing element.
+    # Returns null if this element has no parent (either because this element is the document object, or
+    # because this element is not yet attached to the DOM).
+    parent: ->
+#if jquery
+      parent = @$.parent()
+
+      return null unless parent.length
+#elseif prototype
+      parent = @element.parentNode
+
+      return null unless parent
+#endif
+      new ElementWrapper parent
+
+    # Returns true if this element is visible, false otherwise. This does not check to see if all containers of the
+    # element are visible.
+    visible: ->
+#if jquery
+      @$.css("display") isnt "none"
+#elseif prototype
+      @element.visible()
+#endif
+
+    # Returns true if this element is visible, and all parent elements are also visible, up to the document body.
+    deepVisible: ->
+      cursor = this
+      while cursor
+        return false unless cursor.visible()
+        cursor = cursor.parent()
+
+        return true if cursor and cursor.element is document.body
+
+      # Bound not reached, meaning that the Element is not currently attached to the DOM.
+      return false
+
+    # Fires a named event, passing an optional _memo_ object to event handler functions. This must support
+    # common native events (exact list TBD), as well as custom events (in Prototype, custom events must have
+    # a prefix that ends with a colon).
+    #
+    # * eventName - name of event to trigger on the wrapped Element
+    # * memo - optional value assocated with the event; available as WrappedeEvent.memo in event handler functions (must
+    #   be null for native events). The memo, when provided, should be an object; it is an error if it is a string or other
+    #  non-object type..
+    #
+    # Returns true if the event fully executed, or false if the event was canceled.
+    trigger: (eventName, memo) ->
+      throw new Error "Attempt to trigger event with null event name" unless eventName?
+
+      unless (_.isNull memo) or (_.isObject memo) or (_.isUndefined memo)
+        throw new Error "Event memo may be null or an object, but not a simple type."
+
+#if jquery
+      jqEvent = $.Event eventName
+
+      @$.trigger jqEvent, memo
+
+      # Not sure if this is sufficient to ensure that event was cancelled:
+      return jqEvent.isImmediatePropagationStopped()
+#elseif prototype
+      if (eventName.indexOf ':') > 0
+        # Custom event is supported directly by Prototype:
+        event = @element.fire eventName, memo
+        return not event.defaultPrevented
+
+      # Native events take some extra work:
+      if memo
+        throw new Error "Memo must be null when triggering a native event"
+
+      fireNativeEvent @element, eventName
+#endif
+
+    # With no parameters, returns the current value of the element (which must be a form control element, such as `<input>` or
+    # `<textarea>`). With one parameter, updates the field's value, and returns the previous value. The underlying
+    # foundation is responsible for mapping this correctly based on the type of control element.
+    # TODO: Define behavior for multi-named elements, such as `<select>`.
+    #
+    # * newValue - (optional) new value for field
+    value: (newValue) ->
+#if jquery
+      current = @$.val()
+
+      if arguments.length > 0
+        @$.val newValue
+#elseif prototype
+      current = @element.getValue()
+
+      if arguments.length > 0
+        @element.setValue newValue
+#endif
+      return current
+
+    # Returns true if a checkbox is checked
+    checked: ->
+      @element.checked
+
+    # Stores or retrieves meta-data on the element. With one parameter, the current value for the name
+    # is returned (or undefined). With two parameters, the meta-data is updated and the previous value returned.
+    # For Prototype, the meta data is essentially empty (except, perhaps, for some internal keys used to store
+    # event handling information).  For jQuery, the meta data may be initialized from data- attributes.
+    #
+    # * name - name of meta-data value to store or retrieve
+    # * value - (optional) new value for meta-data
+    meta: (name, value) ->
+#if jquery
+      current = @$.data name
+
+      if arguments.length > 1
+        @$.data name, value
+#elseif prototype
+      current = @element.retrieve name
+
+      if arguments.length > 1
+        @element.store name, value
+#endif
+      return current
+
+    # Adds an event handler for one or more events.
+    #
+    # * events - one or more event names, separated by spaces
+    # * match - optional: CSS expression used as a filter; only events that bubble
+    #   up to the wrapped element from an originating element that matches the CSS expression
+    #   will invoke the handler.
+    # * handler - function invoked; the function is passed an `EventWrapper` object, and the
+    #   context (`this`) is the `ElementWrapper` for the matched element.
+    on: (events, match, handler) ->
+      exports.on @element, events, match, handler
+      return this
+
+    # Returns the text of the element (and its children).
+    text: ->
+#if jquery
+      @$.text()
+#elseif prototype
+      @element.textContent or @element.innerText
+#endif
+
+#if jquery
+  # Wrapper around the `jqXHR` object
+  class ResponseWrapper
+
+    constructor: (@jqxhr, data) ->
+
+      @status = jqxhr.status
+      @statusText = jqxhr.statusText
+      @json = data # Mostly right?  Need a content type check?
+      @text = jqxhr.responseText
+
+    # Retrieves a response header by name
+    header: (name) ->
+      @jqxhr.getResponseHeader name
+#elseif prototype
+  # Wrapper around the Prototype `Ajax.Response` object
+  class ResponseWrapper
+
+    constructor: (@res) ->
+
+      @status = res.status
+      @statusText = res.statusText
+      @json = res.responseJSON
+      @text = res.responseText
+
+    # Retrieves a response header by name
+    header: (name) ->
+      @res.getHeader name
+#endif
+
+
+  # Performs an asynchronous Ajax request, invoking callbacks when it completes.
+  #
+  # This is very low level; most code will want to go through the `t5/core/ajax` module instead,
+  # which adds better handling of exceptions and failures, and handles Tapestry's partial page
+  # render reponse keys.
+  #
+  # * options.method - "post", "get", etc., default: "post".
+  # * options.contentType - default "context "application/x-www-form-urlencoded"
+  # * options.parameters - optional, additional key/value pairs
+  # * options.success - handler to invoke on success. Passed the ResponseWrapper object.
+  #   Default does nothing.
+  # * options.failure - handler to invoke on failure (server responds with a non-2xx code).
+  #   Passed the response. Default will throw the exception
+  # * options.exception - handler to invoke when an exception occurs (often means the server is unavailable).
+  #   Passed the exception. Default will generate an exception message and throw an `Error`.
+  #   Note: not really supported under jQuery, a hold-over from Prototype.
+  # Returns the module's exports
+  ajaxRequest = (url, options = {}) ->
+#if jquery
+    $.ajax
+      url: url
+      type: options.method?.toUpperCase() or "POST"
+      contentType: options.contentType
+      traditional: true
+      data: options.parameters
+      # jQuery doesn't have the equivalent of Protoype's onException
+      error: (jqXHR, textStatus, errorThrown) ->
+        message = "Request to #{url} failed with status #{textStatus}"
+        text = jqXHR.statusText
+        if not _.isEmpty text
+          message += " -- #{text}"
+        message += "."
+
+        if options.failure
+          options.failure (new ResponseWrapper jqXHR), message
+        else
+          throw new Error message
+
+        return
+
+      success: (data, textStatus, jqXHR) ->
+
+        options.success and options.success(new ResponseWrapper jqXHR, data)
+        return
+#elseif prototype
+    finalOptions =
+      method: options.method or "post"
+      contentType: options.contentType or "application/x-www-form-urlencoded"
+      parameters: options.parameters or {}
+      onException: (ajaxRequest, exception) ->
+        if options.exception
+          options.exception exception
+        else
+          throw exception
+
+        return
+
+      onFailure: (response) ->
+        message = "Request to #{url} failed with status #{response.getStatus()}"
+        text = response.getStatusText()
+        if not _.isEmpty text
+          message += " -- #{text}"
+        message += "."
+
+        if options.failure
+          options.failure (new ResponseWrapper response), message
+        else
+          throw new Error message
+
+        return
+
+      onSuccess: (response) ->
+
+        # Prototype treats status == 0 as success, even though it may
+        # indicate that the server didn't respond.
+        if (not response.getStatus()) or (not response.request.success())
+          finalOptions.onFailure(new ResponseWrapper response)
+          return
+
+        # Tapestry 5.3 includes lots more exception catching ... that just got in the way
+        # of identifying the source of problems.  That's been stripped out.
+        options.success and options.success(new ResponseWrapper response)
+        return
+
+    new Ajax.Request(url, finalOptions)
+#endif
+
+    return exports
+
+  triggerReflow =
+#if jquery
+    _.debounce (-> $(document).trigger events.document.reflow), 250
+#elseif prototype
+    _.debounce (-> $(document).fire events.document.reflow), 250
+#endif
+
+  # The main export is a function that wraps a DOM element as an ElementWrapper; additional functions are attached as
+  # properties.
+  #
+  # * element - a DOM element, or a string id of a DOM element
+  #
+  # Returns the ElementWrapper, or null if no element with the id exists
+  exports = wrapElement = (element) ->
+    if _.isString element
+#if jquery
+      element = document.getElementById element
+#elseif prototype
+      element = $ element
+#endif
+      return null unless element
+    else
+      throw new Error "Attempt to wrap a null DOM element" unless element
+
+#if jquery
+    # Assume the object is a DOM element, document or window; something that is compatible with the
+    # jQuery API (especially with respect to events).
+    new ElementWrapper ($ element)
+#elseif prototype
+    # Assume the object is a DOM element, document or window; something that is compatible with the
+    # Prototype API (especially with respect to events).
+    new ElementWrapper element
+#endif
+
+  _.extend exports,
+    wrap: wrapElement
+
+    # Escape's HTML markup in the string.
+    escapeHTML: _.escape
+
+    triggerReflow: triggerReflow
+
+    ajaxRequest: ajaxRequest
+
+    # Used to add an event handler to an element (possibly from elements below it in the hierarch).
+    #
+    # * selector - CSS selector used to select elements to attach handler to; alternately,
+    #   a single DOM element, or an array of DOM elements. The document is considered an element
+    #   for these purposes.
+    # * events - one or more event names, separated by spaces
+    # * match - optional: CSS expression used as a filter; only events that bubble
+    # * up to a selected element from an originating element that matches the CSS expression
+    #   will invoke the handler.
+    # * handler - function invoked; the function is passed an `EventWrapper` object, and the context (`this`)
+    #   is the `ElementWrapper` for the matched element
+    on: (selector, events, match, handler) ->
+      unless handler?
+        handler = match
+        match = null
+
+#if jquery
+      elements = $ selector
+#elseif prototype
+      elements = parseSelectorToElements selector
+      events = utils.split events
+#endif
+      onevent elements, events, match, handler
+      return
+
+    # onDocument() is used to add an event handler to the document object; this is used
+    # for global (or default) handlers.
+    onDocument: (events, match, handler) ->
+      exports.on document, events, match, handler
+
+    # Returns a wrapped version of the document.body element. Because all Tapestry JavaScript occurs
+    # inside a block at the end of the document, inside the `<body`> element, it is assumed that
+    # it is always safe to get the body.
+    body: -> wrapElement document.body
+
+#if jquery
+  $(window).on "resize", exports.triggerReflow
+#elseif prototype
+  Event.observe window, "resize", triggerReflow
+#endif
+
+  return exports
\ No newline at end of file