You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2013/12/05 01:56:01 UTC

[4/4] git commit: TAP5-2251: Add LocalDate component to present formatted date/time in client's time zone

TAP5-2251: Add LocalDate component to present formatted date/time in client's time zone


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

Branch: refs/heads/master
Commit: 2bc3c14c97afb892f3cdb6d4a9e47833bc4d35c6
Parents: e10012a
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Wed Dec 4 16:54:49 2013 -0800
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Wed Dec 4 16:54:49 2013 -0800

----------------------------------------------------------------------
 .../META-INF/modules/t5/core/localdate.coffee   |   37 +
 .../tapestry5/corelib/components/LocalDate.java |   95 +
 .../tapestry5/modules/JavaScriptModule.java     |    5 +
 .../org/apache/tapestry5/t5-core-dom.coffee     |   31 +
 .../META-INF/assets/tapestry5/moment-2.4.0.js   | 7063 ++++++++++++++++++
 .../org/apache/tapestry5/core.properties        |    5 +-
 tapestry-core/src/test/app1/LocalDateDemo.tml   |   17 +
 .../integration/app1/pages/LocalDateDemo.groovy |    8 +
 .../tapestry5/integration/app1/pages/Index.java |    1 +
 9 files changed, 7261 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2bc3c14c/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/localdate.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/localdate.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/localdate.coffee
new file mode 100644
index 0000000..136ce26
--- /dev/null
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/localdate.coffee
@@ -0,0 +1,37 @@
+# Copyright 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/localdate
+#
+# Used with the LocalDate component to present a Date in a particular format, in the
+# browser's time zone.
+
+define ["./dom", "moment"],
+(dom, moment) ->
+
+  ATTR = "data-localdate-format"
+
+  dom.scanner "[#{ATTR}]", (el) ->
+    format = el.attr ATTR
+
+    isoString = el.text()
+
+    m = moment isoString
+
+    el.update m.format format
+
+    # A good scanner callback always removes itself from future scans.
+    el.attr ATTR, null
+
+    return

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2bc3c14c/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
new file mode 100644
index 0000000..5091176
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
@@ -0,0 +1,95 @@
+// Copyright 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.
+
+package org.apache.tapestry5.corelib.components;
+
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.SupportsInformalParameters;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.services.javascript.JavaScriptSupport;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Used to present a date, formatted in the time zone of the client browser.
+ * This is based on the <a href="http://momentjs.com/">Moment</a> JavaScript library.
+ * <p/>
+ * If the value parameter is non-null, then this component will render an element
+ * wrapping the value (formatted in ISO-8601). The element will match the template element,
+ * or a "span" if the template did not provide an element. Informal parameters will be rendered
+ * into the element.
+ * <p/>
+ * When a date is rendered, it is rendered in an element, used to specify the client-side formatting.
+ * The element's content will be the ISO-8601 format. The client-side will
+ * immediately rewrite the content to the formatted value, in the client browser's time
+ * zone.
+ *
+ * @tapestrydoc
+ * @since 5.4
+ */
+@SupportsInformalParameters
+public class LocalDate
+{
+    /**
+     * The format to use, as defined by <a href="">Moment.js</a>. The factory default
+     * is "lll", which is a short form of the month, day, year, hour, minute and am/pm,
+     * e.g. "Sep 4 1986 8:30 PM".
+     */
+    @Parameter(defaultPrefix = BindingConstants.LITERAL, allowNull = false, value = "message:private-default-localdate-format")
+    String format;
+
+    /**
+     * The date value to render.  If this value is null, then nothing is rendered at all.
+     */
+    @Parameter
+    Date value;
+
+    @Inject
+    ComponentResources resources;
+
+    @Environmental
+    JavaScriptSupport javaScriptSupport;
+
+    private static TimeZone tz = TimeZone.getTimeZone("UTC");
+
+    boolean beginRender(MarkupWriter writer)
+    {
+        if (value != null)
+        {
+            DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
+            df.setTimeZone(tz);
+
+            writer.element(resources.getElementName("span"),
+                    "data-localdate-format", format);
+
+            resources.renderInformalParameters(writer);
+
+            writer.write(df.format(value));
+
+            writer.end();
+
+            javaScriptSupport.require("t5/core/localdate");
+        }
+
+        // Skip the body regardless.
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2bc3c14c/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
index 9ac78e1..a556269 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
@@ -299,6 +299,9 @@ public class JavaScriptModule
                                         @Path("${tapestry.asset.root}/typeahead-0.9.3.js")
                                         Resource typeahead,
 
+                                        @Path("${tapestry.asset.root}/moment-2.4.0.js")
+                                        Resource moment,
+
                                         @Path("${" + SymbolConstants.BOOTSTRAP_ROOT + "}/js/transition.js")
                                         Resource transition)
     {
@@ -322,6 +325,8 @@ public class JavaScriptModule
 
         configuration.add("t5/core/typeahead", new JavaScriptModuleConfiguration(typeahead).dependsOn("jquery"));
 
+        configuration.add("moment", new JavaScriptModuleConfiguration(moment));
+
     }
 
     @Contribute(SymbolProvider.class)

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2bc3c14c/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 58d07e1..c76a6fe 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
@@ -784,6 +784,35 @@ define ["underscore", "./utils", "./events", "jquery"],
     new RequestWrapper (new Ajax.Request url, finalOptions)
 #endif
 
+  scanners = null
+
+  # Sets up a scanner callback; this is used to perfom one-time setup of elements
+  # that match a particular CSS selector. The callback is passed each element that
+  # matches the selector. The callback is expected to modify the element so that it does not
+  # match future selections caused by zone updates, typically by removing the CSS class or data- attribute
+  # referenced by the selector.
+  scanner = (selector, callback) ->
+    # Define a function that scans some root element (the body initially; later an updated Zone)
+    scan = (root) ->
+      callback el for el in root.find selector
+      return
+
+    # Do it once immediately:
+
+    scan exports.body
+
+    # Lazily set up a single event handler for running any added scanners.
+
+    if scanners is null
+      scanners = []
+      exports.body.on events.zone.didUpdate, ->
+        f this for f in scanners
+        return
+
+    scanners.push scan
+
+    return
+
   # The main export is a function that wraps a DOM element as an ElementWrapper; additional functions are attached as
   # properties.
   #
@@ -879,4 +908,6 @@ define ["underscore", "./utils", "./events", "jquery"],
     # it is always safe to get the body.
     body: wrapElement document.body
 
+    scanner: scanner
+
   return exports