You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by de...@apache.org on 2017/09/17 12:29:36 UTC

[myfaces-trinidad] 06/10: Added DOM replace listener and state change listener support with JSF 2 ajax events

This is an automated email from the ASF dual-hosted git repository.

deki pushed a commit to branch jsf2_ajax
in repository https://gitbox.apache.org/repos/asf/myfaces-trinidad.git

commit 707b01ec44d245c8eacb53548eebc20b87c24686
Author: Andrew Robinson <ar...@apache.org>
AuthorDate: Thu Feb 25 23:43:30 2010 +0000

    Added DOM replace listener and state change listener support with JSF 2 ajax events
---
 .../src/main/webapp/demos/ajaxPPRDemos.xhtml       | 340 +++++++++++----------
 .../main/javascript/META-INF/adf/jsLibs/Page.js    | 104 ++++++-
 2 files changed, 277 insertions(+), 167 deletions(-)

diff --git a/trinidad-examples/trinidad-demo/src/main/webapp/demos/ajaxPPRDemos.xhtml b/trinidad-examples/trinidad-demo/src/main/webapp/demos/ajaxPPRDemos.xhtml
index 46696ce..df31e8f 100644
--- a/trinidad-examples/trinidad-demo/src/main/webapp/demos/ajaxPPRDemos.xhtml
+++ b/trinidad-examples/trinidad-demo/src/main/webapp/demos/ajaxPPRDemos.xhtml
@@ -18,180 +18,190 @@
     under the License.
 
 -->
-<ui:composition
-  xmlns:ui="http://java.sun.com/jsf/facelets"
-  xmlns:h="http://java.sun.com/jsf/html"
-  xmlns:f="http://java.sun.com/jsf/core"
-  xmlns:tr="http://myfaces.apache.org/trinidad"
-  xmlns:trd="http://myfaces.apache.org/trinidad/demo"
-  xmlns:trh="http://myfaces.apache.org/trinidad/html">
-  <h:outputScript name="jsf.js" library="javax.faces" target="body" id="os"/>
-  <tr:document title="Partial Page Rendering Demos">
-    <tr:form>
-
-     <tr:panelPage>
-      <f:facet name="navigationGlobal">
-       <tr:navigationPane hint="buttons">
-        <tr:commandNavigationItem text="Return to Feature Demos page"
-                                immediate="true"
-                                action="demos"/>
-       </tr:navigationPane>
-      </f:facet>
 
-      <tr:panelHeader text="Welcome to the Apache Trinidad Partial Page Rendering Demos for JSF 2.0 Ajax">
-        <tr:outputFormatted styleUsage="instruction" id="of0"
-                            value="These demos test Trinidad PPR with JSF 2.0 Ajax using both
-                            trinidad and JSF components."/>
-        <tr:panelGroupLayout layout="vertical">
-          <f:facet name="separator">
-            <tr:spacer width="30" height="10"/>
-          </f:facet>
-          <tr:panelHeader text="Command components using JSF 2.0 native Ajax support" id="phCmd">
-            <tr:outputFormatted styleUsage="instruction" id="of10"
-                                value="Tests commandButton components wired to use either Ajax JS API
-                                by itself or both JSF 2 Ajax and trinidad PPR. Clicking these buttons
-                                should cause a partial or a full page submit (without errors) and
-                                update the field on the right."/>
-            <tr:spacer height="10" id="sp10"/>
-            <tr:panelGroupLayout layout="horizontal" id="pgl10">
-              <tr:panelGroupLayout layout="vertical" id="pgl11">
+<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
+                xmlns:f="http://java.sun.com/jsf/core" xmlns:tr="http://myfaces.apache.org/trinidad"
+                xmlns:trd="http://myfaces.apache.org/trinidad/demo"
+                xmlns:trh="http://myfaces.apache.org/trinidad/html">
+  <tr:document title="Partial Page Rendering Demos"
+    onload="init();">
+    <f:facet name="metaContainer">
+      <tr:group>
+        <trh:script>
+function pprStateChangeFunction(state)
+{
+  var inputText = document.getElementById("it1");
+  if (inputText.value.length)
+  {
+    inputText.value += "\n";
+  }
+  var stateStr = (state == TrRequestQueue.STATE_READY) ? "ready" : "busy";
+  inputText.value += "State has changed to "+stateStr;
+  inputText.scrollTop = inputText.scrollHeight;
+}
+function pprDomReplacementFunction(oldDom, newDom)
+{
+  var inputText = document.getElementById("it1");
+  if (inputText.value.length)
+  {
+    inputText.value += "\n";
+  }
+  if (newDom === document.body)
+  {
+    inputText.value += "Document body was replaced";
+  }
+  else
+  {
+    inputText.value += "DOM element with ID " +
+      newDom.getAttribute("id") + " was replaced";
+  }
+  inputText.scrollTop = inputText.scrollHeight;
+}
+function init()
+{
+  TrPage.getInstance().getRequestQueue().addStateChangeListener(pprStateChangeFunction);
+  TrPage.getInstance().addDomReplaceListener(pprDomReplacementFunction);
+}
+        </trh:script>
+      </tr:group>
+    </f:facet>
+    <tr:form>
+      <tr:panelPage>
+        <f:facet name="navigationGlobal">
+          <tr:panelGroupLayout id="pgl1" layout="horizontal">
+            <f:facet name="separator">
+              <tr:spacer width="10" />
+            </f:facet>
+            <tr:navigationPane hint="buttons">
+              <tr:commandNavigationItem text="Return to Feature Demos page" immediate="true"
+                                        action="demos"/>
+            </tr:navigationPane>
+            <tr:statusIndicator id="si1" />
+          </tr:panelGroupLayout>
+        </f:facet>
+        <tr:panelHeader text="Welcome to the Apache Trinidad Partial Page Rendering Demos for JSF 2.0 Ajax">
+          <tr:outputFormatted styleUsage="instruction" id="of0"
+                              value="These demos test Trinidad PPR with JSF 2.0 Ajax using both trinidad and JSF components."/>
+          <tr:panelGroupLayout layout="vertical">
+            <f:facet name="separator">
+              <tr:spacer width="30" height="10"/>
+            </f:facet>
+            <tr:panelHeader text="Command components using JSF 2.0 native Ajax support" id="phCmd">
+              <tr:outputFormatted styleUsage="instruction" id="of10"
+                                  value="Tests commandButton components wired to use either Ajax JS API by itself or both JSF 2 Ajax and trinidad PPR. Clicking these buttons should cause a partial or a full page submit (without errors) and update the field on the right."/>
+              <tr:spacer height="10" id="sp10"/>
+              <tr:panelGroupLayout layout="horizontal" id="pgl10">
+                <tr:panelGroupLayout layout="vertical" id="pgl11">
+                  <f:facet name="separator">
+                    <tr:spacer height="6" id="sp11"/>
+                  </f:facet>
+                  <tr:outputFormatted styleUsage="instruction"
+                                      value="tr:commandButton using jsf.ajax.request and partialSubmit=true."
+                                      id="of11"/>
+                  <tr:commandButton id="axBtn1" partialSubmit="true" text="Partial Submit"
+                                    shortDesc="partialSubmit"
+                                    actionListener="#{partialDemoUtil.action}"/>
+                  <!--f:ajax event="action" render=""/-->
+                  <tr:outputFormatted styleUsage="instruction"
+                                      value="tr:commandButton using jsf.ajax.request." id="of12"/>
+                  <tr:commandButton id="axBtn2" text="Full Submit" shortDesc="fullSubmit"
+                                    actionListener="#{partialDemoUtil.action}"/>
+                  <tr:outputFormatted styleUsage="instruction"
+                                      value="h:commandButton using jsf.ajax.request." id="of13"/>
+                </tr:panelGroupLayout>
+                <tr:spacer width="30" height="10" id="sp12"/>
+                <tr:panelGroupLayout id="pgl12">
+                  <tr:panelLabelAndMessage label="Button Clicked: " id="plm10">
+                    <tr:outputFormatted id="btnTarget" partialTriggers="axBtn1 axBtn2"
+                                        styleUsage="instruction"
+                                        value="#{partialDemoUtil.status.linkUpdate}">
+                      <f:convertDateTime pattern="HH:mm:ss"/>
+                    </tr:outputFormatted>
+                  </tr:panelLabelAndMessage>
+                </tr:panelGroupLayout>
+              </tr:panelGroupLayout>
+            </tr:panelHeader>
+            <tr:panelHeader text="InputText Component using JSF 2.0 Ajax" id="phInput">
+              <tr:outputFormatted styleUsage="instruction"
+                                  value="Tests autoSubmitting text fields which is also wired to use JSF 2.0 Ajax."/>
+              <tr:panelGroupLayout layout="horizontal" id="pgl20">
                 <f:facet name="separator">
-                  <tr:spacer height="6" id="sp11"/>
+                  <tr:spacer height="10" id="sp20"/>
                 </f:facet>
-                <tr:outputFormatted styleUsage="instruction" value="tr:commandButton using
-                    jsf.ajax.request and partialSubmit=true." id="of11"/>
-                <tr:commandButton id="axBtn1"
-                                partialSubmit="true"
-                                text="Partial Submit"
-                                shortDesc="partialSubmit"
-                                actionListener="#{partialDemoUtil.action}"/>
-                  <!--f:ajax event="action" render=""/-->
-                <tr:outputFormatted styleUsage="instruction" value="tr:commandButton using jsf.ajax.request."
-                 id="of12"/>
-                <tr:commandButton id="axBtn2"
-                                  text="Full Submit"
-                                  shortDesc="fullSubmit"
-                                  actionListener="#{partialDemoUtil.action}"/>
-
-                <tr:outputFormatted styleUsage="instruction" value="h:commandButton using jsf.ajax.request."
-                 id="of13"/>
-
-
+                <tr:panelGroupLayout layout="vertical" id="pgl21">
+                  <f:facet name="separator">
+                    <tr:spacer height="6" id="sp21"/>
+                  </f:facet>
+                  <tr:outputFormatted styleUsage="instruction"
+                                      value="tr:inputText with autoSubmit=true."
+                                      id="of20"/>
+                  <tr:inputText id="itxt1" autoSubmit="true"
+                                value="#{partialDemoUtil.status.textValue}"
+                                label="Enter text and tab out: "
+                                valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+                  <tr:outputFormatted styleUsage="instruction"
+                                      value="tr:inputText with autoSubmit=true inside a subform"
+                                      id="of21"/>
+                  <tr:subform id="sf20">
+                    <tr:inputText autoSubmit="true" id="itxt2"
+                                  label="Enter a different text and tab out: "
+                                  value="#{partialDemoUtil.status.textValue}"
+                                  valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+                  </tr:subform>
+                </tr:panelGroupLayout>
+                <tr:panelLabelAndMessage label="Input entered: ">
+                  <tr:outputFormatted id="itTarget" partialTriggers="itxt1 ::sf20:itxt2"
+                                      styleUsage="instruction"
+                                      value="#{partialDemoUtil.status.textStateText}"/>
+                </tr:panelLabelAndMessage>
               </tr:panelGroupLayout>
