You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2010/06/20 16:21:15 UTC

svn commit: r956363 - in /myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl: _util/_Dom.js core/_Runtime.js xhrCore/_AjaxResponse.js

Author: werpu
Date: Sun Jun 20 14:21:15 2010
New Revision: 956363

URL: http://svn.apache.org/viewvc?rev=956363&view=rev
Log:
https://issues.apache.org/jira/browse/MYFACES-2762

Modified:
    myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js
    myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js
    myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js

Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js?rev=956363&r1=956362&r2=956363&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js Sun Jun 20 14:21:15 2010
@@ -193,6 +193,15 @@ myfaces._impl.core._Runtime.singletonExt
                     evalNode = evalNode.childNodes[0];
                 }
 
+                if('undefined' == typeof evalNode) {
+                    //fallback for htmlunit which should be good enough
+                    //to run the tests, maybe we have to wrap it as well
+                     dummyPlaceHolder.innerHTML = "<div>" + markup + "</div>";
+                     //note this is triggered only in htmlunit no other browser
+                     //so we are save here
+                     evalNode = dummyPlaceHolder.childNodes[0];
+                }
+
                 parentNode = item.parentNode;
                 item.parentNode.replaceChild(evalNode, item);
 
@@ -732,7 +741,14 @@ myfaces._impl.core._Runtime.singletonExt
     fuzzyFormDetection : function(elem) {
         if (!document.forms || !document.forms.length) {
             return null;
-        } else if (1 == document.forms.length) {
+        }
+
+        // This will not work well on portlet case, because we cannot be sure
+        // the returned form is right one.
+        //we can cover that case by simply adding one of our config params
+        //the default is the weaker, but more correct portlet code
+        //you can override it with myfaces_config.no_portlet_env = true globally
+        else if (1 == document.forms.length && myfaces._impl.core._Runtime.getGlobalConfig("no_portlet_env", false)) {
             return document.forms[0];
         }
         if (!elem) {

Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js?rev=956363&r1=956362&r2=956363&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js Sun Jun 20 14:21:15 2010
@@ -381,7 +381,10 @@ if (!myfaces._impl.core._Runtime) {
                 }
                 holder.appendChild(script);
             } catch (e) {
-
+                //webkit based browsers and probably
+                //other standard conforming browsers forbid head manipulation
+                //after the head tag being closed
+                //we fall back to global eval for those cases
                 return false;
             }
 

Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js?rev=956363&r1=956362&r2=956363&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js Sun Jun 20 14:21:15 2010
@@ -49,8 +49,10 @@ myfaces._impl.core._Runtime.extendClass(
      * @param {function} onWarning
      */
     constructor_: function(onException, onWarning) {
-
-        this.changeTrace = [];
+        //List of non form elements to be updated (which can have forms embedded)
+        this._updateElems = [];
+        // List of forms to be updated if any inner block is updated
+        this._updateForms = [];
         this._onException = onException;
         this._onWarning = onWarning;
 
@@ -155,16 +157,30 @@ myfaces._impl.core._Runtime.extendClass(
         /*namespace remapping*/
         var _Dom = myfaces._impl._util._Dom;
 
+        // Now update the forms that were not replaced but forced to be updated, because contains child ajax tags
+        // we should only update forms with view state hidden field. If by some reason, the form was set to be
+        // updated but the form was replaced, it does not have hidden view state, so later in changeTrace processing the
+        // view state is updated.
+        for (var cnt = 0; cnt < this._updateForms.length; cnt ++) {
+            var formToUpdate = this._updateForms[cnt];
+            var viewStateField = _Dom.findFormElement(formToUpdate, this.P_VIEWSTATE);
+            if (null != viewStateField) {
+                _Dom.setAttribute(viewStateField, "value", this.appliedViewState);
+            }
+        }
+
         //note the spec here says clearly it is done, but mojarra not and there is a corner case
         //regarding cross form submits, hence we should check all processed items for embedded forms
-        for (var cnt = 0; cnt < this.changeTrace.length; cnt ++) {
-            var replacementElem = this.changeTrace[cnt];
+        for (var cnt = 0; cnt < this._updateElems.length; cnt ++) {
+            var replacementElem = this._updateElems[cnt];
             var replacedForms = myfaces._impl._util._Dom.findByTagName(replacementElem, "form", false);
             for (var formCnt = 0; formCnt < replacedForms.length; formCnt++) {
                 //we first have to fetch the real form element because the fragment
                 //might be detached in some browser implementations
                 var appliedReplacedFrom = document.getElementById(replacedForms[formCnt].id);
                 var viewStateField = myfaces._impl._util._Dom.findFormElement(appliedReplacedFrom, this.P_VIEWSTATE);
+                //we have to add the viewstate field in case it is not rendered
+                //otherwise those forms cannot issue another submit
                 if (null == viewStateField) {
                     var element = document.createElement("input");
                     _Dom.setAttribute(element, "type", "hidden");
@@ -262,14 +278,37 @@ myfaces._impl.core._Runtime.extendClass(
     processUpdate : function(request, context, node) {
         /*local namespace remapping*/
         var _Dom = myfaces._impl._util._Dom;
-
+        var _Lang = myfaces._impl._util._Lang;
 
         if (node.getAttribute('id') == this.P_VIEWSTATE) {
             //update the submitting forms viewstate to the new value
             // The source form has to be pulled out of the CURRENT document first because the context object
             // may refer to an invalid document if an update of the entire body has occurred before this point.
             var viewStateValue = node.firstChild.nodeValue;
-            var sourceForm = myfaces._impl._util._Dom.fuzzyFormDetection(context.source);
+            var sourceForm = _Dom.fuzzyFormDetection(context.source);
+            
+            // TODO: After some tests, it was found sourceForm could point to a detached instance, but
+            // there is no harm if we update it. Below there is a code that check if the node has been
+            // detached or not to prevent manipulation. I'm not sure if that code works in all browser
+            // so to prevent introduce bugs, I let it commented with the hope somebody check if let this
+            // code is safe or if it is worth. If it is not detached, without this code we could update
+            // the same input hidden view state twice.
+            //if (null != sourceForm) {
+                // Check if sourceForm is inside the document, or in other words, it was not detached.
+                // We have to walk to the parent node
+                //var _Lang = myfaces._impl._util._Lang;
+                //var searchClosure = function(parentItem) {
+                //    return parentItem && (parentItem == document);
+                //};
+                //var sourceFormAncestor = _Dom.getFilteredParent(sourceForm, searchClosure);
+                //Is not on the document?
+                //if (null == sourceFormAncestor)
+                //{
+                    // Let fixViewStates do the job, because after the blocks are processed, we register
+                    // the target forms to be updated if any.
+                    //sourceForm = null;
+                //}
+            //}
 
             //the source form could be determined absolutely by either the form, the identifier of the node, or the name
             //if only one element is given
@@ -306,8 +345,18 @@ myfaces._impl.core._Runtime.extendClass(
 
             switch (node.getAttribute('id')) {
                 case this.P_VIEWROOT:
-                    this._replaceBody(request, context, cDataBlock);
-
+                    var resultNode = this._replaceBody(request, context, cDataBlock);
+                    if (resultNode) {
+                        var parentForm = _Dom.getParent(resultNode,"form");
+                        if (null != parentForm)
+                        {
+                            this._updateForms.push(parentForm);
+                        }
+                        else
+                        {
+                            this._updateElems.push(resultNode);
+                        }
+                    }
                     break;
                 case this.P_VIEWHEAD:
                     //we cannot replace the head, almost no browser allows this, some of them throw errors
@@ -317,13 +366,32 @@ myfaces._impl.core._Runtime.extendClass(
                     break;
                 case this.P_VIEWBODY:
                     //we assume the cdata block is our body including the tag
-                    this._replaceBody(request, context, cDataBlock);
+                    var resultNode = this._replaceBody(request, context, cDataBlock);
+                    if (resultNode) {
+                        var parentForm = _Dom.getParent(resultNode,"form");
+                        if (null != parentForm)
+                        {
+                            this._updateForms.push(parentForm);
+                        }
+                        else
+                        {
+                            this._updateElems.push(resultNode);
+                        }
+                    }
                     break;
 
                 default:
                     var resultNode = this._replaceElement(request, context, node.getAttribute('id'), cDataBlock);
-                    if ('undefined' != typeof resultNode && null != resultNode) {
-                        this.changeTrace.push(resultNode);
+                    if (resultNode) {
+                        var parentForm = _Dom.getParent(resultNode,"form");
+                        if (null != parentForm)
+                        {
+                            this._updateForms.push(parentForm);
+                        }
+                        else
+                        {
+                            this._updateElems.push(resultNode);
+                        }
                     }
                     break;
             }
@@ -362,12 +430,13 @@ myfaces._impl.core._Runtime.extendClass(
         //and if it fails revert to our internal parser
         var bodyData = parser.parse(newData, "body");
         bodyParent.replaceChild(newBody, oldBody);
-        this._replaceElement(request, context, placeHolder, bodyData);
+        var returnedElement = this._replaceElement(request, context, placeHolder, bodyData);
 
         for (var key in parser.tagAttributes) {
             var value = parser.tagAttributes[key];
             _Dom.setAttribute(newBody, key, value);
         }
+        return returnedElement;
     }
     ,
 
@@ -471,7 +540,15 @@ myfaces._impl.core._Runtime.extendClass(
                     nodeHolder, cDataBlock, null);
 
             if (replacementFragment) {
-                this.changeTrace.push(replacementFragment);
+                var parentForm = _Dom.getParent(replacementFragment,"form");
+                if (parentForm)
+                {
+                    this._updateForms.push(parentForm);
+                }
+                else
+                {
+                    this._updateElems.push(replacementFragment);
+                }
             }
 
         } else {
@@ -490,7 +567,15 @@ myfaces._impl.core._Runtime.extendClass(
                     nodeHolder, cDataBlock, null);
 
             if (replacementFragment) {
-                this.changeTrace.push(replacementFragment);
+                var parentForm = _Dom.getParent(replacementFragment,"form");
+                if (null != parentForm)
+                {
+                    this._updateForms.push(parentForm);
+                }
+                else
+                {
+                    this._updateElems.push(replacementFragment);
+                }
             }
 
         }
@@ -508,8 +593,18 @@ myfaces._impl.core._Runtime.extendClass(
                     _Impl.MALFORMEDXML, "Error in delete, id not in xml markup");
             return false;
         }
-
-        _Dom.deleteItem(deleteId);
+        
+        var item = _Dom.byId(deleteId);
+        if (!item) {
+            throw Error("_AjaxResponse.processDelete  Unknown Html-Component-ID: " + deleteId);
+        }
+        
+        var parentForm = _Dom.getParent(item,"form");
+        if (null != parentForm)
+        {
+            this._updateForms.push(parentForm);
+        }
+        _Dom.deleteItem(item);
 
         return true;
     }