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/07/29 12:50:30 UTC
svn commit: r980396 - in
/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl:
_util/_Dom.js _util/_Lang.js core/Impl.js core/_Runtime.js
xhrCore/_IFrameRequest.js
Author: werpu
Date: Thu Jul 29 10:50:30 2010
New Revision: 980396
URL: http://svn.apache.org/viewvc?rev=980396&view=rev
Log:
https://issues.apache.org/jira/browse/MYFACES-2846
https://issues.apache.org/jira/browse/MYFACES-2845
https://issues.apache.org/jira/browse/MYFACES-2841
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/_util/_Lang.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.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/_IFrameRequest.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=980396&r1=980395&r2=980396&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 Thu Jul 29 10:50:30 2010
@@ -1268,6 +1268,21 @@ myfaces._impl.core._Runtime.singletonExt
},
+ isMultipartCandidate: function(executes) {
+ if(this._Lang.isString(executes)) {
+ executes = this._Lang.strToArray(executes, "\\s+");
+ }
+
+ for(var exec in executes) {
+ var element = this.byId(executes[exec]);
+ var inputs = this.findByTagName(element, "input", true);
+ for(var key in inputs) {
+ if(this.getAttribute(inputs[key],"type") == "file") return true;
+ }
+ }
+ return false;
+ },
+
byId: function(id) {
return this._Lang.byId(id);
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js?rev=980396&r1=980395&r2=980396&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js Thu Jul 29 10:50:30 2010
@@ -179,7 +179,7 @@ myfaces._impl.core._Runtime.singletonDel
throw Error("myfaces._impl._util._Lang.strToArray a splitter param must be provided which is either a tring or a regexp");
}
var retArr = it.split(splitter);
- //var len = retArr.length;
+ var len = retArr.length;
for (var cnt = 0; cnt < len; cnt++) {
retArr[cnt] = this.trim(retArr[cnt]);
}
@@ -304,6 +304,7 @@ myfaces._impl.core._Runtime.singletonDel
var ret = {};
var keyIdx = {};
var key = null;
+ var _udef = "undefined";
for (key in src) {
/**
*we always overwrite dest with source
@@ -316,15 +317,15 @@ myfaces._impl.core._Runtime.singletonDel
*on all values being non boolean, we would need an elvis
*operator in javascript to shorten this :-(
*/
- ret[key] = this.exists(dest, key) ? dest[key] : src[key];
+ ret[key] = (_udef != typeof dest[key]) ? dest[key] : src[key];
} else {
- ret[key] = this.exists(src, key) ? src[key] : dest[key];
+ ret[key] = (_udef != typeof src[key]) ? src[key] : dest[key];
}
keyIdx[key] = true;
}
for (key in dest) {
/*if result.key does not exist we push in dest.key*/
- ret[key] = this.exists(ret, key) ? ret[key] : dest[key];
+ ret[key] = (_udef != typeof ret[key]) ? ret[key] : dest[key];
}
return ret;
}
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.js?rev=980396&r1=980395&r2=980396&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.js Thu Jul 29 10:50:30 2010
@@ -119,6 +119,8 @@ myfaces._impl.core._Runtime.singletonExt
*all the time
**/
var _Lang = myfaces._impl._util._Lang;
+ var _Dom = myfaces._impl._util._Dom;
+
var elementId = null;
/**
* we cross reference statically hence the mapping here
@@ -136,7 +138,7 @@ myfaces._impl.core._Runtime.singletonExt
//to get a fallback option in case the identifier is not determinable
// anymore, in case of a framework induced detachment the element.name should
// be shared if the identifier is not determinable anymore
- elementId = elem.id || null;
+ elementId = elem.id || elem.name;
if ((elementId == null || elementId == '') && elem.name) {
elementId = elem.name;
}
@@ -169,21 +171,22 @@ myfaces._impl.core._Runtime.singletonExt
* ajax pass through context with the source
* onevent and onerror
*/
- var context = {};
- context.source = elem;
- context.onevent = options.onevent;
- context.onerror = options.onerror;
+ var context = {
+ source: elem,
+ onevent: options.onevent,
+ onerror: options.onerror
+ };
/**
* fetch the parent form
*/
- var form = myfaces._impl._util._Dom.fuzzyFormDetection(elem);
+ var form = _Dom.fuzzyFormDetection(elem);
var formErr = "Sourceform could not be determined, either because element is not attached to a form or we have multiple forms with named elements of the same identifier or name, stopping the ajax processing";
if (!form && event) {
- form = myfaces._impl._util._Dom.fuzzyFormDetection(_Lang.getEventTarget(event));
+ form = _Dom.fuzzyFormDetection(_Lang.getEventTarget(event));
if (!form) {
throw Error(formErr);
}
@@ -201,26 +204,25 @@ myfaces._impl.core._Runtime.singletonExt
*/
passThrgh[this.P_AJAX] = true;
- /**
- * if execute or render exist
- * we have to pass them down as a blank delimited string representation
- * of an array of ids!
- */
- var exec, none, all, render = null;
- if (passThrgh.execute) {
- /*the options must be a blank delimited list of strings*/
- exec = _Lang.arrToString(passThrgh.execute, ' ');
- none = exec.indexOf(this.IDENT_NONE) != -1;
- all = exec.indexOf(this.IDENT_ALL) != -1;
+
+ var _this = this;
+ var transformList = function(target, srcList) {
+ var opList = _Lang.arrToString(srcList, ' '),
+ none = opList.indexOf(_this.IDENT_NONE) != -1,
+ all = opList.indexOf(_this.IDENT_ALL) != -1;
if (!none && !all) {
- exec = exec.replace(this.IDENT_FORM, form.id);
- exec = exec.replace(this.IDENT_THIS, elementId);
+ opList = opList.replace(_this.IDENT_FORM, form.id);
+ opList = opList.replace(_this.IDENT_THIS, elementId);
- passThrgh[this.P_EXECUTE] = exec;
+ passThrgh[target] = opList;
} else if (all) {
- passThrgh[this.P_EXECUTE] = this.IDENT_ALL;
+ passThrgh[target] = _this.IDENT_ALL;
}
+ };
+ if (passThrgh.execute) {
+ /*the options must be a blank delimited list of strings*/
+ transformList(this.P_EXECUTE, passThrgh.execute);
passThrgh.execute = null;
/*remap just in case we have a valid pointer to an existing object*/
delete passThrgh.execute;
@@ -229,18 +231,8 @@ myfaces._impl.core._Runtime.singletonExt
}
if (passThrgh.render) {
- render = _Lang.arrToString(passThrgh.render, ' ');
- none = render.indexOf(this.IDENT_NONE) != -1;
- all = render.indexOf(this.IDENT_ALL) != -1;
- if (!none && !all) {
- render = render.replace(this.IDENT_FORM, form.id);
- render = render.replace(this.IDENT_THIS, elementId);
- passThrgh[this.P_RENDER] = render;
- passThrgh.render = null;
- } else if (all) {
- passThrgh[this.P_RENDER] = this.IDENT_ALL;
-
- }
+ transformList(this.P_RENDER, passThrgh.render);
+ passThrgh.render = null;
delete passThrgh.render;
}
@@ -250,6 +242,20 @@ myfaces._impl.core._Runtime.singletonExt
delete passThrgh.myfaces;
}
+ var getConfig = myfaces._impl.core._Runtime.getLocalOrGlobalConfig;
+
+ /**
+ * if execute or render exist
+ * we have to pass them down as a blank delimited string representation
+ * of an array of ids!
+ */
+ //for now we turn off the transport auto selection, to enable 2.0 backwards compatibility
+ //on protocol level, the file upload only can be turned on if the auto selection is set to true
+ var transportAutoSelection = getConfig(context, "transportAutoSelection", false);
+ var isMultipart = (transportAutoSelection && _Dom.getAttribute(form,"enctype") == "multipart/form-data") ?
+ _Dom.isMultipartCandidate(passThrgh[this.P_EXECUTE]) :
+ false;
+
/**
* multiple transports upcoming jsf 2.1 feature currently allowed
* default (no value) xhrQueuedPost
@@ -262,13 +268,20 @@ myfaces._impl.core._Runtime.singletonExt
* iframeQueuedPost
*
*/
- var transportType = myfaces._impl.core._Runtime.getLocalOrGlobalConfig(context, "transportType", "xhrQueuedPost");
+
+ var transportType = (!isMultipart) ?
+ getConfig(context, "transportType", "xhrQueuedPost") :
+ getConfig(context, "transportType", "iframeQueuedPost");
+
if (!this._transport[transportType]) {
throw new Error("Transport type " + transportType + " does not exist");
}
+
this._transport[transportType](elem, form, context, passThrgh);
},
+
+
addOnError : function(/*function*/errorListener) {
/*error handling already done in the assert of the queue*/
this._errListeners.enqueue(errorListener);
@@ -322,7 +335,7 @@ myfaces._impl.core._Runtime.singletonExt
}
/**/
- if (myfaces._impl._util._Lang.exists(context, "onerror")) {
+ if (context["onerror"]) {
context.onerror(eventData);
}
@@ -409,25 +422,20 @@ myfaces._impl.core._Runtime.singletonExt
/* run through all script tags and try to find the one that includes jsf.js */
var scriptTags = document.getElementsByTagName("script");
var getConfig = myfaces._impl.core._Runtime.getGlobalConfig;
- for (var i = 0; i < scriptTags.length; i++)
- {
- if (scriptTags[i].src.search(/\/javax\.faces\.resource\/jsf\.js.*ln=javax\.faces/) != -1)
- {
+ for (var i = 0; i < scriptTags.length; i++) {
+ if (scriptTags[i].src.search(/\/javax\.faces\.resource\/jsf\.js.*ln=javax\.faces/) != -1) {
var result = scriptTags[i].src.match(/stage=([^&;]*)/);
- if (result)
- {
+ if (result) {
// we found stage=XXX
// return only valid values of ProjectStage
if (result[1] == "Production"
|| result[1] == "Development"
|| result[1] == "SystemTest"
- || result[1] == "UnitTest")
- {
+ || result[1] == "UnitTest") {
return result[1];
}
}
- else
- {
+ else {
//we found the script, but there was no stage parameter -- Production
//(we also add an override here for testing purposes, the default, however is Production)
return getConfig("projectStage", "Production");
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=980396&r1=980395&r2=980396&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 Thu Jul 29 10:50:30 2010
@@ -289,8 +289,12 @@ if (!myfaces._impl.core._Runtime) {
* @return either the config entry or if none is given the default value
*/
this.getGlobalConfig = function(configName, defaultValue) {
- /*use(myfaces._impl._util)*/
- return (_this.exists(myfaces, "config") && _this.exists(myfaces.config, configName)) ?
+ /**
+ * note we could use exists but this is an heavy operation, since the config name usually
+ * given this function here is called very often
+ * is a single entry without . in between we can do the lighter shortcut
+ */
+ return (myfaces["config"] && 'undefined' != typeof myfaces.config[configName] ) ?
myfaces.config[configName]
:
defaultValue;
@@ -309,8 +313,17 @@ if (!myfaces._impl.core._Runtime) {
*/
this.getLocalOrGlobalConfig = function(localOptions, configName, defaultValue) {
/*use(myfaces._impl._util)*/
+ var _local = !!localOptions;
+ var _localResult;
+ if(_local) {
+ //note we also do not use exist here due to performance improvement reasons
+ //not for now we loose the subnamespace capabilities but we do not use them anyway
+ //this code will give us a performance improvement of 2-3%
+ _localResult = (localOptions["myfaces"])?localOptions["myfaces"][configName] : undefined;
+ _local = 'undefined' != typeof _localResult;
+ }
- return (!_this.exists(localOptions, "myfaces." + configName)) ? _this.getGlobalConfig(configName, defaultValue) : localOptions.myfaces[configName];
+ return (!_local) ? _this.getGlobalConfig(configName, defaultValue) : _localResult;
};
/**
@@ -577,7 +590,28 @@ if (!myfaces._impl.core._Runtime) {
newCls.prototype._callSuper = function(methodName) {
var passThrough = (arguments.length == 1) ? [] : Array.prototype.slice.call(arguments, 1);
- this._parentCls[methodName].apply(this, passThrough);
+
+ //we store the descension level of each method under a mapped
+ //name to avoid name clashes
+ //to avoid name clashes with internal methods of array
+ var _mappedName = ["_",methodName,"_mf_r"].join("");
+ this._mfClsDescLvl = this._mfClsDescLvl || new Array();
+ //we have to detect the descension level
+ //we now check if we are in a super descension for the current method already
+ //if not we are on this level
+ var _oldDescLevel = this._mfClsDescLvl[_mappedName] || this;
+ //we now step one level down
+ var _parentCls = _oldDescLevel._parentCls;
+
+
+ try {
+ //we now store the level position as new descension level for callSuper
+ this._mfClsDescLvl[_mappedName] = _parentCls;
+ //and call the code on this
+ _parentCls[methodName].apply(this, passThrough);
+ } finally {
+ this._mfClsDescLvl[_mappedName] = _oldDescLevel;
+ }
};
}
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_IFrameRequest.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_IFrameRequest.js?rev=980396&r1=980395&r2=980396&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_IFrameRequest.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_IFrameRequest.js Thu Jul 29 10:50:30 2010
@@ -15,11 +15,16 @@
*/
/**
- * Iframe request for communications over Iframes
+ * iframe request for communications over iframe
*
* 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.
+ *
+ * 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
*/
myfaces._impl.core._Runtime.extendClass("myfaces._impl.xhrCore._IFrameRequest", myfaces._impl.xhrCore._BaseRequest, {
@@ -48,25 +53,35 @@ myfaces._impl.core._Runtime.extendClass(
*/
send: function() {
var _Impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+ 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
- this._Lang.addOnLoad(this._frame, this._Lang.hitch(this, this.callback));
+ //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);
+ }
if (!this._response) {
this._response = new myfaces._impl.xhrCore._AjaxResponse(this._onException, this._onWarning);
}
//now to the parameter passing:
- _Impl.sendEvent(this._xhr, _Impl.BEGIN);
+ _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;
try {
this._initAjaxParams();
this._sourceForm.target = this._frame.name;
@@ -86,14 +101,13 @@ myfaces._impl.core._Runtime.extendClass(
//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 {
//Derived from the YUI library, looking this up saved me some time
- request.responseText = this._frame.contentWindow.document.body ? this._frame.contentWindow.document.body.innerHTML : this._frame.contentWindow.document.documentElement.textContent;
- request.responseXML = this._frame.contentWindow.document.XMLDocument ? this._frame.contentWindow.document.XMLDocument : this._frame.contentWindow.document;
-
+ request.responseText = this._getFrameText();
+ request.responseXML = this._getFrameXml();
request.readyState = this._READY_STATE_DONE;
+
this._onDone(request, this._context);
if (!this._Lang.isXMLParseError(request.responseXML)) {
@@ -107,11 +121,37 @@ myfaces._impl.core._Runtime.extendClass(
//_onError
this._onException(null, this._context, "myfaces._impl.xhrCore._IFrameRequest", "constructor", e);
} finally {
- this._frame.parentNode.removeChild(this._frame);
- delete this._frame;
+ //this closes any hanging or pedning comm channel caused by the iframe
+ //this._frame.src = "about:blank";
+ this._setFrameText("");
+ this._frame = null;
}
},
+ /**
+ * returns the frame text in a browser independend manner
+ */
+ _getFrameText: function() {
+ return this._frame.contentWindow.document.body ? this._frame.contentWindow.document.body.innerHTML : this._frame.contentWindow.document.documentElement.textContent;
+ },
+
+ /**
+ * sets the frame text in a browser independend manner
+ *
+ * @param text to be set
+ */
+ _setFrameText: function(text) {
+ this._frame.contentWindow.document.body ? (this._frame.contentWindow.document.body.innerHTML = text) : (this._frame.contentWindow.document.documentElement.textContent = text);
+ },
+
+ /**
+ * returns the processed xml from the frame
+ */
+ _getFrameXml: function() {
+ return this._frame.contentWindow.document.XMLDocument ? this._frame.contentWindow.document.XMLDocument : this._frame.contentWindow.document;
+ },
+
+
_initAjaxParams: function() {
var _Impl = myfaces._impl.core.Impl;
//this._appendHiddenValue(_Impl.P_AJAX, "");
@@ -119,6 +159,8 @@ myfaces._impl.core._Runtime.extendClass(
for (var key in this._passThrough) {
this._appendHiddenValue(key, this._passThrough[key]);
}
+ //marker that this is an ajax iframe request
+ this._appendHiddenValue("javax.faces.partial.iframe", "true");
},
_removeAjaxParams: function(oldTarget) {
@@ -127,6 +169,7 @@ myfaces._impl.core._Runtime.extendClass(
for (var key in this._passThrough) {
this._removeHiddenValue(key);
}
+ this._removeHiddenValue("javax.faces.partial.iframe");
},
_appendHiddenValue: function(key, value) {
@@ -149,35 +192,46 @@ myfaces._impl.core._Runtime.extendClass(
},
_createTransportFrame: function() {
+ var _RT = myfaces._impl.core._Runtime;
var frame = document.getElementById(this._FRAME_ID);
//normally this code should not be called
//but just to be sure
- if (frame) {
- frame.parentNode.removeChild(frame);
- delete frame;
- }
-
- frame = document.createElement('iframe');
-
- 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");
-
- //security, we turn everything off
- //we wont need it
- if (frame.webNavigation) {
- frame.webNavigation.allowAuth = false;
- frame.webNavigation.allowImages = false;
- frame.webNavigation.allowJavascript = false;
- frame.webNavigation.allowMetaRedirects = false;
- frame.webNavigation.allowPlugins = false;
- frame.webNavigation.allowSubframes = false;
+ 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
+ var setAttr = this._Dom.setAttribute;
+ setAttr(frame, "src", "about:blank");
+ setAttr(frame, "id", this._FRAME_ID);
+ setAttr(frame, "name", this._FRAME_ID);
+ setAttr(frame, "type", "content");
+ setAttr(frame, "collapsed", "true");
+ setAttr(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
+ if (document.body.firstChild) {
+ document.body.insertBefore(node, document.body.firstChild);
+ } else {
+ document.body.appendChild(node);
+ }
+ }
}
- document.body.appendChild(frame);
- return frame;
+ //helps to for the onload handlers and innerhtml to be in sync again
+ return document.getElementById(this._FRAME_ID);
+
}
//TODO pps, the idea behind pps is to generate another form