-
-              <tr:spacer width="30" height="10" id="sp12"/>
-
-              <tr:panelGroupLayout id="pgl12">
-                <tr:panelLabelAndMessage label="Button Clicked: " id="plm10">
-                  <tr:outputFormatted id="btnTarget"
-                                     partialTriggers="axBtn1 axBtn2"
-                                     styleUsage="instruction"
-                                     value="#{partialDemoUtil.status.linkUpdate}">
+            </tr:panelHeader>
+            <tr:panelHeader text="Radio Buttons">
+              <tr:outputFormatted styleUsage="instruction"
+                                  value="This demo shows a two sets of radio buttons which use autoSubmit. There is also an output component which is listening on updates to the radio buttons and displaying status text accordingly."/>
+              <tr:panelGroupLayout layout="horizontal">
+                <tr:panelGroupLayout layout="vertical">
+                  <tr:panelGroupLayout layout="horizontal">
+                    <tr:outputFormatted styleUsage="instruction"
+                                        value="selectBooleanRadio buttons"/>
+                    <tr:panelGroupLayout layout="vertical">
+                      <tr:selectBooleanRadio id="sbr1" group="theGroup" selected="false"
+                                             text="item 1" autoSubmit="true"
+                                             valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+                      <tr:selectBooleanRadio id="sbr2" group="theGroup" text="item 2"
+                                             selected="false" autoSubmit="true"
+                                             valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+                      <tr:selectBooleanRadio id="sbr3" group="theGroup" text="item 3"
+                                             selected="false" autoSubmit="true"
+                                             valueChangeListener="#{partialDemoUtil.valueChanged}"/>
+                    </tr:panelGroupLayout>
+                  </tr:panelGroupLayout>
+                  <tr:spacer width="30" height="10"/>
+                  <tr:panelGroupLayout layout="vertical">
+                    <tr:selectOneRadio id="sor1" label="selectOneRadio buttons" autoSubmit="true"
+                                       valueChangeListener="#{partialDemoUtil.valueChanged}">
+                      <tr:selectItem label="item 1" value="1"/>
+                      <tr:selectItem label="item 2" value="2"/>
+                      <tr:selectItem label="item 3" value="3"/>
+                    </tr:selectOneRadio>
+                  </tr:panelGroupLayout>
+                </tr:panelGroupLayout>
+                <tr:spacer width="30" height="10"/>
+                <tr:panelLabelAndMessage label="Selected: ">
+                  <tr:outputFormatted id="rbTarget" partialTriggers="sbr1 sbr2 sbr3 sor1"
+                                      styleUsage="instruction"
+                                      value="#{partialDemoUtil.status.radioStateText}">
                     <f:convertDateTime pattern="HH:mm:ss"/>
                   </tr:outputFormatted>
                 </tr:panelLabelAndMessage>
-             </tr:panelGroupLayout>
-           </tr:panelGroupLayout>
-         </tr:panelHeader>
-
-         <tr:panelHeader text="InputText Component using JSF 2.0 Ajax" id="phInput">
-           <tr:outputFormatted styleUsage="instruction"
-                             value="Tests autoSubmitting text fields which is also wired to use JSF
-                             2.0 Ajax."/>
-            <tr:panelGroupLayout layout="horizontal" id="pgl20">
-              <f:facet name="separator">
-                <tr:spacer height="10" id="sp20"/>
-              </f:facet>
-              <tr:panelGroupLayout layout="vertical" id="pgl21">
-                <f:facet name="separator">
-                  <tr:spacer height="6" id="sp21"/>
-                </f:facet>
-                <tr:outputFormatted styleUsage="instruction" value="tr:inputText with
-                    autoSubmit=true." id="of20"/>
-                <tr:inputText id="itxt1"
-                              autoSubmit="true"
-                              value="#{partialDemoUtil.status.textValue}"
-                              label="Enter text and tab out: "
-                              valueChangeListener="#{partialDemoUtil.valueChanged}"/>
-                <tr:outputFormatted styleUsage="instruction" value="tr:inputText with
-                    autoSubmit=true inside a subform" id="of21"/>
-                <tr:subform id="sf20">
-                  <tr:inputText autoSubmit="true" id="itxt2" label="Enter a different text and tab out: "
-                                 value="#{partialDemoUtil.status.textValue}"
-                                 valueChangeListener="#{partialDemoUtil.valueChanged}"/>
-                </tr:subform>
               </tr:panelGroupLayout>
