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 2011/09/14 14:56:05 UTC
svn commit: r1170583 [2/3] - in /myfaces/core/branches/2.0.x/api/src:
assembler/ main/javascript/META-INF/resources/myfaces/_impl/_util/
main/javascript/META-INF/resources/myfaces/_impl/core/
main/javascript/META-INF/resources/myfaces/_impl/xhrCore/ ma...
Modified: myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js?rev=1170583&r1=1170582&r2=1170583&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js (original)
+++ myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js Wed Sep 14 12:56:05 2011
@@ -20,752 +20,769 @@
* @memberOf myfaces._impl.xhrCore
* @extends myfaces._impl.xhrCore._FinalizeableObj
* @description
- * This class is responsible for handling the standardized xml ajax response
+ * This singleton is responsible for handling the standardized xml ajax response
+ * Note: since the semantic processing can be handled about 90% in a functional
+ * style we make this class stateless. Every state information is stored
+ * temporarily in the context.
+ *
+ * The singleton approach also improves performance
+ * due to less object gc compared to the old instance approach.
*/
-myfaces._impl.core._Runtime.extendClass("myfaces._impl.xhrCore._AjaxResponse", myfaces._impl.xhrCore._FinalizeableObj,
-/** @lends myfaces._impl.xhrCore._AjaxResponse.prototype */
-{
-
- /*partial response types*/
- RESP_PARTIAL : "partial-response",
- RESP_TYPE_ERROR : "error",
- RESP_TYPE_REDIRECT : "redirect",
- RESP_TYPE_CHANGES : "changes",
-
- /*partial commands*/
- CMD_CHANGES : "changes",
- CMD_UPDATE : "update",
- CMD_DELETE : "delete",
- CMD_INSERT : "insert",
- CMD_EVAL : "eval",
- CMD_ERROR : "error",
- CMD_ATTRIBUTES : "attributes",
- CMD_EXTENSION : "extension",
- CMD_REDIRECT : "redirect",
-
- /*other constants*/
- P_VIEWSTATE: "javax.faces.ViewState",
- P_VIEWROOT: "javax.faces.ViewRoot",
- P_VIEWHEAD: "javax.faces.ViewHead",
- P_VIEWBODY: "javax.faces.ViewBody",
-
-
- /**
- * Standard constructor
- *
- * @param {function} base request classed parent object
- * @param {function} onException
- * @param {function} onWarning
- */
- constructor_: function(onException, onWarning) {
- //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;
-
- this.appliedViewState = null;
-
- this._Lang = myfaces._impl._util._Lang;
- this._Dom = myfaces._impl._util._Dom;
- this._RT = myfaces._impl.core._Runtime;
- this._Impl = this._RT.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
- },
- /**
- * uses response to start Html element replacement
- *
- * @param {Object} request (xhrRequest) - xhr request object
- * @param {Object} context (Map) - AJAX context
- *
- * A special handling has to be added to the update cycle
- * according to the JSDoc specs if the CDATA block contains html tags the outer rim must be stripped
- * if the CDATA block contains a head section the document head must be replaced
- * and if the CDATA block contains a body section the document body must be replaced!
- *
- */
- processResponse : function(request, context) {
- try {
- var _Impl = this._Impl;
-
- // TODO:
- // Solution from
- // http://www.codingforums.com/archive/index.php/t-47018.html
- // to solve IE error 1072896658 when a Java server sends iso88591
- // istead of ISO-8859-1
-
- if (!request) {
- throw Exception(this._Lang.getMessage("ERR_EMPTY_RESPONSE",null,"jsf.ajaxResponse"));
- }
-
- if (!this._Lang.exists(request, "responseXML")) {
- _Impl.sendError(request, context, myfaces._impl.core.Impl.EMPTY_RESPONSE);
- return;
- }
- //check for a parseError under certain browsers
-
- var xmlContent = request.responseXML;
- //ie6+ keeps the parsing response under xmlContent.parserError
- //while the rest of the world keeps it as element under the first node
-
- if (this._Lang.isXMLParseError(xmlContent)) {
- _Impl.sendError(request, context, myfaces._impl.core.Impl.MALFORMEDXML);
- return;
- }
- var partials = xmlContent.childNodes[0];
- if ('undefined' == typeof partials || partials == null) {
- _Impl.sendError(request, context, _Impl.MALFORMEDXML);
- return;
- } else {
- if (partials.tagName != this.RESP_PARTIAL) {
- // IE 8 sees XML Header as first sibling ...
- partials = partials.nextSibling;
- if (!partials || partials.tagName != this.RESP_PARTIAL) {
+myfaces._impl.core._Runtime.singletonExtendClass("myfaces._impl.xhrCore._AjaxResponse", Object,
+ /** @lends myfaces._impl.xhrCore._AjaxResponse.prototype */
+ {
+
+ /*partial response types*/
+ RESP_PARTIAL : "partial-response",
+ RESP_TYPE_ERROR : "error",
+ RESP_TYPE_REDIRECT : "redirect",
+ RESP_TYPE_CHANGES : "changes",
+
+ /*partial commands*/
+ CMD_CHANGES : "changes",
+ CMD_UPDATE : "update",
+ CMD_DELETE : "delete",
+ CMD_INSERT : "insert",
+ CMD_EVAL : "eval",
+ CMD_ERROR : "error",
+ CMD_ATTRIBUTES : "attributes",
+ CMD_EXTENSION : "extension",
+ CMD_REDIRECT : "redirect",
+
+ /*other constants*/
+ P_VIEWSTATE: "javax.faces.ViewState",
+ P_VIEWROOT: "javax.faces.ViewRoot",
+ P_VIEWHEAD: "javax.faces.ViewHead",
+ P_VIEWBODY: "javax.faces.ViewBody",
+
+ _Lang: myfaces._impl._util._Lang,
+ _Dom: myfaces._impl._util._Dom,
+ _RT: myfaces._impl.core._Runtime,
+
+
+ /**
+ * Standard constructor
+ */
+ constructor_: function() {
+
+ }
+ ,
+ /**
+ * uses response to start Html element replacement
+ *
+ * @param {Object} request (xhrRequest) - xhr request object
+ * @param {Object} context (Map) - AJAX context
+ *
+ * A special handling has to be added to the update cycle
+ * according to the JSDoc specs if the CDATA block contains html tags the outer rim must be stripped
+ * if the CDATA block contains a head section the document head must be replaced
+ * and if the CDATA block contains a body section the document body must be replaced!
+ *
+ */
+ processResponse : function(request, context) {
+ //the temporary data is hosted here
+ context._mfInternal._updateElems = [];
+ context._mfInternal._updateForms = [];
+ context._mfInternal.appliedViewState = null;
+
+ try {
+ var _Impl = this._getImpl();
+ var _Lang = this._Lang;
+ // TODO:
+ // Solution from
+ // http://www.codingforums.com/archive/index.php/t-47018.html
+ // to solve IE error 1072896658 when a Java server sends iso88591
+ // istead of ISO-8859-1
+
+ if (!request) {
+ throw Exception(_Lang.getMessage("ERR_EMPTY_RESPONSE", null, "jsf.ajaxResponse"));
+ }
+
+ if (!_Lang.exists(request, "responseXML")) {
+ _Impl.sendError(request, context, myfaces._impl.core.Impl.EMPTY_RESPONSE);
+ return;
+ }
+ //check for a parseError under certain browsers
+
+ var xmlContent = request.responseXML;
+ //ie6+ keeps the parsing response under xmlContent.parserError
+ //while the rest of the world keeps it as element under the first node
+
+ if (_Lang.isXMLParseError(xmlContent)) {
_Impl.sendError(request, context, myfaces._impl.core.Impl.MALFORMEDXML);
return;
}
+ var partials = xmlContent.childNodes[0];
+ if ('undefined' == typeof partials || partials == null) {
+ _Impl.sendError(request, context, _Impl.MALFORMEDXML);
+ return;
+ } else {
+ if (partials.tagName != this.RESP_PARTIAL) {
+ // IE 8 sees XML Header as first sibling ...
+ partials = partials.nextSibling;
+ if (!partials || partials.tagName != this.RESP_PARTIAL) {
+ _Impl.sendError(request, context, myfaces._impl.core.Impl.MALFORMEDXML);
+ return;
+ }
+ }
+ }
+
+ var childNodesLength = partials.childNodes.length;
+
+ for (var loop = 0; loop < childNodesLength; loop++) {
+ var childNode = partials.childNodes[loop];
+ var tagName = childNode.tagName;
+ /**
+ * <eval>
+ * <![CDATA[javascript]]>
+ * </eval>
+ */
+
+ //this ought to be enough for eval
+ //however the run scripts still makes sense
+ //in the update and insert area for components
+ //which do not use the response writer properly
+ //we might add this one as custom option in update and
+ //insert!
+ if (tagName == this.CMD_ERROR) {
+ this.processError(request, context, childNode);
+ return;
+ } else if (tagName == this.CMD_REDIRECT) {
+ if (!this.processRedirect(request, context, childNode)) return;
+ } else if (tagName == this.CMD_CHANGES) {
+ if (!this.processChanges(request, context, childNode)) return;
+ }
+ }
+
+ //fixup missing viewStates due to spec deficiencies
+ this.fixViewStates(context);
+ } catch (e) {
+ context._mfInternal._onException(request, context, "myfaces._impl.xhrCore._AjaxResponse", "processResponse", e);
+ } finally {
+ delete context._mfInternal._updateElems;
+ delete context._mfInternal._updateForms;
+ delete context._mfInternal.appliedViewState;
+ }
+ }
+ ,
+
+ /**
+ * fixes the viewstates in the current page
+ *
+ * @param context
+ */
+ fixViewStates : function(context) {
+
+ if (null == context._mfInternal.appliedViewState) {
+ return;
+ }
+ var _Lang = this._Lang;
+ //if we set our no portlet env we safely can update all forms with
+ //the new viewstate
+ if (this._RT.getLocalOrGlobalConfig(context, "no_portlet_env", false)) {
+ for (var cnt = document.forms.length - 1; cnt >= 0; cnt --) {
+ this._setVSTForm(context, document.forms[cnt]);
+ }
+ return;
+ }
+
+ // 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.
+
+ //set the viewstates of all outer forms parents of our updated elements
+
+ _Lang.arrForEach(context._mfInternal._updateForms,_Lang.hitch(this, function(elem) {
+ this._setVSTForm(context, elem);
+ }), 0, this);
+
+ //set the viewstate of all forms within our updated elements
+ _Lang.arrForEach(context._mfInternal._updateElems,_Lang.hitch(this, function(elem) {
+ this._setVSTInnerForms(context, elem);
+ }), 0, this);
+ }
+ ,
+
+ /**
+ * sets the viewstate element in a given form
+ *
+ * @param theForm the form to which the element has to be set to
+ * @param context the current request context
+ */
+ _setVSTForm: function(context, theForm) {
+ theForm = this._Lang.byId(theForm);
+ if (!theForm) return;
+
+ var viewStateField = (theForm.elements) ? theForm.elements[this.P_VIEWSTATE] : null;//this._Dom.findFormElement(elem, this.P_VIEWSTATE);
+
+ if (viewStateField) {
+ this._Dom.setAttribute(viewStateField, "value", context._mfInternal.appliedViewState);
+ } else if (!viewStateField) {
+ var element = this._Dom.getDummyPlaceHolder();
+ element.innerHTML = ["<input type='hidden'", "id='", this.P_VIEWSTATE ,"' name='", this.P_VIEWSTATE ,"' value='" , context._mfInternal.appliedViewState , "' />"].join("");
+ //now we go to proper dom handling after having to deal with another ie screwup
+ try {
+ theForm.appendChild(element.childNodes[0]);
+ } finally {
+ element.innerHTML = "";
+ }
+ }
+ }
+ ,
+
+ _setVSTInnerForms: function(context, elem) {
+ elem = this._Dom.byIdOrName(elem);
+ var _Lang = this._Lang;
+
+ var replacedForms = this._Dom.findByTagName(elem, "form", false);
+ var applyVST = _Lang.hitch(this, function(elem) {
+ this._setVSTForm(context, elem);
+ });
+
+ try {
+ _Lang.arrForEach(replacedForms, applyVST, 0, this);
+ } finally {
+ delete applyVST;
}
}
+ ,
+
+ /**
+ * processes an incoming error from the response
+ * which is hosted under the <error> tag
+ * @param request the current request
+ * @param context the contect object
+ * @param node the node in the xml hosting the error message
+ */
+ processError : function(request, context, node) {
+ /**
+ * <error>
+ * <error-name>String</error-name>
+ * <error-message><![CDATA[message]]></error-message>
+ * <error>
+ */
+ var errorName = node.firstChild.textContent || "";
+ var errorMessage = node.childNodes[1].firstChild.data || "";
- var childNodesLength = partials.childNodes.length;
+ var _Impl = this._getImpl();
- for (var loop = 0; loop < childNodesLength; loop++) {
- var childNode = partials.childNodes[loop];
- var tagName = childNode.tagName;
+ _Impl.sendError(request, context, myfaces._impl.core.Impl.SERVER_ERROR, errorName, errorMessage);
+ }
+ ,
+
+ /**
+ * processes an incoming xml redirect directive from the ajax response
+ * @param request the request object
+ * @param context the context
+ * @param node the node hosting the redirect data
+ */
+ processRedirect : function(request, context, node) {
/**
- * <eval>
- * <![CDATA[javascript]]>
- * </eval>
+ * <redirect url="url to redirect" />
*/
+ var _Lang = this._Lang;
+ var redirectUrl = node.getAttribute("url");
+ if (!redirectUrl) {
+ var _Impl = this._getImpl();
- //this ought to be enough for eval
- //however the run scripts still makes sense
- //in the update and insert area for components
- //which do not use the response writer properly
- //we might add this one as custom option in update and
- //insert!
- if (tagName == this.CMD_ERROR) {
- this.processError(request, context, childNode);
- return;
- } else if (tagName == this.CMD_REDIRECT) {
- if (!this.processRedirect(request, context, childNode)) return;
- } else if (tagName == this.CMD_CHANGES) {
- if (!this.processChanges(request, context, childNode)) return;
- }
- }
-
- //fixup missing viewStates due to spec deficiencies
- this.fixViewStates(context);
- } catch (e) {
- this._onException(request, context, "myfaces._impl.xhrCore._AjaxResponse", "processResponse", e);
- }
- },
-
- /**
- * fixes the viewstates in the current page
- *
- * @param context
- */
- fixViewStates : function(context) {
-
- if (null == this.appliedViewState) {
- return;
- }
- //if we set our no portlet env we safely can update all forms with
- //the new viewstate
- if (this._RT.getLocalOrGlobalConfig(context, "no_portlet_env", false)) {
- for (var cnt = document.forms.length - 1; cnt >= 0; cnt --) {
- this._setVSTForm(document.forms[cnt]);
- }
- return;
- }
-
- // 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.
-
- //set the viewstates of all outer forms parents of our updated elements
- this._Lang.arrForEach(this._updateForms, this._setVSTForm, 0, this);
-
- //set the viewstate of all forms within our updated elements
- this._Lang.arrForEach(this._updateElems, this._setVSTInnerForms, 0, this);
- },
-
- /**
- * sets the viewstate element in a given form
- *
- * @param theForm the form to which the element has to be set to
- * @param doNotChange if set to true no change is performed if the element is found already to be rendered
- */
- _setVSTForm: function(theForm) {
- theForm = this._Lang.byId(theForm);
- if(!theForm) return;
-
- var viewStateField = (theForm.elements) ? theForm.elements[this.P_VIEWSTATE] : null;//this._Dom.findFormElement(elem, this.P_VIEWSTATE);
-
- if (viewStateField) {
- this._Dom.setAttribute(viewStateField, "value", this.appliedViewState);
- } else if (!viewStateField) {
- var element = this._Dom.getDummyPlaceHolder();
- element.innerHTML = ["<input type='hidden'", "id='", this.P_VIEWSTATE ,"' name='", this.P_VIEWSTATE ,"' value='" , this.appliedViewState , "' />"].join("");
- //now we go to proper dom handling after having to deal with another ie screwup
- try {
- theForm.appendChild(element.childNodes[0]);
- } finally {
- element.innerHTML = "";
- }
- }
- },
-
- _setVSTInnerForms: function(elem) {
- elem = this._Dom.byIdOrName(elem);
- var replacedForms = this._Dom.findByTagName(elem, "form", false);
- var applyVST = this._Lang.hitch(this, function(elem) {
- this._setVSTForm(elem);
- });
-
- try {
- this._Lang.arrForEach(replacedForms, applyVST, 0, this);
- } finally {
- delete applyVST;
- }
- },
-
-
- /**
- * processes an incoming error from the response
- * which is hosted under the <error> tag
- * @param request the current request
- * @param context the contect object
- * @param node the node in the xml hosting the error message
- */
- processError : function(request, context, node) {
- /**
- * <error>
- * <error-name>String</error-name>
- * <error-message><![CDATA[message]]></error-message>
- * <error>
- */
- var errorName = node.firstChild.textContent || "";
- var errorMessage = node.childNodes[1].firstChild.data || "";
-
- var _Impl = this._Impl;
-
- _Impl.sendError(request, context, myfaces._impl.core.Impl.SERVER_ERROR, errorName, errorMessage);
- },
-
- /**
- * processes an incoming xml redirect directive from the ajax response
- * @param request the request object
- * @param context the context
- * @param node the node hosting the redirect data
- */
- processRedirect : function(request, context, node) {
- /**
- * <redirect url="url to redirect" />
- */
- var redirectUrl = node.getAttribute("url");
- if (!redirectUrl) {
- var _Impl = this._Impl;
-
- _Impl.sendError(request, context, myfaces._impl.core.Impl.MALFORMEDXML, myfaces._impl.core.Impl.MALFORMEDXML,this._Lang.getMessage("ERR_RED_URL", null, "_AjaxResponse.processRedirect"));
- return false;
- }
- redirectUrl = this._Lang.trim(redirectUrl);
- if (redirectUrl == "") {
- return false;
- }
- window.location = redirectUrl;
- return true;
- },
-
- /**
- * main entry point for processing the changes
- * it deals with the <changes> node of the
- * response
- *
- * @param request the xhr request object
- * @param context the context map
- * @param node the changes node to be processed
- */
- processChanges : function(request, context, node) {
- var changes = node.childNodes;
-
- //note we need to trace the changes which could affect our insert update or delete
- //se that we can realign our ViewStates afterwards
- //the realignment must happen post change processing
-
- for (var i = 0; i < changes.length; i++) {
-
- switch (changes[i].tagName) {
+ _Impl.sendError(request, context, myfaces._impl.core.Impl.MALFORMEDXML, myfaces._impl.core.Impl.MALFORMEDXML, _Lang.getMessage("ERR_RED_URL", null, "_AjaxResponse.processRedirect"));
+ return false;
+ }
+ redirectUrl = _Lang.trim(redirectUrl);
+ if (redirectUrl == "") {
+ return false;
+ }
+ window.location = redirectUrl;
+ return true;
+ }
+ ,
- case this.CMD_UPDATE:
- if (!this.processUpdate(request, context, changes[i])) {
- return false;
+ /**
+ * main entry point for processing the changes
+ * it deals with the <changes> node of the
+ * response
+ *
+ * @param request the xhr request object
+ * @param context the context map
+ * @param node the changes node to be processed
+ */
+ processChanges : function(request, context, node) {
+ var changes = node.childNodes;
+
+ //note we need to trace the changes which could affect our insert update or delete
+ //se that we can realign our ViewStates afterwards
+ //the realignment must happen post change processing
+
+ for (var i = 0; i < changes.length; i++) {
+
+ switch (changes[i].tagName) {
+
+ case this.CMD_UPDATE:
+ if (!this.processUpdate(request, context, changes[i])) {
+ return false;
+ }
+ break;
+ case this.CMD_EVAL:
+ this._Lang.globalEval(changes[i].firstChild.data);
+ break;
+ case this.CMD_INSERT:
+ if (!this.processInsert(request, context, changes[i])) return false;
+ break;
+ case this.CMD_DELETE:
+ if (!this.processDelete(request, context, changes[i])) return false;
+ break;
+ case this.CMD_ATTRIBUTES:
+ if (!this.processAttributes(request, context, changes[i])) return false;
+ break;
+ case this.CMD_EXTENSION:
+ break;
+ default:
+ var _Impl = this._getImpl();
+ _Impl.sendError(request, context, myfaces._impl.core.Impl.MALFORMEDXML);
+ return false;
}
- break;
- case this.CMD_EVAL:
- this._Lang.globalEval(changes[i].firstChild.data);
- break;
- case this.CMD_INSERT:
- if (!this.processInsert(request, context, changes[i])) return false;
- break;
- case this.CMD_DELETE:
- if (!this.processDelete(request, context, changes[i])) return false;
- break;
- case this.CMD_ATTRIBUTES:
- if (!this.processAttributes(request, context, changes[i])) return false;
- break;
- case this.CMD_EXTENSION:
- break;
- default:
- var _Impl = this._Impl;
- _Impl.sendError(request, context, myfaces._impl.core.Impl.MALFORMEDXML);
- return false;
+ }
+
+ return true;
}
- }
+ ,
+
+ /**
+ * First substep process a pending update tag
+ *
+ * @param request the xhr request object
+ * @param context the context map
+ * @param node the changes node to be processed
+ */
+ processUpdate : function(request, context, node) {
+ 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 elementId = (context._mfInternal) ? context._mfInternal["_mfSourceControlId"] : context.source.id;
+ var sourceForm = (context._mfInternal) ? (document.forms[context._mfInternal["_mfSourceFormId"]] || this._Dom.fuzzyFormDetection(elementId)) : this._Dom.fuzzyFormDetection(elementId);
+ context._mfInternal.appliedViewState = viewStateValue;
+ //source form could not be determined either over the form identifer or the element
+ //we now skip this phase and just add everything we need for the fixup code
+
+ if (!sourceForm) {
+ //no source form found is not an error because
+ //we might be able to recover one way or the other
+ return true;
+ }
- return true;
- },
+ context._mfInternal._updateForms.push(sourceForm.id)
+ //this._setVSTForm(sourceForm);
+ }
+ else {
+ // response may contain several blocks
+ var cDataBlock = this._Dom.concatCDATABlocks(node);
+ var resultNode = null;
+ switch (node.getAttribute('id')) {
+ case this.P_VIEWROOT:
+
+ cDataBlock = cDataBlock.substring(cDataBlock.indexOf("<html"));
+
+ var parsedData = this._replaceHead(request, context, cDataBlock);
+
+ resultNode = ('undefined' != typeof parsedData && null != parsedData) ? this._replaceBody(request, context, cDataBlock, parsedData) : this._replaceBody(request, context, cDataBlock);
+ if (resultNode) {
+ this._pushOperationResult(context, resultNode);
+ }
+ break;
+ case this.P_VIEWHEAD:
+ //we cannot replace the head, almost no browser allows this, some of them throw errors
+ //others simply ignore it or replace it and destroy the dom that way!
+ this._replaceHead(request, context, cDataBlock);
+
+ break;
+ case this.P_VIEWBODY:
+ //we assume the cdata block is our body including the tag
+ resultNode = this._replaceBody(request, context, cDataBlock);
+ if (resultNode) {
+ this._pushOperationResult(context, resultNode);
+ }
+ break;
+
+ default:
+ resultNode = this.replaceHtmlItem(request, context, node.getAttribute('id'), cDataBlock);
+ if (resultNode) {
+ this._pushOperationResult(context, resultNode);
+ }
+ break;
+ }
+ }
- /**
- * First substep process a pending update tag
- *
- * @param request the xhr request object
- * @param context the context map
- * @param node the changes node to be processed
- */
- processUpdate : function(request, context, node) {
- 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 elementId = (context._mfInternal)? context._mfInternal["_mfSourceControlId"] : context.source.id;
- var sourceForm = (context._mfInternal)? (document.forms[context._mfInternal["_mfSourceFormId"]] || this._Dom.fuzzyFormDetection(elementId)) : this._Dom.fuzzyFormDetection(elementId);
- this.appliedViewState = viewStateValue;
- //source form could not be determined either over the form identifer or the element
- //we now skip this phase and just add everything we need for the fixup code
-
- if (!sourceForm) {
- //no source form found is not an error because
- //we might be able to recover one way or the other
return true;
}
+ ,
+
+ _pushOperationResult: function(context, resultNode) {
+ var pushSubnode = this._Lang.hitch(this, function(currNode) {
+ var parentForm = this._Dom.getParent(currNode, "form");
+ //if possible we work over the ids
+ //so that elements later replaced are referenced
+ //at the latest possibility
+ if (null != parentForm) {
+ context._mfInternal._updateForms.push(parentForm.id || parentForm);
+ }
+ else {
+ context._mfInternal._updateElems.push(currNode.id || currNode);
+ }
+ });
+ var isArr = 'undefined' != typeof resultNode.length && 'undefined' == typeof resultNode.nodeType;
+ if (isArr && resultNode.length) {
+ for (var cnt = 0; cnt < resultNode.length; cnt++) {
+ pushSubnode(resultNode[cnt]);
+ }
+ } else if (!isArr) {
+ pushSubnode(resultNode);
+ }
+
+ }
+ ,
+
+ /**
+ * replaces a current head theoretically,
+ * pratically only the scripts are evaled anew since nothing else
+ * can be changed.
+ *
+ * @param request the current request
+ * @param context the ajax context
+ * @param newData the data to be processed
+ *
+ * @return an xml representation of the page for further processing if possible
+ */
+ _replaceHead: function(request, context, newData) {
+
+ var _Impl = this._getImpl();
+ var _Lang = this._Lang;
+ var isWebkit = this._RT.browser.isWebKit;
+
+ //we have to work around an xml parsing bug in Webkit
+ //see https://issues.apache.org/jira/browse/MYFACES-3061
+ var doc = (!isWebkit) ? _Lang.parseXML(newData) : null;
+
+ var newHead = null;
+ if (!isWebkit && _Lang.isXMLParseError(doc)) {
+ doc = _Lang.parseXML(newData.replace(/<!\-\-[\s\n]*<!\-\-/g, "<!--").replace(/\/\/-->[\s\n]*\/\/-->/g, "//-->"));
+ }
- this._updateForms.push(sourceForm.id)
- //this._setVSTForm(sourceForm);
- }
- else {
- // response may contain several blocks
- var cDataBlock = this._Dom.concatCDATABlocks(node);
-
- switch (node.getAttribute('id')) {
- case this.P_VIEWROOT:
-
-
- cDataBlock = cDataBlock.substring(cDataBlock.indexOf("<html"));
-
- var parsedData = this._replaceHead(request, context, cDataBlock);
-
- var resultNode = ('undefined' != typeof parsedData && null != parsedData) ? this._replaceBody(request, context, cDataBlock, parsedData) : this._replaceBody(request, context, cDataBlock);
- if (resultNode) {
- this._pushOperationResult(resultNode);
- }
- break;
- case this.P_VIEWHEAD:
- //we cannot replace the head, almost no browser allows this, some of them throw errors
- //others simply ignore it or replace it and destroy the dom that way!
- this._replaceHead(request, context, cDataBlock);
-
- break;
- case this.P_VIEWBODY:
- //we assume the cdata block is our body including the tag
- var resultNode = this._replaceBody(request, context, cDataBlock);
- if (resultNode) {
- this._pushOperationResult(resultNode);
- }
- break;
-
- default:
- var resultNode = this.replaceHtmlItem(request, context, node.getAttribute('id'), cDataBlock);
- if (resultNode) {
- this._pushOperationResult(resultNode);
- }
- break;
- }
- }
- return true;
- },
-
- _pushOperationResult: function(resultNode) {
- var pushSubnode = this._Lang.hitch(this, function(currNode) {
- var parentForm = this._Dom.getParent(currNode, "form");
- //if possible we work over the ids
- //so that elements later replaced are referenced
- //at the latest possibility
- if (null != parentForm) {
- this._updateForms.push(parentForm.id || parentForm);
- }
- else {
- this._updateElems.push(currNode.id || currNode);
- }
- });
- var isArr = 'undefined' != typeof resultNode.length && 'undefined' == typeof resultNode.nodeType;
- if (isArr && resultNode.length) {
- for (var cnt = 0; cnt < resultNode.length; cnt++) {
- pushSubnode(resultNode[cnt]);
- }
- } else if (!isArr) {
- pushSubnode(resultNode);
- }
-
- },
-
- /**
- * replaces a current head theoretically,
- * pratically only the scripts are evaled anew since nothing else
- * can be changed.
- *
- * @param request the current request
- * @param context the ajax context
- * @param newData the data to be processed
- *
- * @return an xml representation of the page for further processing if possible
- */
- _replaceHead: function(request, context, newData) {
-
- var _Impl = this._Impl;
-
- var isWebkit = this._RT.browser.isWebKit;
-
- //we have to work around an xml parsing bug in Webkit
- //see https://issues.apache.org/jira/browse/MYFACES-3061
- var doc = (!isWebkit)? this._Lang.parseXML(newData) : null;
-
- var newHead = null;
- if (!isWebkit && this._Lang.isXMLParseError(doc)) {
- doc = this._Lang.parseXML(newData.replace(/<!\-\-[\s\n]*<!\-\-/g, "<!--").replace(/\/\/-->[\s\n]*\/\/-->/g, "//-->"));
- }
-
- if (isWebkit || this._Lang.isXMLParseError(doc) ) {
- //the standard xml parser failed we retry with the stripper
- var parser = new (this._RT.getGlobalConfig("updateParser", myfaces._impl._util._HtmlStripper))();
- var headData = parser.parse(newData, "head");
- //We cannot avoid it here, but we have reduced the parsing now down to the bare minimum
- //for further processing
- newHead = this._Lang.parseXML("<head>" + headData + "</head>");
- //last and slowest option create a new head element and let the browser
- //do its slow job
- if (this._Lang.isXMLParseError(newHead)) {
+ if (isWebkit || _Lang.isXMLParseError(doc)) {
+ //the standard xml parser failed we retry with the stripper
+ var parser = new (this._RT.getGlobalConfig("updateParser", myfaces._impl._util._HtmlStripper))();
+ var headData = parser.parse(newData, "head");
+ //We cannot avoid it here, but we have reduced the parsing now down to the bare minimum
+ //for further processing
+ newHead = _Lang.parseXML("<head>" + headData + "</head>");
+ //last and slowest option create a new head element and let the browser
+ //do its slow job
+ if (_Lang.isXMLParseError(newHead)) {
+ try {
+ newHead = document.createElement("head");
+ newHead.innerHTML = headData;
+ } catch (e) {
+ //we give up no further fallbacks
+ _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML, "Error head replacement failed reason:" + e.toString());
+ return null;
+ }
+ }
+ } else {
+ //parser worked we go on
+ newHead = doc.getElementsByTagName("head")[0];
+ }
+
+ this._Dom.runScripts(newHead, true);
+
+ return doc;
+ }
+ ,
+
+
+ /**
+ * special method to handle the body dom manipulation,
+ * replacing the entire body does not work fully by simply adding a second body
+ * and by creating a range instead we have to work around that by dom creating a second
+ * body and then filling it properly!
+ *
+ * @param {Object} request our request object
+ * @param {Object} context (Map) the response context
+ * @param {String} newData the markup which replaces the old dom node!
+ * @param {Node} parsedData (optional) preparsed XML representation data of the current document
+ */
+ _replaceBody : function(request, context, newData /*varargs*/) {
+
+ var oldBody = document.getElementsByTagName("body")[0];
+ var placeHolder = document.createElement("div");
+ var isWebkit = this._RT.browser.isWebKit;
+
+ placeHolder.id = "myfaces_bodyplaceholder";
+
+ this._Dom._removeChildNodes(oldBody);
+ oldBody.innerHTML = "";
+ var newBody = oldBody;
+ var _Lang = this._Lang;
+
+ newBody.appendChild(placeHolder);
+
+ var bodyData = null;
+
+ var doc = null;
+
+ //we have to work around an xml parsing bug in Webkit
+ //see https://issues.apache.org/jira/browse/MYFACES-3061
+ if (!isWebkit) {
+ doc = (arguments.length > 3) ? arguments[3] : _Lang.parseXML(newData);
+ }
+
+ if (!isWebkit && _Lang.isXMLParseError(doc)) {
+ doc = _Lang.parseXML(newData.replace(/<!\-\-[\s\n]*<!\-\-/g, "<!--").replace(/\/\/-->[\s\n]*\/\/-->/g, "//-->"));
+ }
+
+ if (isWebkit || _Lang.isXMLParseError(doc)) {
+ //the standard xml parser failed we retry with the stripper
+
+ var parser = new (this._RT.getGlobalConfig("updateParser", myfaces._impl._util._HtmlStripper))();
+
+ bodyData = parser.parse(newData, "body");
+ } else {
+ //parser worked we go on
+ var newBodyData = doc.getElementsByTagName("body")[0];
+
+ //speedwise we serialize back into the code
+ //for code reduction, speedwise we will take a small hit
+ //there which we will clean up in the future, but for now
+ //this is ok, I guess, since replace body only is a small subcase
+ bodyData = _Lang.serializeChilds(newBodyData);
+
+ if (!this._RT.browser.isIEMobile || this._RT.browser.isIEMobile >= 7) {
+ //TODO check what is failing there
+ for (var cnt = 0; cnt < newBodyData.attributes.length; cnt++) {
+ var value = newBodyData.attributes[cnt].value;
+ if (value)
+ this._Dom.setAttribute(newBody, newBodyData.attributes[cnt].name, value);
+ }
+ }
+ }
+
+ //TODO eliminate the serialisation in case of already having a parsed tree
+ var returnedElement = this.replaceHtmlItem(request, context, placeHolder, bodyData);
+
+ if (returnedElement) {
+ this._pushOperationResult(context, returnedElement);
+ }
+ return returnedElement;
+ }
+ ,
+
+ /**
+ * Replaces HTML elements through others and handle errors if the occur in the replacement part
+ *
+ * @param {Object} request (xhrRequest)
+ * @param {Object} context (Map)
+ * @param {Object} itemIdToReplace (String|Node) - ID of the element to replace
+ * @param {String} markup - the new tag
+ */
+ replaceHtmlItem : function(request, context, itemIdToReplace, markup) {
+ var _Lang = this._Lang;
try {
- newHead = document.createElement("head");
- newHead.innerHTML = headData;
+ var item = (!_Lang.isString(itemIdToReplace)) ? itemIdToReplace :
+ this._Dom.byIdOrName(itemIdToReplace);
+
+ if (!item) {
+ throw Error(_Lang.getMessage("ERR_ITEM_ID_NOTFOUND", null, "_AjaxResponse.replaceHtmlItem", (itemIdToReplace) ? itemIdToReplace.toString() : "undefined"));
+ }
+ return this._Dom.outerHTML(item, markup);
+
} catch (e) {
- //we give up no further fallbacks
- _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML, "Error head replacement failed reason:"+e.toString());
- return null;
- }
- }
- } else {
- //parser worked we go on
- newHead = doc.getElementsByTagName("head")[0];
- }
-
- this._Dom.runScripts(newHead, true);
-
- return doc;
- },
-
-
- /**
- * special method to handle the body dom manipulation,
- * replacing the entire body does not work fully by simply adding a second body
- * and by creating a range instead we have to work around that by dom creating a second
- * body and then filling it properly!
- *
- * @param {Object} request our request object
- * @param {Object} context (Map) the response context
- * @param {String} newData the markup which replaces the old dom node!
- * @param {Node} parsedData (optional) preparsed XML representation data of the current document
- */
- _replaceBody : function(request, context, newData /*varargs*/) {
-
- var oldBody = document.getElementsByTagName("body")[0];
- var placeHolder = document.createElement("div");
- var isWebkit = this._RT.browser.isWebKit;
-
- placeHolder.id = "myfaces_bodyplaceholder";
-
- var bodyParent = oldBody.parentNode;
- this._Dom._removeChildNodes(oldBody);
- oldBody.innerHTML = "";
- var newBody = oldBody;
-
- newBody.appendChild(placeHolder);
-
- var bodyData = null;
-
- var doc = null;
-
- //we have to work around an xml parsing bug in Webkit
- //see https://issues.apache.org/jira/browse/MYFACES-3061
- if(!isWebkit) {
- doc = (arguments.length > 3) ? arguments[3] : this._Lang.parseXML(newData);
- }
-
- if (!isWebkit && this._Lang.isXMLParseError(doc)) {
- doc = this._Lang.parseXML(newData.replace(/<!\-\-[\s\n]*<!\-\-/g, "<!--").replace(/\/\/-->[\s\n]*\/\/-->/g, "//-->"));
- }
-
- if (isWebkit || this._Lang.isXMLParseError(doc)) {
- //the standard xml parser failed we retry with the stripper
-
- var parser = new (this._RT.getGlobalConfig("updateParser", myfaces._impl._util._HtmlStripper))();
-
-
- bodyData = parser.parse(newData, "body");
- } else {
- //parser worked we go on
- var newBodyData = doc.getElementsByTagName("body")[0];
-
- //speedwise we serialize back into the code
- //for code reduction, speedwise we will take a small hit
- //there which we will clean up in the future, but for now
- //this is ok, I guess, since replace body only is a small subcase
- bodyData = this._Lang.serializeChilds(newBodyData);
-
- if (!this._RT.browser.isIEMobile || this._RT.browser.isIEMobile >= 7) {
- //TODO check what is failing there
- for (var cnt = 0; cnt < newBodyData.attributes.length; cnt++) {
- var value = newBodyData.attributes[cnt].value;
- if (value)
- this._Dom.setAttribute(newBody, newBodyData.attributes[cnt].name, value);
- }
- }
- }
-
- //TODO eliminate the serialisation in case of already having a parsed tree
- var returnedElement = this.replaceHtmlItem(request, context, placeHolder, bodyData);
-
- if (returnedElement) {
- this._pushOperationResult(returnedElement);
- }
- return returnedElement;
- },
-
- /**
- * Replaces HTML elements through others and handle errors if the occur in the replacement part
- *
- * @param {Object} request (xhrRequest)
- * @param {Object} context (Map)
- * @param {Object} itemIdToReplace (String|Node) - ID of the element to replace
- * @param {String} markup - the new tag
- */
- replaceHtmlItem : function(request, context, itemIdToReplace, markup) {
- try {
- //TODO make a detachement fixup which tries to replace the item
- //with the correct name upon its parent form if given
-
-
- var origIdentifier = itemIdToReplace;
- var item = (!this._Lang.isString(itemIdToReplace)) ? itemIdToReplace :
- this._Dom.byIdOrName(itemIdToReplace);
-
- if (!item) {
- throw Error(this._Lang.getMessage("ERR_ITEM_ID_NOTFOUND", null,"_AjaxResponse.replaceHtmlItem",(itemIdToReplace)? itemIdToReplace.toString():"undefined"));
- }
- return this._Dom.outerHTML(item, markup);
-
- } catch (e) {
- this._onException(request, context, "myfaces._impl.xhrCore._AjaxResponse", "replaceHTMLItem", e);
- }
- return null;
- }
- ,
-
- /*insert, three attributes can be present
- * id = insert id
- * before = before id
- * after = after id
- *
- * the insert id is the id of the node to be inserted
- * the before is the id if set which the component has to be inserted before
- * the after is the id if set which the component has to be inserted after
- **/
- processInsert : function(request, context, node) {
- /*remapping global namespaces for speed and readability reasons*/
- var _Impl = this._Impl;
- var _Dom = this._Dom;
- var _Lang = this._Lang;
-
- var insertId = node.getAttribute('id');
- var beforeId = node.getAttribute('before');
- var afterId = node.getAttribute('after');
-
- var isInsert = insertId && this._Lang.trim(insertId) != "";
- var isBefore = beforeId && this._Lang.trim(beforeId) != "";
- var isAfter = afterId && this._Lang.trim(afterId) != "";
-
- if (!isInsert) {
- _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML,this._Lang.getMessage("ERR_PPR_IDREQ"));
- return false;
- }
- if (!(isBefore || isAfter)) {
- _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML,this._Lang.getMessage("ERR_PPR_INSERTBEFID"));
- return false;
- }
- //either before or after but not two at the same time
- var nodeHolder = null;
- var parentNode = null;
-
-
- var cDataBlock = this._Dom.concatCDATABlocks(node);
-
- var replacementFragment;
- if (isBefore) {
- beforeId = this._Lang.trim(beforeId);
- var beforeNode = this._Dom.byIdOrName(beforeId);
- if (!beforeNode) {
- _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML,this._Lang.getMessage("ERR_PPR_INSERTBEFID_1", null,"_AjaxResponse.processInsert",beforeId));
- return false;
- }
- /**
- *we generate a temp holder
- *so that we can use innerHTML for
- *generating the content upfront
- *before inserting it"
+ context._mfInternal._onException(request, context, "myfaces._impl.xhrCore._AjaxResponse", "replaceHTMLItem", e);
+ }
+ return null;
+ }
+ ,
+
+ /*insert, three attributes can be present
+ * id = insert id
+ * before = before id
+ * after = after id
+ *
+ * the insert id is the id of the node to be inserted
+ * the before is the id if set which the component has to be inserted before
+ * the after is the id if set which the component has to be inserted after
**/
- nodeHolder = document.createElement("div");
- parentNode = beforeNode.parentNode;
- parentNode.insertBefore(nodeHolder, beforeNode);
- replacementFragment = this.replaceHtmlItem(request, context,
- nodeHolder, cDataBlock);
- if (replacementFragment) {
- this._pushOperationResult(replacementFragment);
- }
-
- } else {
- afterId = this._Lang.trim(afterId);
- var afterNode = this._Dom.byIdOrName(afterId);
- if (!afterNode) {
- _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML, this._Lang.getMessage("ERR_PPR_INSERTBEFID_2", null,"_AjaxResponse.processInsert", afterId));
- return false;
- }
-
- nodeHolder = document.createElement("div");
- parentNode = afterNode.parentNode;
-
- //TODO nextsibling not working in ieMobile 6.1 we have to change the method
- //of accessing it to something else
- parentNode.insertBefore(nodeHolder, afterNode.nextSibling);
-
- replacementFragment = this.replaceHtmlItem(request, context,
- nodeHolder, cDataBlock);
-
- if (replacementFragment) {
- this._pushOperationResult(replacementFragment);
- }
-
- }
- return true;
- }
- ,
-
- processDelete : function(request, context, node) {
- var _Impl = this._Impl;
-
- var deleteId = node.getAttribute('id');
- if (!deleteId) {
- _Impl.sendError(request, context, _Impl.MALFORMEDXML,
- _Impl.MALFORMEDXML,this._Lang.getMessage("ERR_PPR_DELID", null,"_AjaxResponse.processDelete"));
- return false;
- }
-
- var item = this._Dom.byIdOrName(deleteId);
- if (!item) {
- throw Error(this._Lang.getMessage("ERR_PPR_UNKNOWNCID", null,"_AjaxResponse.processDelete",deleteId));
- }
-
- var parentForm = this._Dom.getParent(item, "form");
- if (null != parentForm) {
- this._updateForms.push(parentForm);
- }
- this._Dom.deleteItem(item);
-
- return true;
- }
- ,
-
- processAttributes : function(request, context, node) {
- //we now route into our attributes function to bypass
- //IE quirks mode incompatibilities to the biggest possible extent
- //most browsers just have to do a setAttributes but IE
- //behaves as usual not like the official standard
- //myfaces._impl._util.this._Dom.setAttribute(domNode, attribute, value;
-
- var _Impl = this._Impl;
-
- //<attributes id="id of element"> <attribute name="attribute name" value="attribute value" />* </attributes>
- var elemId = node.getAttribute('id');
- if (!elemId) {
- _Impl.sendError(request, context, _Impl.MALFORMEDXML
- , _Impl.MALFORMEDXML, "Error in attributes, id not in xml markup");
- return false;
- }
- var childNodes = node.childNodes;
-
- if (!childNodes) {
- return false;
- }
- for (var loop2 = 0; loop2 < childNodes.length; loop2++) {
- var attributesNode = childNodes[loop2];
-
- var attrName = attributesNode.getAttribute("name");
- var attrValue = attributesNode.getAttribute("value");
-
- if (!attrName) {
- continue;
- }
-
- attrName = this._Lang.trim(attrName);
- /*no value means reset*/
- //value can be of boolean value hence full check
- if ('undefined' == typeof attrValue || null == attrValue) {
- attrValue = "";
- }
-
- switch (elemId) {
- case this.P_VIEWROOT:
- throw new Error(this._Lang.getMessage("ERR_NO_VIEWROOTATTR", null,"_AjaxResponse.processAttributes"));
- break;
-
- case this.P_VIEWHEAD:
- throw new Error(this._Lang.getMessage("ERR_NO_HEADATTR", null,"_AjaxResponse.processAttributes"));
- break;
-
- case this.P_VIEWBODY:
- var element = document.getElementsByTagName("body")[0];
- this._Dom.setAttribute(element, attrName, attrValue);
- break;
-
- default:
- this._Dom.setAttribute(document.getElementById(elemId), attrName, attrValue);
- break;
- }
-
- }
- return true;
- },
- _finalize: function() {
- delete this._onException;
- delete this._onWarning;
- delete this._updateElems;
- // List of forms to be updated if any inner block is updated
- delete this._updateForms;
- delete this.appliedViewState;
- }
+ processInsert : function(request, context, node) {
+ /*remapping global namespaces for speed and readability reasons*/
+ var _Impl = this._getImpl();
+ var _Lang = this._Lang;
+
+ var insertId = node.getAttribute('id');
+ var beforeId = node.getAttribute('before');
+ var afterId = node.getAttribute('after');
+
+ var isInsert = insertId && _Lang.trim(insertId) != "";
+ var isBefore = beforeId && _Lang.trim(beforeId) != "";
+ var isAfter = afterId && _Lang.trim(afterId) != "";
+
+ if (!isInsert) {
+ _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML, this._Lang.getMessage("ERR_PPR_IDREQ"));
+ return false;
+ }
+ if (!(isBefore || isAfter)) {
+ _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML, this._Lang.getMessage("ERR_PPR_INSERTBEFID"));
+ return false;
+ }
+ //either before or after but not two at the same time
+ var nodeHolder = null;
+ var parentNode = null;
+
+ var cDataBlock = this._Dom.concatCDATABlocks(node);
+
+ var replacementFragment;
+ if (isBefore) {
+ beforeId = _Lang.trim(beforeId);
+ var beforeNode = this._Dom.byIdOrName(beforeId);
+ if (!beforeNode) {
+ _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML, this._Lang.getMessage("ERR_PPR_INSERTBEFID_1", null, "_AjaxResponse.processInsert", beforeId));
+ return false;
+ }
+ /**
+ *we generate a temp holder
+ *so that we can use innerHTML for
+ *generating the content upfront
+ *before inserting it"
+ **/
+ nodeHolder = document.createElement("div");
+ parentNode = beforeNode.parentNode;
+ parentNode.insertBefore(nodeHolder, beforeNode);
+ replacementFragment = this.replaceHtmlItem(request, context,
+ nodeHolder, cDataBlock);
+ if (replacementFragment) {
+ this._pushOperationResult(context, replacementFragment);
+ }
+
+ } else {
+ afterId = _Lang.trim(afterId);
+ var afterNode = this._Dom.byIdOrName(afterId);
+ if (!afterNode) {
+ _Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML, this._Lang.getMessage("ERR_PPR_INSERTBEFID_2", null, "_AjaxResponse.processInsert", afterId));
+ return false;
+ }
+
+ nodeHolder = document.createElement("div");
+ parentNode = afterNode.parentNode;
+
+ //TODO nextsibling not working in ieMobile 6.1 we have to change the method
+ //of accessing it to something else
+ parentNode.insertBefore(nodeHolder, afterNode.nextSibling);
+
+ replacementFragment = this.replaceHtmlItem(request, context,
+ nodeHolder, cDataBlock);
+
+ if (replacementFragment) {
+ this._pushOperationResult(context, replacementFragment);
+ }
+
+ }
+ return true;
+ }
+ ,
+
+ processDelete : function(request, context, node) {
+ var _Impl = this._getImpl();
+ var _Lang = this._Lang;
+
+ var deleteId = node.getAttribute('id');
+ if (!deleteId) {
+ _Impl.sendError(request, context, _Impl.MALFORMEDXML,
+ _Impl.MALFORMEDXML, _Lang.getMessage("ERR_PPR_DELID", null, "_AjaxResponse.processDelete"));
+ return false;
+ }
+
+ var item = this._Dom.byIdOrName(deleteId);
+ if (!item) {
+ throw Error(_Lang.getMessage("ERR_PPR_UNKNOWNCID", null, "_AjaxResponse.processDelete", deleteId));
+ }
+
+ var parentForm = this._Dom.getParent(item, "form");
+ if (null != parentForm) {
+ context._mfInternal._updateForms.push(parentForm);
+ }
+ this._Dom.deleteItem(item);
+
+ return true;
+ }
+ ,
+
+ processAttributes : function(request, context, node) {
+ //we now route into our attributes function to bypass
+ //IE quirks mode incompatibilities to the biggest possible extent
+ //most browsers just have to do a setAttributes but IE
+ //behaves as usual not like the official standard
+ //myfaces._impl._util.this._Dom.setAttribute(domNode, attribute, value;
+
+ var _Impl = this._getImpl();
+ var _Lang = this._Lang;
+ //<attributes id="id of element"> <attribute name="attribute name" value="attribute value" />* </attributes>
+ var elemId = node.getAttribute('id');
+ if (!elemId) {
+ _Impl.sendError(request, context, _Impl.MALFORMEDXML
+ , _Impl.MALFORMEDXML, "Error in attributes, id not in xml markup");
+ return false;
+ }
+ var childNodes = node.childNodes;
+
+ if (!childNodes) {
+ return false;
+ }
+ for (var loop2 = 0; loop2 < childNodes.length; loop2++) {
+ var attributesNode = childNodes[loop2];
+
+ var attrName = attributesNode.getAttribute("name");
+ var attrValue = attributesNode.getAttribute("value");
+
+ if (!attrName) {
+ continue;
+ }
+
+ attrName = _Lang.trim(attrName);
+ /*no value means reset*/
+ //value can be of boolean value hence full check
+ if ('undefined' == typeof attrValue || null == attrValue) {
+ attrValue = "";
+ }
+
+ switch (elemId) {
+ case this.P_VIEWROOT:
+ throw new Error(_Lang.getMessage("ERR_NO_VIEWROOTATTR", null, "_AjaxResponse.processAttributes"));
+ break;
+
+ case this.P_VIEWHEAD:
+ throw new Error(_Lang.getMessage("ERR_NO_HEADATTR", null, "_AjaxResponse.processAttributes"));
+ break;
+
+ case this.P_VIEWBODY:
+ var element = document.getElementsByTagName("body")[0];
+ this._Dom.setAttribute(element, attrName, attrValue);
+ break;
+
+ default:
+ this._Dom.setAttribute(document.getElementById(elemId), attrName, attrValue);
+ break;
+ }
+
+ }
+ return true;
+ },
+
+ _getImpl: function() {
+ if(!this._Impl) {
+ this._Impl = this._RT.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+ }
+ return this._Impl;
+ }
-});
+ })
+ ;
Modified: myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxUtils.js
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxUtils.js?rev=1170583&r1=1170582&r2=1170583&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxUtils.js (original)
+++ myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxUtils.js Wed Sep 14 12:56:05 2011
@@ -17,24 +17,20 @@
* @class
* @name _AjaxUtils
* @memberOf myfaces._impl.xhrCore
- * @extends myfaces._impl.xhrCore._FinalizeableObj
* @description
*
* A set of helper routines which are utilized within our Ajax subsystem and nowhere else
+ *
+ * TODO move this into a singleton, the current structure is
+ * still a j4fry legacy we need to get rid of it in the long run
*/
-myfaces._impl.core._Runtime.extendClass("myfaces._impl.xhrCore._AjaxUtils", myfaces._impl.xhrCore._FinalizeableObj,
+myfaces._impl.core._Runtime.singletonExtendClass("myfaces._impl.xhrCore._AjaxUtils", Object,
/** @lends myfaces._impl.xhrCore._AjaxUtils.prototype */
{
- _processedExceptions: {},
-
/**
* Constructor
- * @param {function} onException - exception handler
- * @param {function} onWarning - warning handler
*/
- constructor_ : function(onException, onWarning) {
- this._onException = onException;
- this._onWarning = onWarning;
+ constructor_ : function() {
},
@@ -51,7 +47,7 @@ myfaces._impl.core._Runtime.extendClass(
try {
if (!parentItem) {
- this._onWarning(request, context, "myfaces._impl.xhrCore._AjaxUtils", "encodeSubmittableFields " + "Html-Component is not nested in a Form-Tag");
+ context._mfInternal._onWarning(request, context, "myfaces._impl.xhrCore._AjaxUtils", "encodeSubmittableFields " + "Html-Component is not nested in a Form-Tag");
return null;
}
@@ -67,7 +63,7 @@ myfaces._impl.core._Runtime.extendClass(
this.appendIssuingItem(item, targetBuf);
} catch (e) {
- this._onException(request, context, "myfaces._impl.xhrCore._AjaxUtils", "encodeSubmittableFields", e);
+ context._mfInternal._onException(request, context, "myfaces._impl.xhrCore._AjaxUtils", "encodeSubmittableFields", e);
}
},
@@ -235,11 +231,5 @@ myfaces._impl.core._Runtime.extendClass(
}
}
- },
-
- _finalize: function() {
- delete this._onException;
- delete this._onWarning;
}
-
});
\ No newline at end of file
Modified: myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_FinalizeableObj.js
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_FinalizeableObj.js?rev=1170583&r1=1170582&r2=1170583&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_FinalizeableObj.js (original)
+++ myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_FinalizeableObj.js Wed Sep 14 12:56:05 2011
@@ -17,6 +17,12 @@
* Author: Werner Punz (latest modification by $Author: werpu $)
* Version: $Revision: 1.4 $ $Date: 2009/05/31 09:16:44 $
*/
+/**
+ * @memberOf myfaces._impl
+ * @namespace
+ * @name xhrCore
+ */
+
/**
* @class
@@ -37,6 +43,10 @@ myfaces._impl.core._Runtime.extendClass(
constructor_: function() {
this._resettableContent={};
+ //we add our three util singletons
+ this._RT = myfaces._impl.core._Runtime;
+ this._Lang = myfaces._impl._util._Lang;
+ this._Dom = myfaces._impl._util._Dom;
},
_initDefaultFinalizableFields: function() {
Modified: myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_IFrameRequest.js
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_IFrameRequest.js?rev=1170583&r1=1170582&r2=1170583&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_IFrameRequest.js (original)
+++ myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_IFrameRequest.js Wed Sep 14 12:56:05 2011
@@ -14,36 +14,18 @@
* limitations under the License.
*/
+
/**
* @class
- * @name _IFrameRequest
+ * @name _AjaxRequest
* @memberOf myfaces._impl.xhrCore
- * @extends myfaces._impl.xhrCore._BaseRequest
- * @description
- * iframe transport for an alternative way to do ajax communication
- * <p />
- * The idea to make a frame a protocol transport is, to make a form submit
- * with the iframe as target, and once done use the result in the iframe
- * as result for the request.
- *
- * <p />
- * This method can be used by older browsers and if you have
- * a multipart request which includes
- * a fileupload element, fileuploads cannot be handled by
- * normal xhr requests. The standard html 4+ compliant way to do this
- * is to use an iframe as submit target for a form.
- * <p />
- * Note on almost all browsers this method induces a real asynchronity, the only
- * exception is firefox 3.6- which blocks the ui, this is resolved in Firefox 4
+ * @extends myfaces._impl.xhrCore._FinalizeableObj
+ * @description specialized implementation of the jsf js ajax request class
+ * which utilizes an iframe transport for communications to the server
*/
-myfaces._impl.core._Runtime.extendClass("myfaces._impl.xhrCore._IFrameRequest", myfaces._impl.xhrCore._BaseRequest,
-/** @lends myfaces._impl.xhrCore._IFrameRequest */
-{
-
- _FRAME_ID: "_mf_comm_frm",
- _frame: null,
- _RT: myfaces._impl.core._Runtime,
- CLS_NAME: "myfaces._impl.xhrCore._IFrameRequest",
+myfaces._impl.core._Runtime.extendClass("myfaces._impl.xhrCore._IFrameRequest", myfaces._impl.xhrCore._AjaxRequest,
+ /** @lends myfaces._impl.xhrCore._IFrameRequest.prototype */
+ {
/**
* @constant
@@ -56,254 +38,25 @@ myfaces._impl.core._Runtime.extendClass(
*/
MF_PART_IFRAME: "org.apache.myfaces.partial.iframe",
- /**
- * constructor which shifts the arguments
- * to the protected properties of this clas
- *
- * @param arguments
- */
constructor_: function(arguments) {
- try {
- //we fetch in the standard arguments
- this._callSuper("constructor", arguments);
- this._Lang.applyArgs(this, arguments);
-
- if (!this._response) {
- this._response = new myfaces._impl.xhrCore._AjaxResponse(this._onException, this._onWarning);
- }
- this._ajaxUtil = new myfaces._impl.xhrCore._AjaxUtils(this._onException, this._onWarning);
- } catch (e) {
- //_onError
- this._onException(null, this._context, this.CLS_NAME, "constructor", e);
- }
- },
-
- /**
- * send method, central callback which sends the
- * request
- */
- send: function() {
- var _Impl = this._getImpl();
- var _RT = myfaces._impl.core._Runtime;
-
- this._frame = this._createTransportFrame();
-
- //we append an onload handler to the frame
- //to cover the starting and loading events,
- //timeouts cannot be covered in a cross browser way
-
- //we point our onload handler to the frame, we do not use addOnLoad
- //because the frame should not have other onload handlers in place
- if (!_RT.browser.isIE) {
- this._frame.onload = this._Lang.hitch(this, this.callback);
- } else {
- //ie has a bug, onload is not settable outside of innerHTML on iframes
- this._frame.onload_IE = this._Lang.hitch(this, this.callback);
- }
-
- //now to the parameter passing:
- _Impl.sendEvent(this._xhr, this._context, _Impl.BEGIN);
-
- //viewstate should be in our parent form which we will isse we however have to add the execute and
- //render parameters as well as the usual javax.faces.request params to our target
-
- var oldTarget = this._sourceForm.target;
- var oldMethod = this._sourceForm.method;
- var _progress = 0;
- var _srcFrm = this._sourceForm;
- try {
- this._initAjaxParams();
- _srcFrm.target = this._frame.name;
- _srcFrm.method = this._ajaxType;
- _srcFrm.submit();
- } finally {
- this._removeAjaxParams(oldTarget);
- _srcFrm.target = oldTarget;
- _srcFrm.method = oldMethod;
- }
- },
-
- /**
- * the callback function after the request is done
- */
- callback: function() {
- //now we have to do the processing, for that we have to parse the result, if it is a http 404 then
- //nothing could be delivered and we bomb out with an error anything else has to be parsed
- //via our xml parser
- var request = {};
- try {
- request.responseText = this._getFrameText();
- request.responseXML = this._getFrameXml();
- request.readyState = this._READY_STATE_DONE;
- this._xhr = request;
- this._onDone(request, this._context);
-
- if (!this._Lang.isXMLParseError(request.responseXML)) {
- request.status = 201;
- this._onSuccess();
- } else {
- request.status = 0;
- //we simulate the request for our xhr call
- this._onError();
-
- }
- } catch (e) {
- //_onError
- this._onException(request, this._context, this.CLS_NAME, "constructor", e);
- } finally {
- //this closes any hanging or pending comm channel caused by the iframe
- this._clearFrame();
- this._frame = null;
- this._xhr = null;
- }
- },
-
- /**
- * returns the frame text in a browser independend manner
- */
- _getFrameDocument: function() {
- //we cover various browsers here, because almost all browsers keep the document in a different
- //position
- return this._frame.contentWindow.document || this._frame.contentDocument || this._frame.document ;
+ this._callSuper("constructor_", arguments);
},
- _getFrameText: function() {
- var framedoc = this._getFrameDocument();
- //also ie keeps the body in framedoc.body the rest in documentElement
- var body = framedoc.body || framedoc.documentElement ;
- return body.innerHTML;
- },
-
- _clearFrame: function() {
- var framedoc = this._getFrameDocument();
- var body = framedoc.documentElement || framedoc.body;
- //ie8 in 7 mode chokes on the innerHTML method
- //direct dom removal is less flakey and works
- //over all browsers, but is slower
- this._Dom._removeChildNodes(body, false);
- },
-
- /**
- * returns the processed xml from the frame
- */
- _getFrameXml: function() {
- var framedoc = this._getFrameDocument();
- //same situation here, the xml is hosted either in xmlDocument or
- //is located directly under the frame document
- return framedoc.XMLDocument || framedoc;
- },
-
-
- _initAjaxParams: function() {
- var _Impl = this._getImpl();
- //this._appendHiddenValue(_Impl.P_AJAX, "");
- var appendHiddenValue = this._Lang.hitch(this, this._appendHiddenValue);
- for (var key in this._passThrough) {
-
- appendHiddenValue(key, this._passThrough[key]);
- }
+ getFormData: function() {
+ var ret = new myfaces._impl.xhrCore.engine.FormData(this._sourceForm);
//marker that this is an ajax iframe request
- appendHiddenValue(this.JX_PART_IFRAME, "true");
- appendHiddenValue(this.MF_PART_IFRAME, "true");
-
- },
-
-
- _removeAjaxParams: function(oldTarget) {
- var _Impl = this._getImpl();
- this._sourceForm.target = oldTarget;
- //some browsers optimize this and loose their scope that way,
- //I am still not sure why, but probably because the function itself
- //was called under finally and I ran into a bug in the fox 4
- //scripting engine
- var toDelete = [];
- var possibleKeys = {};
- for(var key in this._passThrough) {
- possibleKeys[key] = true;
- }
- possibleKeys[this.JX_PART_IFRAME] = true;
- possibleKeys[this.MF_PART_IFRAME] = true;
- (possibleKeys["javax.faces.ViewState"])? delete possibleKeys["javax.faces.ViewState"]:null;
-
- for(var cnt = this._sourceForm.elements.length -1; cnt >= 0; cnt--) {
- var elem = this._sourceForm.elements[cnt];
- if(possibleKeys[elem.name] && elem.type == "hidden") {
- elem.parentNode.removeChild(elem);
- delete elem;
- }
- }
+ ret.append(this.JX_PART_IFRAME, "true");
+ ret.append(this.MF_PART_IFRAME, "true");
+ return ret;
},
- _appendHiddenValue: function(key, value) {
- if ('undefined' == typeof value) {
- return;
- }
- var input = document.createElement("input");
- //the dom is a singleton nothing can happen by remapping
- this._Dom.setAttribute(input, "type", "hidden");
- this._Dom.setAttribute(input, "name", key);
- this._Dom.setAttribute(input, "style", "display:none");
- this._Dom.setAttribute(input, "value", value);
- this._sourceForm.appendChild(input);
- },
-
- _removeHiddenValue: function(key) {
- var elem = this._Dom.findByName(this._sourceForm, key, true);
- if (elem.length) {
-
- elem[0].parentNode.removeChild(elem[0]);
- delete elem[0];
- }
+ _formDataToURI: function(formData) {
+ //http get alwyays sends the form data
+ return "";
},
- _createTransportFrame: function() {
- var _RT = this._RT;
- var frame = document.getElementById(this._FRAME_ID);
- //normally this code should not be called
- //but just to be sure
- if (!frame) {
- if (!_RT.browser.isIE) {
- frame = document.createElement('iframe');
-
- //probably the ie method would work on all browsers
- //but this code is the safe bet it works on all standards
- //compliant browsers in a clean manner
-
- this._Dom.setAttribute(frame, "src", "about:blank");
- this._Dom.setAttribute(frame, "id", this._FRAME_ID);
- this._Dom.setAttribute(frame, "name", this._FRAME_ID);
- this._Dom.setAttribute(frame, "type", "content");
- this._Dom.setAttribute(frame, "collapsed", "true");
- this._Dom.setAttribute(frame, "style", "display:none");
-
- document.body.appendChild(frame);
- } else { //Now to the non compliant browsers
- var node = document.createElement("div");
- this._Dom.setAttribute(node, "style", "display:none");
- //we are dealing with two well known iframe ie bugs here
- //first the iframe has to be set via innerHTML to be present
- //secondly the onload handler is immutable on ie, we have to
- //use a dummy onload handler in this case and call that one
- //from the onload handler
- node.innerHTML = "<iframe id='" + this._FRAME_ID + "' name='" + this._FRAME_ID + "' style='display:none;' src='about:blank' type='content' onload='this.onload_IE();' ></iframe>";
-
- //avoid the ie open tag problem
- var body = document.body;
- if (body.firstChild) {
- body.insertBefore(node, document.body.firstChild);
- } else {
- body.appendChild(node);
- }
- }
-
- }
- //helps to for the onload handlers and innerhtml to be in sync again
- return document.getElementById(this._FRAME_ID);
-
+ _getTransport: function() {
+ return new myfaces._impl.xhrCore.engine.IFrame();
}
- //TODO pps, the idea behind pps is to generate another form
- // and temporarily shift the elements over which have to be
- // ppsed, but it is up for discussion if we do pps at all in case of
- // an iframe, so I wont implement anything for now
});
\ No newline at end of file
Modified: myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_Transports.js
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_Transports.js?rev=1170583&r1=1170582&r2=1170583&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_Transports.js (original)
+++ myfaces/core/branches/2.0.x/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_Transports.js Wed Sep 14 12:56:05 2011
@@ -224,10 +224,14 @@ myfaces._impl.core._Runtime.extendClass(
/**
* Spec. 13.3.3
* Examining the response markup and updating the DOM tree
- * @param {XmlHttpRequest} request - the ajax request
- * @param {XmlHttpRequest} context - the ajax context
+ * @param {XMLHttpRequest} request - the ajax request
+ * @param {Object} context - the ajax context
*/
response : function(request, context) {
+
+ //TODO we can eliminate this method in favor of an impl specific code where
+ //the response is weakly bound
+
var internalContext = context._mfInternal;
//the normal usecase is that the request knows about its response
@@ -336,7 +340,12 @@ myfaces._impl.core._Runtime.extendClass(
_getAjaxReqClass: function(context) {
- return myfaces._impl.xhrCore._AjaxRequest;
+ // var _RT = myfaces._impl.core._Runtime;
+ //if(_RT.getXHRLvl() < 2) {
+ return myfaces._impl.xhrCore._AjaxRequest;
+ //} else {
+ // return myfaces._impl.xhrCore._AjaxRequestLevel2;
+ //}
}
});