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 2012/10/03 21:07:42 UTC
[1/10] git commit: Rebuild FormFragment client-side support
Updated Branches:
refs/heads/5.4-js-rewrite 48bec3a6d -> 654f3ef1a
Rebuild FormFragment client-side support
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/654f3ef1
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/654f3ef1
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/654f3ef1
Branch: refs/heads/5.4-js-rewrite
Commit: 654f3ef1a58335ccadf1309acc7948a8f1863025
Parents: 423df6d
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Wed Oct 3 12:07:21 2012 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Wed Oct 3 12:07:21 2012 -0700
----------------------------------------------------------------------
.../META-INF/modules/core/events.coffee | 13 +++
.../META-INF/modules/core/form-fragment.coffee | 62 ++++++++-------
.../META-INF/modules/core/forms.coffee | 6 +-
.../tapestry5/corelib/components/FormFragment.java | 49 ++++++------
.../resources/org/apache/tapestry5/tapestry.js | 4 +-
5 files changed, 75 insertions(+), 59 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/654f3ef1/tapestry-core/src/main/coffeescript/META-INF/modules/core/events.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/core/events.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/core/events.coffee
index 0131c15..2b649ea 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/core/events.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/core/events.coffee
@@ -29,6 +29,7 @@ define
# Triggered after `validateForm` (when there are no prior validation exceptions), to allow certain elements
# to configure themselves immediately before the form is submitted. This exists primarily for components such
# as FormFragment, which will update a enable or disable a hidden field to match the visibility of the fragment.
+ # The `core/spi.EventWrapper` for the form element is passed as the memo.
prepareForSubmit: "t5:form:prepare-for-submit"
# Triggered last, when the form is configured to not submit normally (as a standard POST). Under 5.3, this
@@ -36,6 +37,7 @@ define
# set the `data-prevent-submission` attribute. In either case, the submit event is stopped, and this
# event fired to replace it; in most cases, a handler will then handle submitting the form's data as part
# of an Ajax request.
+ # The `core/spi.EventWrapper` for the form element is passed as the memo.
processSubmit: "t5:form:process-submit"
field:
@@ -71,3 +73,14 @@ define
didShow: "t5:element:did-show"
# Trigered when a visible element has just been hidden.
didHide: "t5:element:did-hide"
+ # Event names specific to client-side element associated with the FormFragment component. These events exist to allow
+ # client code to cleanly adjust the visibility of the fragment, or remove it.
+ formfragment:
+ # Requests that the fragment change its visibility. The event memo is an object with a single key, visible, a
+ # boolean. The fragment will show or hide itself if necessary (triggering the `element.didShow` or
+ # `element.didHide` event).
+ changeVisibility: "t5:fragment:change-visibility"
+ # Request that the fragment remove itself entirely. This event is of no practical use, as it is simply equivalent
+ # to invoking `spi/ElementWrapper.remove()` on the fragment's element; the event exists for compatibility with
+ # Tapestry 5.3 and will be removed in Tapestry 5.5.
+ remove: "t5:fragment:remove"
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/654f3ef1/tapestry-core/src/main/coffeescript/META-INF/modules/core/form-fragment.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/core/form-fragment.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/core/form-fragment.coffee
index 601f0ac..699f3af 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/core/form-fragment.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/core/form-fragment.coffee
@@ -15,45 +15,49 @@
# ##core/form-fragment
#
-define ["core/spi", "core/events", "core/compat/tapestry"],
- (spi, events) ->
+define ["_", "core/spi", "core/events", "core/compat/tapestry"],
+ (_, spi, events) ->
- # Initializes a FormFragment element
- #
- # * spec.element - id of fragment's element
- # * spec.bound - (optional) reference to function that determines bound
- # (used with `core/spi:EventWrapper.deepVisible()`)
- # * spec.alwaysSubmit - (optional) if true, then fields inside the fragment submit their values
- # even when the fragment is not visible. If false (default), then field data is not submitted.
- initFragment = (spec) ->
- element = spi spec.element
- hidden = spi "#{spec.element}-hidden"
- form = spi hidden.element.form
+ SELECTOR = '[data-component-type="core/FormFragment"]'
+
+ # Setup up top-level event handlers for FormFragment-related DOM events.
+ spi.domReady ->
+ body = spi.body()
+
+ # This is mostly for compatibility with 5.3, which supported
+ # a DOM event to ask a fragment to remove itself. This makes less sense since
+ # default animations were eliminated in 5.4.
+ body.on events.formfragment.remove, SELECTOR, (event) ->
+ this.remove()
- opts = spec.bound and { bound: spec.bound} or null
+ # When any form fires the prepareForSubmit event, check to see if
+ # any form fragments are contained within, and give them a chance
+ # to enabled/disable their hidden field.
+ body.on events.form.prepareForSubmit, "form", (event) ->
- unless spec.alwaysSubmit
- hidden.element.disabled = ! element.deepVisible opts
+ fragments = this.findAll SELECTOR
- updateUI = (makeVisible) ->
- unless spec.alwaysSubmit
- hidden.element.disabled = ! (makeVisible and element.container().deepVisible opts)
+ _.each fragments, (frag) ->
- element[if makeVisible then "show" else "hide"]()
+ fragmentId = frag.getAttribute "id"
- element.trigger events.element[if makeVisible then "didShow" else "didHide"]
+ hidden = frag.find "input[type=hidden][data-for-fragment=#{fragmentId}]"
- element.on Tapestry.CHANGE_VISIBILITY_EVENT, (event) ->
+ # If found (e.g., not alwaysSubmit), then enable/disable the field.
+ hidden && hidden.setAttribute "disabled", not frag.deepVisible()
+
+ # Again, a DOM event to make the FormFragment visible or invisible; this is useful
+ # because of the didShow/didHide events ... but we're really just seeing the evolution
+ # from the old style (the FormFragment class as controller) to the new style (DOM events and
+ # top-level event handlers).
+ body.on events.formfragment.changeVisibility, SELECTOR, (event) ->
event.stop()
makeVisible = event.memo.visible
- unless makeVisible is element.visible()
- updateUI makeVisible
+ this[if makeVisible then "show" else "hide"]()
- element.on Tapestry.HIDE_AND_REMOVE_EVENT, (event) ->
- event.stop()
- element.remove()
+ this.trigger events.element[if makeVisible then "didShow" else "didHide"]
# Initializes a trigger for a FormFragment
#
@@ -68,11 +72,11 @@ define ["core/spi", "core/events", "core/compat/tapestry"],
checked = trigger.element.checked
makeVisible = checked isnt invert
- (spi spec.fragmentId).trigger Tapestry.CHANGE_VISIBILITY_EVENT, visible: makeVisible
+ (spi spec.fragmentId).trigger events.formfragment.changeVisibility, visible: makeVisible
if trigger.element.type is "radio"
spi.on trigger.element.form, "click", update
else
trigger.on "click", update
- { initFragment, linkTrigger }
+ { linkTrigger }
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/654f3ef1/tapestry-core/src/main/coffeescript/META-INF/modules/core/forms.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/core/forms.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/core/forms.coffee
index 05fe893..d9e424f 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/core/forms.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/core/forms.coffee
@@ -69,14 +69,14 @@ define ["core/events", "core/spi", "core/builder", "core/compat/tapestry"],
# Allow certain types of elements to do last-moment set up. Basically, this is for
# FormFragment, or similar, to make their t:hidden field enabled or disabled to match
# their UI's visible/hidden status. This is assumed to work.
- this.trigger events.form.prepareForSubmit
+ this.trigger events.form.prepareForSubmit, this
# Sometimes we want to submit the form normally, for a full-page render.
# Othertimes we want to stop here and let the `events.form.processSubmit`
# handler take it from here.
if isPreventSubmission this
event.stop()
- this.trigger events.form.processSubmit
+ this.trigger events.form.processSubmit, this
# Otherwise, the event is good, there are no validation problems, let the normal processing commence.
return
@@ -89,7 +89,7 @@ define ["core/events", "core/spi", "core/builder", "core/compat/tapestry"],
# On any click on a submit or image, update the containing form to indicate that the element
# was responsible for the eventual submit; this is very important to Ajax updates, otherwise the
# information about which control triggered the submit gets lost.
- spi.body().on "click", "input[type=submit], input[type=image]", (event) ->
+ spi.body().on "click", "input[type=submit], input[type=image]", ->
setSubmittingHidden (spi this.element.form), this
exports =
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/654f3ef1/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/FormFragment.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/FormFragment.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/FormFragment.java
index 0e08011..4a22299f 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/FormFragment.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/FormFragment.java
@@ -16,6 +16,7 @@ package org.apache.tapestry5.corelib.components;
import org.apache.tapestry5.*;
import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.corelib.internal.ComponentActionSink;
@@ -24,8 +25,6 @@ import org.apache.tapestry5.corelib.internal.HiddenFieldPositioner;
import org.apache.tapestry5.corelib.mixins.TriggerFragment;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.ioc.annotations.Inject;
-import org.apache.tapestry5.json.JSONLiteral;
-import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.ClientDataEncoder;
import org.apache.tapestry5.services.Environment;
import org.apache.tapestry5.services.FormSupport;
@@ -38,16 +37,16 @@ import org.slf4j.Logger;
* automatically bypass validation when the fragment is invisible. The trick is to also bypass server-side form
* processing for such fields when the form is submitted; client-side logic "removes" the
* {@link org.apache.tapestry5.corelib.components.Form#FORM_DATA form data} for the fragment if it is invisible when the
- * form
- * is submitted; alternately, client-side logic can simply remove the form fragment element (including its visible and
+ * form is submitted (e.g., the hidden form field is disabled);
+ * alternately, client-side logic can simply remove the form fragment element (including its visible and
* hidden fields) to prevent server-side processing.
* <p/>
- * The client-side element will now listen to two new event defined by client-side constants:
+ * The client-side element will now listen to two new events defined by client-side constants:
* <dl>
- * <dt>Tapestry.CHANGE_VISIBILITY_EVENT</dt>
+ * <dt>core/events.formfragment.changeVisibility or Tapestry.CHANGE_VISIBILITY_EVENT</dt>
* <dd>Change the visibility as per the event memo's visibility property. When the visibility changes, the correct
* animation is executed.</dd>
- * <dt>Tapestry.HIDE_AND_REMOVE_EVENT</dt>
+ * <dt>core/events.formfragment.remove or Tapestry.HIDE_AND_REMOVE_EVENT</dt>
* <dd>Hides the element, then removes it from the DOM entirely.
* </dl>
*
@@ -56,6 +55,7 @@ import org.slf4j.Logger;
* @see Form
*/
@SupportsInformalParameters
+@Import(modules = "core/form-fragment")
public class FormFragment implements ClientElement
{
/**
@@ -109,13 +109,14 @@ public class FormFragment implements ClientElement
private String idParameter;
/**
- * A javascript function that overrides the default visibility search bound.
+ * The name of a javascript function that overrides the default visibility search bound.
* Tapestry normally ensures that not only the form fragment but all parent elements up to the containing body
* are visible when determining whether to submit the contents of a form fragment. This behavior can be modified by
* supplying a javascript function that receives the "current" element in the chain. Returning true will stop the
* search (and report ElementWrapper.deepVisible() as true). Returning false will continue the search up the chain.
*
* @since 5.3
+ * @deprecated Deprecated in 5.4 with no current replacement.
*/
@Parameter(defaultPrefix = BindingConstants.LITERAL, allowNull = false)
private String visibleBound;
@@ -161,7 +162,9 @@ public class FormFragment implements ClientElement
hiddenFieldPositioner = new HiddenFieldPositioner(writer, rules);
- Element element = writer.element(this.element, "id", clientId);
+ Element element = writer.element(this.element,
+ "id", clientId,
+ "data-component-type", "core/FormFragment");
resources.renderInformalParameters(writer);
@@ -170,20 +173,6 @@ public class FormFragment implements ClientElement
element.addClassName(CSSClassConstants.INVISIBLE);
}
- JSONObject spec = new JSONObject("element", clientId);
-
- if (visibleBound != null)
- {
- spec.put("bound", new JSONLiteral(visibleBound));
- }
-
- if (alwaysSubmit)
- {
- spec.put("alwaysSubmit", true);
- }
-
- javascriptSupport.require("core/form-fragment").invoke("initFragment").with(spec);
-
componentActions = new ComponentActionSink(logger, clientDataEncoder);
// Here's the magic of environmentals ... we can create a wrapper around
@@ -223,16 +212,26 @@ public class FormFragment implements ClientElement
*/
void afterRender(MarkupWriter writer)
{
- hiddenFieldPositioner.getElement().attributes("type", "hidden",
+ Element hidden = hiddenFieldPositioner.getElement();
+
+ hidden.attributes("type", "hidden",
"name", Form.FORM_DATA,
- "id", clientId + "-hidden",
"value", componentActions.getClientData());
+ if (!alwaysSubmit)
+ {
+ // Make it possible for the FormFragment to locate the hidden field, even if
+ // FormFragments get nested in some complex way. When the always submit option
+ // is enabled, there's no need for the hidden field to be locatable.
+ hidden.attributes("data-for-fragment", clientId);
+ }
+
writer.end(); // div
+
environment.pop(FormSupport.class);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/654f3ef1/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js b/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
index de4dd63..8af4064 100644
--- a/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
@@ -79,13 +79,13 @@ define("core/compat/tapestry", [
* fragment. The event memo object includes a key, visible, that should be
* true or false.
*/
- CHANGE_VISIBILITY_EVENT: "tapestry:changevisibility",
+ CHANGE_VISIBILITY_EVENT: events.formfragment.changeVisibility,
/**
* Event fired on a form fragment element to hide the element and remove it
* from the DOM.
*/
- HIDE_AND_REMOVE_EVENT: "tapestry:hideandremove",
+ HIDE_AND_REMOVE_EVENT: events.formfragment.remove,
/**
* Event fired on a link or submit to request that it request that the