-
-              <tr:panelLabelAndMessage label="Input entered: ">
-               <tr:outputFormatted id="itTarget"
-                                   partialTriggers="itxt1 ::sf20:itxt2"
-                                   styleUsage="instruction"
-                                   value="#{partialDemoUtil.status.textStateText}"/>
-              </tr:panelLabelAndMessage>
-            </tr:panelGroupLayout>
-         </tr:panelHeader>
-
-         <tr:panelHeader text="Radio Buttons">
-           <tr:outputFormatted styleUsage="instruction"
-                               value="This demo shows a two sets of radio buttons which use autoSubmit.
-                               There is also an output component which is listening on updates to the
-                               radio buttons and displaying status text accordingly."/>
-          <tr:panelGroupLayout layout="horizontal">
-           <tr:panelGroupLayout layout="vertical">
-            <tr:panelGroupLayout layout="horizontal">
-             <tr:outputFormatted styleUsage="instruction"
-                                 value="selectBooleanRadio buttons"/>
-             <tr:panelGroupLayout layout="vertical">
-              <tr:selectBooleanRadio id="sbr1"
-                                     group="theGroup"
-                                     selected="false"
-                                     text="item 1"
-                                     autoSubmit="true"
-                                     valueChangeListener="#{partialDemoUtil.valueChanged}"/>
-              <tr:selectBooleanRadio id="sbr2"
-                                     group="theGroup"
-                                     text="item 2"
-                                     selected="false"
-                                     autoSubmit="true"
-                                     valueChangeListener="#{partialDemoUtil.valueChanged}"/>
-              <tr:selectBooleanRadio id="sbr3"
-                                     group="theGroup"
-                                     text="item 3"
-                                     selected="false"
-                                     autoSubmit="true"
-                                     valueChangeListener="#{partialDemoUtil.valueChanged}"/>
-             </tr:panelGroupLayout>
-            </tr:panelGroupLayout>
-            <tr:spacer width="30" height="10"/>
-            <tr:panelGroupLayout layout="vertical">
-             <tr:selectOneRadio id="sor1"
-                                label="selectOneRadio buttons"
-                                autoSubmit="true"
-                                valueChangeListener="#{partialDemoUtil.valueChanged}">
-              <tr:selectItem label="item 1" value="1" />
-              <tr:selectItem label="item 2" value="2" />
-              <tr:selectItem label="item 3" value="3" />
-             </tr:selectOneRadio>
-            </tr:panelGroupLayout>
-           </tr:panelGroupLayout>
-           <tr:spacer width="30" height="10"/>
-           <tr:panelLabelAndMessage label="Selected: ">
-            <tr:outputFormatted id="rbTarget"
-                                partialTriggers="sbr1 sbr2 sbr3 sor1"
-                                styleUsage="instruction"
-                                value="#{partialDemoUtil.status.radioStateText}">
-             <f:convertDateTime pattern="HH:mm:ss"/>
-            </tr:outputFormatted>
-           </tr:panelLabelAndMessage>
+            </tr:panelHeader>
           </tr:panelGroupLayout>
-         </tr:panelHeader>
-
-
-      </tr:panelGroupLayout>
-     </tr:panelHeader>
-     </tr:panelPage>
-
+          <tr:panelLabelAndMessage id="plam1" label="Ajax Status Log">
+            <tr:inputText id="it1" value="" simple="true" rows="7" columns="100" />
+          </tr:panelLabelAndMessage>
+        </tr:panelHeader>
+      </tr:panelPage>
     </tr:form>
-
   </tr:document>
 </ui:composition>
