tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hls...@apache.org
Subject [9/13] git commit: Re-instate the floating console - add ElementWrapper.prepend(), .fadeIn(), and .fadeOut() - since core/console depends on core/spi, core/spi cannot depend on core/console - refactor the code in core/spi:ajaxRequest() that uses core/con
Date Fri, 10 Aug 2012 22:07:25 GMT
Re-instate the floating console
- add ElementWrapper.prepend(), .fadeIn(), and .fadeOut()
- since core/console depends on core/spi, core/spi cannot depend on core/console
- refactor the code in core/spi:ajaxRequest() that uses core/console into core/ajax


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

Branch: refs/heads/5.4-js-rewrite
Commit: 309253ad4dd2b86ebdc4fa947037b0c4dbac4117
Parents: febfe01
Author: Howard M. Lewis Ship <hlship@apache.org>
Authored: Fri Aug 10 11:24:28 2012 -0700
Committer: Howard M. Lewis Ship <hlship@apache.org>
Committed: Fri Aug 10 11:26:54 2012 -0700

----------------------------------------------------------------------
 .../coffeescript/META-INF/modules/core/ajax.coffee |   28 +++--
 .../META-INF/modules/core/builder.coffee           |   50 +++++---
 .../META-INF/modules/core/console.coffee           |   49 +++++----
 .../coffeescript/META-INF/modules/core/spi.coffee  |   92 +++++++++++++--
 4 files changed, 159 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/309253ad/tapestry-core/src/main/coffeescript/META-INF/modules/core/ajax.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/core/ajax.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/core/ajax.coffee
index d503b68..1e35292 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/core/ajax.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/core/ajax.coffee
@@ -17,14 +17,25 @@
 # Exports a single function, that invokes `core/spi:ajaxRequest()` with the provided `url`
and a modified version of the
 # `options`.
 #
