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/07/18 19:56:09 UTC

[2/2] git commit: Remove t5/core/builder module Rename t5/core/exceptionframe to t5/core/exception-frame

Remove t5/core/builder module
Rename t5/core/exceptionframe to t5/core/exception-frame


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

Branch: refs/heads/master
Commit: 2dbde11ae4ecbf298d98b413d70ba137f7bab83b
Parents: fdd6b89
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Thu Jul 18 10:55:59 2013 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Thu Jul 18 10:55:59 2013 -0700

----------------------------------------------------------------------
 .../META-INF/modules/t5/core/ajax.coffee        |   4 +-
 .../modules/t5/core/ajaxformloop.coffee         |  16 +-
 .../META-INF/modules/t5/core/alert.coffee       |  42 ++---
 .../META-INF/modules/t5/core/builder.coffee     | 128 ---------------
 .../META-INF/modules/t5/core/console.coffee     | 162 ++++++++++---------
 .../META-INF/modules/t5/core/datefield.coffee   |   8 +-
 .../modules/t5/core/exception-frame.coffee      |  69 ++++++++
 .../modules/t5/core/exceptionframe.coffee       |  63 --------
 .../META-INF/modules/t5/core/fields.coffee      |  14 +-
 .../META-INF/modules/t5/core/forms.coffee       |   6 +-
 .../org/apache/tapestry5/t5-core-dom.coffee     |  37 ++++-
 11 files changed, 233 insertions(+), 316 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.coffee
index 87ef023..216b633 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajax.coffee
@@ -19,8 +19,8 @@
 #
 # It wraps (or provides) `success`, `exception`, and `failure` handlers, extended to handle a partial page render
 # response (for success), or properly log a server-side failure or client-side exception, including using the
-# `t5/core/exceptionframe` module to display a server-side processing exception.
-define ["./pageinit", "./dom", "./exceptionframe", "./console", "underscore"],
+# `t5/core/exception-frame` module to display a server-side processing exception.
+define ["./pageinit", "./dom", "./exception-frame", "./console", "underscore"],
   (pageinit, dom, exceptionframe, console, _) ->
     (url, options) ->
       newOptions = _.extend {}, options,

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajaxformloop.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajaxformloop.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajaxformloop.coffee
index dd54831..1a29d1b 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajaxformloop.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/ajaxformloop.coffee
@@ -16,8 +16,8 @@
 #
 # Provides handlers related to the core/AjaxFormLoop component (as well as core/AddRowLink and
 # core/RemoveRowLink).
-define ["./dom", "./events", "./console", "./ajax", "./builder"],
-  (dom, events, console, ajax, builder) ->
+define ["./dom", "./events", "./console", "./ajax"],
+  (dom, events, console, ajax) ->
 
     # "afl" is short for "AjaxFormLoop".
     AFL_SELECTOR = "[data-container-type='core/AjaxFormLoop']"
@@ -60,15 +60,17 @@ define ["./dom", "./events", "./console", "./ajax", "./builder"],
 
       ajax url,
         success: (response) =>
-          content = response.json?.content
+          content = response.json?.content or ""
 
           # Create a new element with the same type (usually "div") and class as this element.
           # It will contain the new content.
-          newElement = builder insertionPoint.element.tagName,
-              class: insertionPoint.element.className,
-              "data-container-type": FRAGMENT_TYPE
 
-          newElement.update content
+          newElement = """
+              <#{insertionPoint.element.tagName} class="#{insertionPoint.element.className}"
+                data-container-type="#{FRAGMENT_TYPE}">
+                #{content}
+                </#{insertionPoint.element.tagName}>
+              """
 
           insertionPoint.insertBefore newElement
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/alert.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/alert.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/alert.coffee
index 142aed6..64d0d8f 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/alert.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/alert.coffee
@@ -16,8 +16,8 @@
 #
 # Support for the core/Alerts components.
 #
-define ["./dom", "./console", "./messages", "./builder", "./ajax", "underscore"],
-  (dom, console, messages, builder, ajax, _) ->
+define ["./dom", "./console", "./messages", "./ajax", "underscore"],
+  (dom, console, messages, ajax, _) ->
 
     severityToClass =
       success: "alert alert-success"
@@ -33,7 +33,6 @@ define ["./dom", "./console", "./messages", "./builder", "./ajax", "underscore"]
         container.update null
 
     dismissAll = (container) ->
-      console.debug "dismiss all"
 
       alerts = container.find "[data-alert-id]"
 
@@ -45,7 +44,6 @@ define ["./dom", "./console", "./messages", "./builder", "./ajax", "underscore"]
         success: -> container.update null
 
     dismissOne = (container, button) ->
-      console.debug "dismiss single"
 
       alert = button.parent()
 
@@ -61,19 +59,23 @@ define ["./dom", "./console", "./messages", "./builder", "./ajax", "underscore"]
 
     setupUI = (container) ->
 
-      clickHandler = ->
+      container.update """
+         <div class="well">
+          <div data-container-type="inner"></div>
+          <div class="row-fluid">
+            <button class="btn btn-mini pull-right" data-action="dismiss-all">
+              <strong>&times;</strong>
+              #{messages "core-dismiss-label"}
+            </button>
+          </div>
+         </div>
+         """
+
+      container.on "click", "[data-action=dismiss-all]", ->
         dismissAll container
         return false
 
-      container.update builder ".well",
-        ["div", "data-container-type": "inner"],
-        [".row-fluid > button.btn.btn-mini.pull-right",
-            onclick: clickHandler
-            ["strong", "\u00d7 "],
-            messages "core-dismiss-label"
-        ]
-
-      container.on "click button.close", ->
+      container.on "click", "button.close", ->
         dismissOne container, this
         return false
 
@@ -108,12 +110,14 @@ define ["./dom", "./console", "./messages", "./builder", "./ajax", "underscore"]
       # Note that `data-dismiss=alert` is purposely excluded
       # - we want to handle closes w/ notifications to the server if not transient
       # - we don't want to rely on bootstrap.js, as that will drag jQuery into the application
-      element = builder "div", class: className,
-        ["button.close", "\u00d7"]
-        content
 
-      if data.id
-        element.attribute "data-alert-id", data.id
+      element = dom.create "div",
+        "data-alert-id": data.id
+        class: className
+        """
+          <button class="close">&times;</button>
+          #{content}
+        """
 
       container.append element
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/builder.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/builder.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/builder.coffee
deleted file mode 100644
index 83bfaef..0000000
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/builder.coffee
+++ /dev/null
@@ -1,128 +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/builder
-#
-# A system for constructing DOM element nodes for a particular structure in minimal code.  The basic syntax is:
-# `builder(elementDescription, body...)` and the result is a `t5/core/dom:ElementWrapper` (a wrapper around the constructed
-# DOM elements). The element description is primarily the name of the element.
-#
-# The element description may contain sequences of "._name_"; these appropriate CSS syntax to describe a CSS class name
-# for the element.  The element name may be omitted when CSS class names are specified, in which case `div` is the
-# default element name. Multiple CSS class names are allowed, e.g., `button.btn.btn-primary`.
-#
-# The description may also include the `>` character; this represents the start of a nested element; in this way
-# a structure can quickly be specified. e.g. `builder "label.checkbox > input", type: "checkbox", " Remember me"`
-# would construct:
-#
-#     <label class="checkbox">
-#        <input type="checkbox"> Remember me</input>
-#     </label>
-#
-# The body may consist of:
-#
-# * Objects: used to specify attributes and event handlers of the element
-# * Strings: literal markup text
-# * Array: a nested element definition
-#
-# Literal text is NOT escaped. You should be careful to use Underscore's `escape()` if the body contains
-# any potential markup that should be escaped; alternately, it may be easier to use embedded markup in the body
-# than to use an element definition.
-#
-# For an Object, each key and value is simply added as an attribute. However, for keys that start with "on", the value
-# is assumed to be an event handler function. The special key "on" consists of nested event handlers for the events
-# whose name matches the key. The following are equivalent:
-#
-#     { onclick: -> ... }
-#
-# and
-#
-#     { on: { click: -> ... }}
-define ["underscore", "./dom", "./utils"], (_, dom, utils) ->
-  # _internal_: creates a single DOM element and CSS class attribute
-  createElement = (elementDescription) ->
-    # TODO: Support #id for setting the id of an element, maybe others, such as ?name for the name of an input element.
-    # That will require a regex or more sophisticated parsing.
-    terms = utils.trim(elementDescription).split(".")
-
-    elementName = terms.shift() or "div"
-
-    element = document.createElement elementName
-
-    if terms.length
-      element.className = terms.join " "
-
-    return element
-
-  # _internal_: adds attributes and event handlers to a DOM element
-  addAttributes = (element, attributes) ->
-    return unless attributes
-
-    wrapper = dom element
-
-    for name, value of attributes
-      if name is "on"
-        for eventName, handler of value
-          wrapper.on eventName, handler
-      else if (utils.startsWith name, "on")
-        wrapper.on (name.substring 2), value
-      else
-        wrapper.attribute name, value
-
-    return null
-
-  # _internal_: processes the body, adding attributes and nested nodes to the DOM element
-  addAttributesAndBody = (element, body) ->
-    for nested in body
-      unless nested?
-        # Ignore null nodes
-      else if _.isString nested
-        element.innerHTML += nested
-      else if _.isArray nested
-        [elementDescription, nestedBody...] = nested
-        nestedElement = buildTree elementDescription, nestedBody
-        element.appendChild nestedElement
-      else if _.isObject nested
-        addAttributes element, nested
-      else throw new Error "Unexpected body value <#{nested}> while building DOM elements."
-
-    return null
-
-  # _internal_: builds the tree from the element description, handing nested nodes, and split
-  # descriptions (containing `>`), returning the topmost DOM element
-  buildTree = (elementDescription, body) ->
-    splitx = elementDescription.indexOf ">"
-    currentDescription =
-      if splitx is -1
-        elementDescription
-      else
-        elementDescription.substring 0, splitx
-
-    element = createElement currentDescription
-
-    if splitx is -1
-      addAttributesAndBody element, body
-    else
-      nestedDescription = elementDescription.substring splitx + 1
-      nestedElement = buildTree nestedDescription, body
-      element.appendChild nestedElement
-
-    return element
-
-  # The module exports a single function that builds the tree of elements and returns the top element, wrapped as an
-  # `t5/core/dom:ElementWrapper`.
-  (elementDescription, body...) ->
-    element = buildTree elementDescription, body
-
-    dom element
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/console.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/console.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/console.coffee
index a622080..2d530df 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/console.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/console.coffee
@@ -15,87 +15,93 @@
 # ## t5/core/console
 #
 # A wrapper around the native console, when it exists.
-define ["./dom", "./builder", "underscore"], (dom, builder, _) ->
-  nativeConsole = {}
-  floatingConsole = null
-
-  FADE_DURATION = 0.25
-
-  # module exports are mutable; someone else could
-  # require this module to change the default DURATION
-  exports =
-  # Default duration for floating console is 10 seconds.
-    DURATION: 10
-
-  try
-    # FireFox will throw an exception if you even access the console object and it does
-    # not exist. Wow!
-    nativeConsole = console
-  catch e
-
-  # _internal_: displays the message inside the floating console, creating the floating
-  # console as needed.
-  display = (className, message) ->
-    unless floatingConsole
-      floatingConsole = builder ".tapestry-console"
-      dom.body.prepend floatingConsole
-
-    div = builder ".entry>.#{className}",
-      ["button.close", "&times;"],
-      (_.escape message)
-
-    floatingConsole.append div.hide().fadeIn FADE_DURATION
-
-    removed = false
-
-    runFadeout = ->
-      div.fadeOut FADE_DURATION, ->
-        div.remove() unless removed
-
-    window.setTimeout runFadeout, exports.DURATION * 1000
-
-    div.on "click", ->
-      div.remove()
-      removed = true
-
-  level = (className, consolefn) ->
-    (message) ->
-      # consolefn may be null if there's no console; under IE it may be non-null, but not a function.
-
-      unless consolefn
-        # Display it floating. If there's a real problem, such as a failed Ajax request, then the
-        # client-side code should be alerting the user in some other way, and not rely on them
-        # being able to see the logged console output.
-        display className, message
-        return
-
-      if _.isFunction consolefn
-        # Use the available native console, calling it like an instance method
-        consolefn.call console, message
-      else
-        # And IE just has to be different. The properties of console are callable, like functions,
-        # but aren't proper functions that work with `call()` either.
-        consolefn message
+define ["./dom", "underscore"],
+  (dom, _) ->
+    nativeConsole = {}
+    floatingConsole = null
+
+    FADE_DURATION = 0.25
+
+    # module exports are mutable; someone else could
+    # require this module to change the default DURATION
+    exports =
+    # Default duration for floating console is 10 seconds.
+      DURATION: 10
+
+    try
+      # FireFox will throw an exception if you even access the console object and it does
+      # not exist. Wow!
+      nativeConsole = console
+    catch e
+
+    # _internal_: displays the message inside the floating console, creating the floating
+    # console as needed.
+    display = (className, message) ->
+      unless floatingConsole
+        floatingConsole = dom.create class: "tapestry-console"
+        dom.body.prepend floatingConsole
+
+      div = dom.create
+        class: "entry"
+        """
+          <div class="#{className}">
+            <button class="close">&times;</button>
+            #{_.escape message}
+          </div>
+        """
+
+      floatingConsole.append div.hide().fadeIn FADE_DURATION
+
+      removed = false
+
+      runFadeout = ->
+        div.fadeOut FADE_DURATION, ->
+          div.remove() unless removed
+
+      window.setTimeout runFadeout, exports.DURATION * 1000
+
+      div.on "click", ->
+        div.remove()
+        removed = true
+
+    level = (className, consolefn) ->
+      (message) ->
+        # consolefn may be null if there's no console; under IE it may be non-null, but not a function.
+
+        unless consolefn
+          # Display it floating. If there's a real problem, such as a failed Ajax request, then the
+          # client-side code should be alerting the user in some other way, and not rely on them
+          # being able to see the logged console output.
+          display className, message
+          return
+
+        if _.isFunction consolefn
+          # Use the available native console, calling it like an instance method
+          consolefn.call console, message
+        else
+          # And IE just has to be different. The properties of console are callable, like functions,
+          # but aren't proper functions that work with `call()` either.
+          consolefn message
 
-      return
+        return
 
 
-  # Determine whether debug is enabled by checking for the necessary attribute (which is missing
-  # in production mode).
-  exports.debugEnabled = (document.documentElement.getAttribute "data-debug-enabled")?
+    # Determine whether debug is enabled by checking for the necessary attribute (which is missing
+    # in production mode).
+    exports.debugEnabled = (document.documentElement.getAttribute "data-debug-enabled")?
 
-  # When debugging is not enabled, then the debug function becomes a no-op.
-  exports.debug =
-    if exports.debugEnabled
-      # If native console available, go for it.  IE doesn't have debug, so we use log instead.
-      level "alert", (nativeConsole.debug or nativeConsole.log)
-    else
-      ->
+    # When debugging is not enabled, then the debug function becomes a no-op.
+    exports.debug =
+      if exports.debugEnabled
+        # If native console available, go for it.  IE doesn't have debug, so we use log instead.
+        level "alert", (nativeConsole.debug or nativeConsole.log)
+      else
+        ->
 
-  exports.info = level "alert.alert-info", nativeConsole.info
-  exports.warn = level "alert", nativeConsole.warn
-  exports.error = level "alert.alert-error", nativeConsole.error
+    exports.info = level "alert.alert-info", nativeConsole.info
+    exports.warn = level "alert", nativeConsole.warn
+    exports.error = level "alert.alert-error", nativeConsole.error
 
-  # Return the exports; we keep a reference to it, so we can see exports.DURATION, even
-  # if some other module imports this one and modifies that property.
-  return exports
\ No newline at end of file
+    # Return the exports; we keep a reference to it, so we can see exports.DURATION, even
+    # if some other module imports this one and modifies that property.
+    return exports
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee
index 7f994d1..8c4948f 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/datefield.coffee
@@ -15,9 +15,8 @@
 # ## t5/core/datefield
 #
 # Provides support for the `core/DateField` component.