\ No newline at end of file
diff --git a/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js b/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
index b9fb298..fcc8288 100644
--- a/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
+++ b/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
@@ -802,13 +802,113 @@ TrPage._delegateToJSFAjax = function(formId, inputId, event, params)
 
 TrPage.prototype._jsfAjaxCallback = function(data)
 {
-  if (data.status == "complete")
+  // TODO: move this code into the request queue to stop this gross infringement
+  // of encapsulation
+  switch (data.status)
   {
-    _pprStopBlocking(window);
+    case "begin":
+      this._requestQueue._state = TrRequestQueue.STATE_BUSY;
+      this._requestQueue._broadcastStateChangeEvent(this._requestQueue._state);
+      break;
+    case "success":
+      try
+      {
+        this._notifyDomReplacementListeners(this._ajaxOldDomElements);
+      }
+      finally
+      {
+        delete this._ajaxOldDomElements;
+      }
+      this._requestQueue._state = TrRequestQueue.STATE_READY;
+      this._requestQueue._broadcastStateChangeEvent(this._requestQueue._state);
+      break;
+    case "complete": default:
+      _pprStopBlocking(window);
+      // Collect the DOM elements that will be replaced to be able to fire the
+      // DOM replacement events
+      this._ajaxOldDomElements = this._getDomToBeUpdated(data.responseCode, data.responseXML);
+      break;
   }
 }
 
 TrPage.prototype._jsfAjaxErrorCallback = function(data)
 {
+  // TODO: move this code into the request queue to stop this gross infringement
+  // of encapsulation
+  this._requestQueue._state = TrRequestQueue.STATE_READY;
+  this._requestQueue._broadcastStateChangeEvent(this._requestQueue._state);
+  delete this._ajaxOldDomElements;
+}
+
+TrPage.prototype._notifyDomReplacementListeners = function(dataArray)
+{
+  var listeners = this._domReplaceListeners;
+  if (!listeners || listeners.length == 0)
+  {
+    return;
+  }
+  for (var i = 0, isize = dataArray.length; i < isize; ++i)
+  {
+    var oldElem = dataArray[i].element;
+    var id = dataArray[i].id;
+    var newElem = id == null ? document.body : document.getElementById(id);
+    for (var j = 0, jsize = listeners.length; j < jsize; ++j)
+    {
+      var currListener = listeners[j];
+      var currInstance = listeners[++j];
+      if (currInstance != null)
+      {
+        currListener.call(currInstance, oldElem, newElem);
+      }
+      else
+      {
+        currListener(oldElem, newElem);
+      }
+    }
+  }
+}
+
+TrPage.prototype._getDomToBeUpdated = function(status, responseXML)
+{
+  // check for a successful request
+  if (status < 200 || status >= 300)
+  {
+    return null;
+  }
+  // see if the response contains changes (not a redirect for example)
+  var nodes = responseXML.getElementsByTagName("partial-response");
+  var responseTypeNode = nodes.length ? nodes[0].firstChild : null;
+  if (!responseTypeNode || responseTypeNode.nodeName !== "changes")
+  {
+    return null;
+  }
+
+  var changeNodes = responseTypeNode.childNodes;
+  var oldElements = [];
+  for (var i = 0, size = changeNodes.length; i < size; ++i)
+  {
+    var node = changeNodes[i];
+    if (node.nodeName !== "update")
+    {
+      // We only care about updates as that is what Trinidad supported for the DOM
+      // replacement notification API
+      continue;
+    }
+
+    var id = node.getAttribute("id");
+    if (id == "javax.faces.ViewState")
+    {
+      continue;
+    }
+    if (id == "javax.faces.ViewRoot" || id == "javax.faces.ViewBody")
+    {
+      oldElements.push({ "id": null, "element": document.body });
+    }
+    else
+    {
+      oldElements.push({ "id": id, "element": document.getElementById(id) });
+    }
+  }
 
+  return oldElements;
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
"commits@myfaces.apache.org" <co...@myfaces.apache.org>.