-# It wraps (or provides) `onsuccess` and `onfailure` elements, extended to handle a partial
page render reponse (for
-# success), or properly log a server-side failure, including using `core/exceptionframe`
module to display a server-side
-# processing exception.
+# It wraps (or provides) `onsuccess`, `onexception`, and `onfailure` handlers, extended to
handle a partial page render
+# response (for success), or properly log a server-side failure or client-side exception,
including using
+# `core/exceptionframe` module to display a server-side processing exception.
 define ["core/pageinit", "core/spi", "core/exceptionframe", "core/console", "_"],
   (pageinit, spi, exceptionframe, console, _) ->
-    (url, options = {}) ->
+    (url, options) ->
       newOptions = _.extend {}, options,
-        onfailure: (response) ->
+
+        # Logs the exception to the console before passing it to the
+        # provided exception handler or throwing the exception.
+        onexception: (exception) ->
+          console.error "Request to #{url} failed with #{exception}"
+
+          if options.onexception
+            options.onexception exception
+          else
+            throw exception
+
+        onfailure: (response, failureMessage) ->
           raw = response.getHeader "X-Tapestry-ErrorMessage"
           unless _.isEmpty raw
             message = window.unescape raw
@@ -37,12 +48,7 @@ define ["core/pageinit", "core/spi", "core/exceptionframe", "core/console",
"_"]
             if isHTML
               exceptionframe response.responseText
           else
-            message = "Request to #{url} failed with status #{response.getStatus()}"
-            text = response.getStatusText()
-            if not _.isEmpty text
-              message += " -- #{text}"
-
-            console.error message + "."
+            console.error failureMessage
 
           options.onfailure and options.onfailure(response)
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/309253ad/tapestry-core/src/main/coffeescript/META-INF/modules/core/builder.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/core/builder.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/core/builder.coffee
index 0bf76d8..2037dfc 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/core/builder.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/core/builder.coffee
@@ -12,29 +12,41 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# core/builder
+# ##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 DOM element.  The element description
is
-# primarily the name of the element.
+# `builder(elementDescription, body...)` and the result is a `core/spi:ElementWrapper` (a
wrapper around the constructed
+# DOM elements). The element description is primarily the name of the element.
 #
-# It 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. Multiple CSS class
-# names are allowed.
+# 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 a '>' character; this represents the start of a nested
element; in this way
-# a structure can quickly be specified.
+# 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 handles of the element
-# Strings: literal text
-# Array: a nested element definition
-# For an Object, each key and value is simply added as an attribute. However, keys that start
with "on" are assumed to
-# be event handler functions. The special key "on" consists of nested event handlers for
the keys. The following are
-# equivlent:
-# { onclick: -> ... } and
-# { on: { click: -> ... }}
+#
+# * Objects: used to specify attributes and event handlers of the element
+# * Strings: literal text
+# * Array: a nested 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 ["_", "core/spi"], (_, spi) ->
+  # _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.
@@ -48,6 +60,7 @@ define ["_", "core/spi"], (_, spi) ->
 
     return element
 
+  # _internal_: adds attributes and event handlers to a DOM element
   addAttributes = (element, attributes) ->
     return unless attributes
 
@@ -64,6 +77,7 @@ define ["_", "core/spi"], (_, spi) ->
 
     return null
 
+  # _internal_: processes the body, adding attributes and nested nodes to the DOM element
   addAttributesAndBody = (element, body) ->
     for nested in body
       unless nested?
@@ -80,6 +94,8 @@ define ["_", "core/spi"], (_, spi) ->
 
     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 =
@@ -100,7 +116,7 @@ define ["_", "core/spi"], (_, spi) ->
     return element
 
   # The module exports a single function that builds the tree of elements and returns the
top element, wrapped as an
-  # spi.ElementWrapper.
+  # `core/spi:ElementWrapper`.
   (elementDescription, body...) ->
     element = buildTree elementDescription, body
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/309253ad/tapestry-core/src/main/coffeescript/META-INF/modules/core/console.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/core/console.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/core/console.coffee
index 273b73d..32b0c7b 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/core/console.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/core/console.coffee
@@ -12,42 +12,49 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-define ->
+# ##core/console
+#
+# A wrapper around the native console, when it exists.
+define ["core/spi", "core/builder", "_"], (spi, 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
-  # seconds
 
   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 ".t-console"
+      spi.body().prepend floatingConsole
+
+    div = builder ".t-console-entry.#{className}", message
+
+    floatingConsole.append div.hide().fadeIn FADE_DURATION
+
+    removed = false
+
+    runFadeout = ->
+      div.fadeOut FADE_DURATION, ->
+        div.remove() unless removed
 
-    # Disable the floating console temporarily, since we have to resolve the tangle of dependencies
-    # related to loading vs. the core stack, etc.
+    window.setTimeout runFadeout, exports.DURATION * 1000
 
-    #    unless floatingConsole
-    #      floatingConsole = new Element "div", class: "t-console"
-    #      $(document.body).insert top: floatingConsole
-    #
-    #    div = new Element "div", class: "t-console-entry #{className}"
-    #    div.update(_.escape(message)).hide()
-    #    floatingConsole.insert top:div
-    #
-    #    new Effect.Appear div, duration: .25
-    #
-    #    fade = new Effect.Fade div,
-    #      delay: exports.DURATION
-    #      afterFinish: -> div.remove()  # was T5.dom.remove(div)
-    #
-    #    div.observe "click", ->
-    #      fade.cancel()
-    #      div.remove() # was T5.dom.remove(div)
+    div.on "click", ->
+      div.remove()
+      removed = true
 
   level = (className, consolefn) ->
     (message) ->

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/309253ad/tapestry-core/src/main/coffeescript/META-INF/modules/core/spi.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/core/spi.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/core/spi.coffee
index 64e8452..5f9dfdc 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/core/spi.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/core/spi.coffee
@@ -18,9 +18,7 @@
 # This is the core of 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 is the
standard SPI, which wraps
 # Prototype ... but does it in a way that makes it relatively easy to swap in jQuery instead.
-#
-# TODO: Define a dependency on "prototype" when that's exposed as a stub module.
-define ["_", "core/console"], (_, console) ->
+define ["_", "prototype"], (_) ->
 
   # _internal_: splits the string into words separated by whitespace
   split = (str) ->
@@ -40,7 +38,36 @@ define ["_", "core/console"], (_, console) ->
 
     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.
+  # _internal_: Currently don't want to rely on Scriptaculous, since our needs are pretty
minor.
+  animate = (element, styleName, initial, final, duration, callbacks) ->
+    styles = {}
+    range = final - initial
+    initialTime = Date.now()
+    first = true
+    animator = ->
+      elapsed = Date.now() - initialTime
+      if elapsed >= duration
+        styles[styleName] = final
+        element.setStyle styles
+        window.clearInterval timeoutID
+        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] = initial
+    element.setStyle styles
+
+  # Generic view of an DOM event that is passed to a handler function.
   #
   # Properties:
   #
@@ -52,7 +79,7 @@ define ["_", "core/console"], (_, console) ->
   #  or a key name for others.
   class EventWrapper
 
-   constructor: (event) ->
+    constructor: (event) ->
       @nativeEvent = event
       @memo = event.memo
       @type = event.type
@@ -118,7 +145,7 @@ define ["_", "core/console"], (_, console) ->
   # Exposes the original element as property `element`.
   class ElementWrapper
 
-   constructor: (element) ->
+    constructor: (element) ->
       @element = $(element)
 
     # Hides the wrapped element, setting its display to 'none'.
@@ -182,13 +209,48 @@ define ["_", "core/console"], (_, console) ->
       @element.update (convertContent content)
       this
 
-    # Appends new content (Element or HTML markup string) to the element.
+    # Appends new content (Element, ElementWrapper, or HTML markup string) to the body of
the element.
     #
     # Returns this ElementWrapper.
     append: (content) ->
       @element.insert bottom: (convertContent content)
       this
 
+    # Prepends new content (Element, ElementWrapper, or HTML markup string) to the body of
the element.
+    #
+    # Returns this ElementWrapper
+    prepend: (content) ->
+      @element.insert top: (convertContent content)
+      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
+    #
+    # Returns this ElementWrapper
+    fadeIn: (duration, callback) ->
+      animate @element, "opacity", 0, 1, duration * 1000,
+        onstart: => @element.show()
+        oncomplete: callback
+
+    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
+    #
+    # Returns this ElementWrapper
+    fadeOut: (duration, callback) ->
+      animate @element, "opacity", 1, 0, duration * 1000,
+        oncomplete: callback
+
+      this
+
     # Finds the first child element that matches the CSS selector.
     #
     # Returns the ElementWrapper for the child element, or null if not found.
@@ -255,6 +317,10 @@ define ["_", "core/console"], (_, console) ->
   bodyWrapper = null
 
   # Performs an asynchronous Ajax request, invoking callbacks when it completes.
+  #
+  # This is very low level; most code will want to go through the `core/ajax` module instead,
+  # which adds better handling of exceptions and failures, and handles Tapestry's
+  #
   # * 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"
@@ -262,9 +328,10 @@ define ["_", "core/console"], (_, console) ->
   # * options.onsuccess - handler to invoke on success. Passed the XMLHttpRequest transport
object.
   #   Default does nothing.
   # * options.onfailure - handler to invoke on failure (server responds with a non-2xx code).
-  #   Passed the response. Default will log and error to the console.
+  #   Passed the response. Default will throw the exception
   # * options.onexception - handler to invoke when an exception occurs (often means the server
is unavailable).
-  #   Passed the exception. Default will log an error to the cnsole and throw the exception.
+  #   Passed the exception. Default will generate an exception message and throw an `Error`.
+  #
   # TODO: Clarify what the response object looks like and/or wrap the Prototype Ajax.Response
object.
   # TODO: Define what the return value is, or return exports
   ajaxRequest = (url, options = {}) ->
@@ -276,7 +343,6 @@ define ["_", "core/console"], (_, console) ->
         if options.onexception
           options.onexception exception
         else
-          console.error "Request to #{url} failed with #{exception}"
           throw exception
 
       onFailure: (response) ->
@@ -287,8 +353,12 @@ define ["_", "core/console"], (_, console) ->
           text = response.getStatusText()
           if not _.isEmpty text
             message += " -- #{text}"
+          message += "."
 
-          console.error message + "."
+          if options.onfailure
+            options.onfailure response, message
+          else
+            throw new Error(message)
 
       onSuccess: (response) ->
 


Mime
View raw message