-define ["./dom", "./events", "./messages", "./builder", "./ajax",
-  "underscore", "./fields"],
-  (dom, events, messages, builder, ajax, _) ->
+define ["./dom", "./events", "./messages", "./ajax", "underscore", "./fields"],
+  (dom, events, messages, ajax, _) ->
 
 
     # Translate from the provided order (SUNDAY = 0, MONDAY = 1), to
@@ -115,8 +114,7 @@ define ["./dom", "./events", "./messages", "./builder", "./ajax",
       createPopup: ->
         @datePicker = new DatePicker()
         @datePicker.setFirstWeekDay datePickerFirstDay
-        @popup = builder "div.t-datefield-popup"
-        @popup.append dom @datePicker.create()
+        @popup = dom.create().append @datePicker.create()
         @container.append @popup
 
         @datePicker.onselect = _.bind @onSelect, this

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exception-frame.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exception-frame.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exception-frame.coffee
new file mode 100644
index 0000000..dc1a34b
--- /dev/null
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exception-frame.coffee
@@ -0,0 +1,69 @@
+# 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/exception-frame
+#
+# Manages a special element used to present a HTML exception report from an Ajax request (where a non-markup response
+# was expected, including a partial page render response).
+define ["./dom", "underscore"],
+  (dom, _) ->
+    container = null
+    iframe = null
+    iframeDocument = null
+
+    write = (content) ->
+      # Clear current content:
+      iframeDocument.open()
+      # Write new content:
+      iframeDocument.write content
+      iframeDocument.close()
+
+    clear = ->
+      write ""
+      container.hide()
+      return false
+
+    create = ->
+      return if container
+
+      container = dom.create
+        class: "exception-container"
+        """
+          <iframe> </iframe>
+          <div>
+            <button class="pull-right btn btn-primary">
+              <i class="icon-remove icon-white"></i>
+              Close
+            </button>
+          </div>
+        """
+
+      dom.body.append container.hide()
+
+      iframe = (container.findFirst "iframe").element
+
+      # See http://xkr.us/articles/dom/iframe-document/
+
+      iframeDocument = iframe.contentWindow or iframe.contentDocument
+      if iframeDocument.document
+        iframeDocument = iframeDocument.document
+
+      container.on "click", "button", clear
+
+    # Export single function:
+
+    (exceptionContent) ->
+      create()
+      write exceptionContent
+      container.show()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exceptionframe.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exceptionframe.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exceptionframe.coffee
deleted file mode 100644
index 93d2757..0000000
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/exceptionframe.coffee
+++ /dev/null
@@ -1,63 +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/exceptionframe
-#
-# Manages a special element used to present a HTML exception report from an Ajax request (where a non-markup response
-# was expected, including a partial page render response).
-define ["./dom", "./builder", "underscore"],
-  (dom, builder, _) ->
-    container = null
-    iframe = null
-    iframeDocument = null
-
-    write = (content) ->
-      # Clear current content:
-      iframeDocument.open()
-      # Write new content:
-      iframeDocument.write content
-      iframeDocument.close()
-
-    clear = ->
-      write ""
-      container.hide()
-      return false
-
-    create = ->
-      return if container
-
-      container = builder ".exception-container",
-        ["iframe"],
-        ["div>button.pull-right.btn.btn-primary",
-         ["i.icon-remove.icon-white"],
-         "Close"]
-
-      dom.body.append container.hide()
-
-      iframe = (container.findFirst "iframe").element
-
-      # See http://xkr.us/articles/dom/iframe-document/
-
-      iframeDocument = iframe.contentWindow or iframe.contentDocument
-      if iframeDocument.document
-        iframeDocument = iframeDocument.document
-
-      container.on "click", "button", clear
-
-    # Export single function:
-
-    (exceptionContent) ->
-      create()
-      write exceptionContent
-      container.show()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/fields.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/fields.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/fields.coffee
index 1f0923f..2846f91 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/fields.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/fields.coffee
@@ -16,8 +16,8 @@
 #
 # Module for logic relating to form input fields (input, select, textarea); specifically
 # presenting validation errors and perfoming input validation when necessary.
-define ["underscore", "./events", "./dom", "./builder", "./utils", "./forms"],
-  (_, events, dom, builder, utils) ->
+define ["underscore", "./events", "./dom", "./utils", "./forms"],
+  (_, events, dom, utils) ->
 
     ensureFieldId = (field) ->
       fieldId = field.attribute "id"
@@ -76,7 +76,9 @@ define ["underscore", "./events", "./dom", "./builder", "./utils", "./forms"],
 
       container = field.parent()
 
-      block = builder "p.help-block", "data-error-block-for": fieldId
+      block = dom.create "p",
+        class: "help-block"
+        "data-error-block-for": fieldId
 
       # The .input-append and .input-prepend are used to attach buttons or markers to the field.
       # In which case, the block can go
@@ -87,10 +89,6 @@ define ["underscore", "./events", "./dom", "./builder", "./utils", "./forms"],
 
       return block
 
-    # This may be removed soon:
-    showValidationError = (id, message) ->
-      dom.wrap(id).trigger events.field.showValidationError, { message }
-
     collectOptionValues = (wrapper) ->
       _.pluck wrapper.element.options, "value"
 
@@ -171,4 +169,4 @@ define ["underscore", "./events", "./dom", "./builder", "./utils", "./forms"],
 
       group and group.addClass "error"
 
-    exports = {findHelpBlock, createHelpBlock, showValidationError}
\ No newline at end of file
+    exports = {findHelpBlock, createHelpBlock}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/forms.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/forms.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/forms.coffee
index ef9cff1..d3adb11 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/forms.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/forms.coffee
@@ -16,8 +16,8 @@
 #
 # Defines handlers for HTML forms and HTML field elements, specifically to control input validation.
 
-define ["./events", "./dom", "./builder", "underscore"],
-  (events, dom, builder, _) ->
+define ["./events", "./dom", "underscore"],
+  (events, dom, _) ->
 
     # Meta-data name that indicates the next submission should skip validation (typically, because
     # the form was submitted by a "cancel" button).
@@ -44,7 +44,7 @@ define ["./events", "./dom", "./builder", "underscore"],
 
       unless hidden
         firstHidden = form.findFirst "input[type=hidden]"
-        hidden = builder "input", type:"hidden", name:"t:submit"
+        hidden = dom.create "input", type: "hidden", name: "t:submit"
         firstHidden.insertBefore hidden
 
       # TODO: Research why we need id and name and get rid of one if possible.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2dbde11a/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
index a08ef9d..6b1ce81 100644
--- 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
@@ -322,8 +322,8 @@ define ["underscore", "./utils", "./events", "jquery"],
 #if jquery
         @$.attr name
 #elseif prototype
-        for name, value of name
-          @element.writeAttribute name, value
+        for attributeName, value of name
+          @attribute attributeName, value
 #endif
         return this
 
@@ -334,7 +334,10 @@ define ["underscore", "./utils", "./events", "jquery"],
 #elseif prototype
       current = @element.readAttribute name
       if arguments.length > 1
-        @element.writeAttribute name, value
+        # Treat undefined and null the same; Prototype does something slightly odd,
+        # treating undefined as a special case where the attribute value matches
+        # the attribute name.
+        @element.writeAttribute name, if value is undefined then null else value
 #endif
 
       return current
@@ -837,9 +840,37 @@ define ["underscore", "./utils", "./events", "jquery"],
     new ElementWrapper element
 #endif
 
+  # Creates a new element, detached from the DOM.
+  #
+  # * elementName - (string) name of element to create, if ommitted, then "div"
+  # * attributes - (object) attributes to apply to the created element (may be omitted)
+  # * body - (string) content for the new element, may be omitted for no body
+  createElement = (elementName, attributes, body) ->
+
+    if _.isObject elementName
+      body = attributes
+      attributes = elementName
+      elementName = null
+
+    if _.isString attributes
+      body = attributes
+      attributes = null
+
+    element = wrapElement document.createElement (elementName or "div")
+
+    if attributes
+      element.attribute attributes
+
+    if body
+      element.update body
+
+    return element
+
   _.extend exports,
     wrap: wrapElement
 
+    create: createElement
+
     triggerReflow: triggerReflow
 
     ajaxRequest: ajaxRequest