Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: EE-2.0.0.GA
-
Fix Version/s: 3.0.RC1, 3.0, EE-2.0.0.GA_P01
-
Component/s: Bridge
-
Labels:None
-
Environment:windows 7, jdk 1.6, eclipse Indigo
Description
Problem:
In a Portal Envrionement, such as Liferay, you sometimes need to trigger an regular (non-ajax) Post Call which triggers the Portal's ACTION_PHASE. The problem is that it is not going to work for commandLinks. It looks like as soon as JSF decorates a commandButton or a commandLink with the onclick="mojarra.jsfcljs(document.getElementById('myForm'),{'myForm:noneButton2':'myForm:noneButton2'},'');return false" function, ICEfaces is having troubles to detect whether these components have really been disabled via f:ajax disable=true
The commandButton actually works in ICEfaces but as soon as the mojarra patch is applied the commandButtons acts like a commandLink (as you would expect) and thus none of them interprets the f:ajax disabled="true" correctly and a ajax post is sent instead
What is the mojarra patch:
There is a bug in mojarra which fails to decorate the commandButton having an onclick method if the f:ajax disabled is set to true: thus the f:param is not set to the requestParameterMap
In order to Fix that Behavoir patch Line: 137:
FROM:
RenderKitUtils.renderOnclick(context, component, params, null, false);
TO:
RenderKitUtils.renderOnclick(context, component, params, null, true);
-
- application.js
- 26 kB
- Ted Goddard
-
- icefaces_7405_R2.xlsx
- 12 kB
- Patrick Dobler
-
- icefaces_7405.xlsx
- 12 kB
- Patrick Dobler
-
Hide
- icefaces_7405.zip
- 6.18 MB
- Patrick Dobler
-
- icefacesSupport_ICE-7405_part1/.classpath 0.8 kB
- icefacesSupport_ICE-7405_part1/.../faces-config.pageflow 0.2 kB
- icefacesSupport_ICE-7405_part1/.project 1 kB
- icefacesSupport_ICE-7405_part1/.../.jsdtscope 0.5 kB
- icefacesSupport_ICE-7405_part1/.../org.eclipse.jdt.core.prefs 0.4 kB
- icefacesSupport_ICE-7405_part1/.../org.eclipse.wst.common.component 0.5 kB
- icefacesSupport_ICE-7405_part1/.../org.eclipse.wst.common.project.facet.core.prefs.xml 0.2 kB
- icefacesSupport_ICE-7405_part1/.../org.eclipse.wst.common.project.facet.core.xml 0.3 kB
- icefacesSupport_ICE-7405_part1/.../org.eclipse.wst.jsdt.ui.superType.container 0.0 kB
- icefacesSupport_ICE-7405_part1/.../org.eclipse.wst.jsdt.ui.superType.name 0.0 kB
- icefacesSupport_ICE-7405_part1/.../ICEfacesBugCommandLink.xhtml 2 kB
- icefacesSupport_ICE-7405_part1/.../JSFBugCommandButton.xhtml 4 kB
- icefacesSupport_ICE-7405_part1/.../MANIFEST.MF 0.0 kB
- icefacesSupport_ICE-7405_part1/.../faces-config.xml 0.3 kB
- icefacesSupport_ICE-7405_part1/.../commons-beanutils.jar 226 kB
- icefacesSupport_ICE-7405_part1/.../commons-digester.jar 140 kB
- icefacesSupport_ICE-7405_part1/.../commons-logging.jar 52 kB
- icefacesSupport_ICE-7405_part1/.../icefaces-ee-2.0.0-INSIEME3.jar 206 kB
- icefacesSupport_ICE-7405_part1/.../icefaces-ee-compat-2.0.0-INSIEME3.jar 2.67 MB
- icefacesSupport_ICE-7405_part1/.../jsf-api-2.1.2-MIMACOM2.jar 609 kB
- icefacesSupport_ICE-7405_part1/.../jsf-impl-2.1.2-MIMACOM2.jar 1.84 MB
- icefacesSupport_ICE-7405_part1/.../jstl.jar 20 kB
- icefacesSupport_ICE-7405_part1/.../jxl.jar 708 kB
- icefacesSupport_ICE-7405_part1/.../krysalis-jCharts-1.0.0-alpha-1.jar 151 kB
- icefacesSupport_ICE-7405_part1/.../web.xml 3 kB
- icefacesSupport_ICE-7405_part1/.../index.xhtml 1 kB
- icefacesSupport_ICE-7405_part1/.../dummy.js 0.0 kB
- icefacesSupport_ICE-7405_part1/.../jsf-uncompressed.js 107 kB
- icefacesSupport_ICE-7405_part1/.../jsf.js 107 kB
- icefacesSupport_ICE-7405_part1/.../ButtonRenderer.class 7 kB
-
- submit.js
- 13 kB
- Ted Goddard
Issue Links
- depends on
-
ICE-7054 Setting <f:ajax disabled="true"> does not work for h:commandLink
- Closed
Activity
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion
The following does not include the parameters due to mojarra disabling ajax features on the component; effectively they are disabling JavaScript when they are disabling Ajax, which is a reasonable interpretation (and related to some current difficulties with MyFaces).
<h:commandButton value="button"
actionListener="#
">
<f:param name="paramname" value="paramvalue" />
<f:ajax disabled="true" />
</h:commandButton>
For this use case we likely need a different mechanism for "disabling Ajax" on the command button. However, this depends on how mojarra implements the setting of parameters: if they are injected into the form as hidden fields, then a non-Ajax post will work. If they are passed as parameters to jsf.ajax.request, then the parameters will not be available to the standard form POST.
Hi Ted,
You mentioned: "effectively they are disabling JavaScript when they are disabling Ajax". In my opinion mojarra should still add the onclick function -> mojarra.jsfcljs(... ) to the h:commandButton. Thats why I think there might be a bug in "com.sun.faces.renderkit.html_basic.ButtonRenderer: Line 137: RenderKitUtils.renderOnclick( , TRUE instead of FALSE)". Then you'll get the same behaviour for the h:commandButton as the h:commandLink:
<h:commandLink value="link"
actionListener="#
">
<f:param name="paramname" value="paramvalue" />
<f:ajax disabled="true" />
</h:commandLink >
=> This code still puts an mojarra.jsfcljs(...) to the commandLink and makes sure the parameters are rendered as hidden fields and it does not perfrom a ajax request.
If an onclick is added to a commandButton, the event is generated for the form rather than the button itself, causing ajaxDisabled detection to fail.
The following change allows the ICEfaces bridge to extract the correct element to test for when the "form" is the submitting element:
+++ core/src/main/javascript/submit.js (working copy)
@@ -186,6 +186,9 @@
var removePrefix = 'patch-';
fullSubmit = function(execute, render, event, element, additionalParameters, callbacks) {
+ if (toLowerCase(element.tagName) == "form")
if (isAjaxDisabled(element)) {
var f = formOf(element);
//use native submit function saved by namespace.captureSubmit
With the page modified to trick mojarra into ignoring the ajaxDisabled:
+++ samples/core/basic/src/main/webapp/icefaces.xhtml (working copy)
@@ -42,8 +42,10 @@
<h:outputText id="out2" value="Or Not" rendered="#
"/>
</h:panelGroup>
<br/>
- <h:commandButton id="button1" value="Show/Hide"
+ <h:commandButton id="button1" value="Show/Hide" onclick="console.log('empty');"
actionListener="# {basic.toggle}">
+ <f:param name="zzzzzzzzzzzz" value="xxxxxxxxxxxxxx" />
+ <f:ajax disabled="true" />
</h:commandButton>
<br/>
<h:outputText value="Reload entire page: "/>
Note that the ICEfaces bridge does not ignore ajaxDisabled in this case (with the above submit.js change).
Hi Ted,
thanks for the patch. unfortunatelly it is not gonna work for the following scenarios:
<h:commandLink id="btn5" action="#
{myBean.executeMethod1}" ><f:ajax disabled="true" />
<h:outputText value="what about me" />
<f:param name="testParam" value="testValue" />
</h:commandLink>
or even more complex:
<h:commandLink id="btn5" action="#{myBean.executeMethod1}
" >
<f:ajax disabled="true" />
<span>
<h:outputText value="what about me"></h:outputText>
</span>
<f:param name="testParam" value="testValue" />
</h:commandLink>
due the problem that the triggeredBy() function returns the SPAN element rather than the commandLink itself and thus the isAjaxDisabled function fails again...
what I did so far as an very ugly workaround for your patch:
if (toLowerCase(element.tagName) == "form") {
element = triggeredBy($event(event, element));
while (toLowerCase(element.tagName) != "a" && toLowerCase(element.tagName) != "input")
}
if (isAjaxDisabled(element)) {
....
btw: it seems that our commandLinks (see example above that comment) don't work in Firefox Version 5.0: Looks like the method triggeredBy(...) does not return the correct element (in our case the form is returned)
In this case triggeredBy() is returning the incorrect value; we will need to investigate a fix for that as well.
The following patch has been checked in:
Index: core/src/main/javascript/application.js
===================================================================
— core/src/main/javascript/application.js (revision 26183)
+++ core/src/main/javascript/application.js (working copy)
@@ -362,7 +362,23 @@
//hijack browser form submit, instead submit through an Ajax request
f.nativeSubmit = f.submit;
f.submit = function() {
- submit(null, f);
+ var theEvent = null;
+ if (typeof(event) != 'undefined') { + theEvent = event; + }else if (window.event)
{ + theEvent = window.event; + }else
Unknown macro: {+ //very bizzarre hack to extract parameters from high up+ //on the call stack to obtain the current Event on Firefox+ //this is sensitive to the depth of the call stack so+ //it may eventually be necessary to walk up rather than+ //test a specific caller+ var maybeEvent = arguments.callee.caller.caller.arguments[0];+ if (typeof(maybeEvent.target) != 'undefined') { + theEvent = maybeEvent; + }+ }+ submit(theEvent, f);
{ Index: core/src/main/javascript/submit.js =================================================================== --- core/src/main/javascript/submit.js (revision 26183) +++ core/src/main/javascript/submit.js (working copy) @@ -32,9 +32,8 @@ return toLowerCase(element.nodeName) == 'form' ? element : enclosingForm(element); }
};
each(['onkeydown', 'onkeypress', 'onkeyup', 'onclick', 'ondblclick', 'onchange'], function(name) {
f[name] = function(e)
- function isAjaxDisabled(element) {
+ function isAjaxDisabled(formID, element) {
var elementID = element.id; - var formID = formOf(element).id;
//lookup element that contains the list of elements that have AJAX submission disabled
var disablingMarker = document.getElementById(formID + ":ajaxDisabled");
return disablingMarker && contains(split(trim(disablingMarker.value), ' '), elementID);
@@ -186,14 +185,36 @@
var removePrefix = 'patch-';
fullSubmit = function(execute, render, event, element, additionalParameters, callbacks) {
- if (isAjaxDisabled(element)) {
- var f = formOf(element);
+ var f = null;
+ var eventElement = (event.currentTarget) ? event.currentTarget :
+ triggeredBy($event(event, element));
+ if (toLowerCase(element.tagName) == "form") { + f = element; + }else
{ + f = formOf(element); + }+ var formID = f.id;
+ //if the element has ajaxDisabled or any parent has ajaxDisabled,
+ //then ajax is disabled
+ var ajaxIsDisabled = false;
+ var ancestor = eventElement;
+ while (null != ancestor)Unknown macro: {+ if (toLowerCase(ancestor.tagName) == "form") { + break; + }+ if (isAjaxDisabled(formID, ancestor)) { + ajaxIsDisabled = true; + break; + }+ ancestor = ancestor.parentNode;+ }+ if (ajaxIsDisabled) {
//use native submit function saved by namespace.captureSubmit
if (f && f.nativeSubmit) {
var fakeClick = document.createElement("input");
fakeClick.setAttribute("type", "hidden"); - fakeClick.setAttribute("name", element.name);
- fakeClick.setAttribute("value", element.value);
+ fakeClick.setAttribute("name", eventElement.name);
+ fakeClick.setAttribute("value", eventElement.value);
f.appendChild(fakeClick);
f.nativeSubmit();
f.removeChild(fakeClick);
The above patch has been verified on commandLink with child elements on FireFox, IE7, and Chrome.
The changes to application.js expand the ability to capture the user event when the submit is captured (often due to form.submit() being invoked from commandLink handling, but also from automatic Ajax submit capture). Each different strategy is intended for a different browser: on Chrome, an "event" object was observed to be already in scope, on IE window.event is always available, and as a fallback (which actually works on most Netscape-offspring browsers but is the most fragile under jsf.js code changes) snag the event passed as a parameter to the onclick handler:
arguments.callee.caller.caller.arguments[0]
In submit.js, the additional details in the captured event are used to better find the ajaxDisabled state of the element: the algorithm searches upward (bailing out on a form or the top of the document) looking for ajaxDisabled. In other words, children of ajaxDisabled have ajax disabled.
Attaching modified files for use in trunk once code freeze completes.
covers testcases from testcases sheet
The following was tested successfully on IE7 and Chrome. Does it not cover the "Nok" cases described in Icefaces_7405.xlsx
<h:commandButton id="button1" value="Show/Hide" onclick="var x = 0;"
actionListener="#
<f:param name="zzzzzzzzzzzz" value="xxxxxxxxxxxxxx" />
<f:ajax disabled="true" />
</h:commandButton>
<h:commandLink value="Show/Hide" onclick="var x = 0;"
actionListener="#{basic.toggle}
">
<f:param name="llllllllllll" value="nnnnnnnnnnn" />
<f:ajax disabled="true" />
</h:commandLink>
<h:commandLink onclick="var x = 0;"
actionListener="#
">
<f:param name="llllllllllll" value="nnnnnnnnnnn" />
<f:ajax disabled="true" />
<span>
<h:outputText value="SpanShowHide"></h:outputText>
</span>
</h:commandLink>
Were errors observed in any browser, and was this test performed with the latest EE branch?
An improved fix has been checked in to the branch. This addresses some cases on FireFox, but does not yet address the case for IE with ajaxDisabled and no param.
Patrick, it may be difficult to handle all possible combinations of the attributes on all browsers, so please provide confirmation if there is now a strategy that works for you on the browsers you need to support.
Tyler, please provide a new build from the branch to the customer.
Additional code has been added that should handle IE behavior.
Passing along a note from Patrick:
Please find attached the test results based on the newest patch. Unfortunately IE8 is our target browser.
icefaces_7405_R2.xlsx
onclick="console.log();" will not work on IE; instead, use something like onclick="var x = 0;".
The recent merge with the trunk is causing a regression failure. Please see ICE-7454.
This fix is causing failures with various ACE components due to the following:
ice.ace.AjaxRequest = function(cfg) {
...
ice.fullSubmit(jsfExecute, jsfRender, null, source || form[0], function(parameter) {
The synthetic event passed by ice.ace.AjaxRequest is null.
This should be addressed, but will likely require extensive changes to where ice.ace.AjaxRequest is used. A sufficient fix to solve the regression will be to check for the null event when it occurs. The drawback will be that ice.ace.AjaxRequest cases will likely ignore ajax disabled.
A fix is checked in to proceed when the event is null.
This has been verified fixed in the reported cases. If specific cases are found where ajax disabled does not interact correctly with parameters, specific JIRAs can be created.
Please find attached a demo application
How to import to Eclipse:
file -> import -> existing project into workspace -> select archieve file -> finish
How to verify the mojarra bug:
1. Please remove the icefaces-ee-2.0.0-INSIEME2.jar and icefaces-ee-compat-2.0.0-INSIEME2.jar from to /WEB-INF/lib
2. Start the server
3. go to: http://localhost:8080/icefacesSupport/JSFBugCommandButton.xhtml
4. Follow instuctions
5. Patch the com.sun.faces.renderkit.html_basic.ButtonRenderer as descibred above
6. Start the server again
7. go to: http://localhost:8080/icefacesSupport/JSFBugCommandButton.xhtml
8. Follow instuctions
How to verify the icefaces bug:
1. Please add the icefaces-ee-2.0.0-INSIEME2.jar and icefaces-ee-compat-2.0.0-INSIEME2.jar to /WEB-INF/lib
2. Start the server
3. go to: http://localhost:8080/icefacesSupport/ICEfacesBugCommandLink.xhtml
4. Follow instuctions
summa summarum: