Details
-
Type: Improvement
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: None
-
Component/s: ICE-Components
-
Labels:None
-
Environment:renderer + effect related JS handlers
Description
LocalEffectEncoder
.encodeLocalEffects(uiComponent, attributeElement, facesContext);
Issue Links
Activity
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion
Implemented the optimisation for ice:inputText, as a testing ground, as well as fixed a regression with HtmlInputText sub-classes that was introduced in a commit for ICE-3321.
TRUNK
Subversion 17758
icefaces\component\src\com\icesoft\faces\component\ext\HtmlInputText.java
icefaces\component\src\com\icesoft\faces\component\ext\renderkit\InputTextRenderer.java
icefaces\component\src\com\icesoft\faces\component\ExtendedAttributeConstants.java
icefaces\component\src\com\icesoft\faces\component\selectinputtext\SelectInputText.java
icefaces\core\src\com\icesoft\faces\component\AttributeConstants.java
icefaces\core\src\com\icesoft\faces\context\effects\LocalEffectEncoder.java
These changes were made with the PassThruAttributeWriter and the LocalEffectEncoder, so they just pertain to ResponseWriter components, and have yet to be adapted to DOM rendering components.
The basic idea is that the javascript handler pass-through attribute rendering becomes the responsibility of the LocalEffectEncoder, not PassThruAttributeWriter anymore. That way, only one method is trying to render out the on* javascript handlers, so they're not being redundantly or incorrectly stomped over by other code.
Let's look at ice:inputText, and its attributes, as an example, dividing them up into categories.
PassThruAttributes, as defined in ExtendedAttributeConstants
Regular passthrough attributes:
accesskey
alt
dir
lang
maxlength
size
style
tabindex
title
Javascript handlers (All of these can pass-through values from the application. Renderer ones also have values from the component renderers):
Effect related handlers:
onclick
ondblclick
onkeydown
onkeypress (Renderer)
onkeyup
onmousedown
onmousemove
onmouseout
onmouseover
onmouseup
Non-Effect
onblur (Renderer)
onfocus (Renderer)
onchange
onselect
ExtendedAttributeConstants just gives a flat String[] of all those attributes. It's a little easier if we start thinking of them as sets that describe categories of attributes.
Passthru : All of the pass-through attributes for a given component
Regular : A component's non-javascript attributes
Javascript : A component's javascript on* attributes
Effect : Subset of Javascript, related to effects. Eg: onclick is in it, onblur is not.
NonEffect : Remainder of Javascript
AllPossibleJavascript : For all components together, the complete list of all possible javascript on* attributes
Before, the PassThruAttributeWriter wrote out all Passthru, both Regular and Javascript. Then LocalEffectEncoder wrote out the Effect attributes. Since Effect is a subset of Javascript, they would overlap. Now, we want PassThruAttributeWriter to only do Regular, and LocalEffectEncoder to do Javascript.
We get Javascript by finding the intersection of AllPossibleJavascript and Passthru:
private static final String[] jsEvents = LocalEffectEncoder.maskEvents(
ExtendedAttributeConstants.getAttributes(
ExtendedAttributeConstants.ICE_INPUTTEXT));
We get Regular by taking Passthru, and excluding Javascript:
private static final String[] passThruAttributes =
ExtendedAttributeConstants.getAttributesExceptJavascript(
ExtendedAttributeConstants.ICE_INPUTTEXT,
jsEvents);
Note that we have to pass our renderer values into LocalEffectEncoder, for any entries in Javascript. But, Javascript does not equal AllPossibleJavascript. So, for any entries outside of that, the component renderer has to handle them itself.
In this case, the output is highly static, only depending on if partialSubmit is true or false, so I build two static maps, taking care to use String constants, so they'll all be interned:
private static Map rendererJavascript;
private static Map rendererJavascriptPartialSubmit;
static {
rendererJavascript = new HashMap();
rendererJavascript.put(HTML.ONKEYPRESS_ATTR,
DomBasicRenderer.ICESUBMIT);
rendererJavascript.put(HTML.ONFOCUS_ATTR,
"setFocus(this.id);");
rendererJavascript.put(HTML.ONBLUR_ATTR,
"setFocus('');");
rendererJavascriptPartialSubmit = new HashMap();
rendererJavascriptPartialSubmit.put(HTML.ONKEYPRESS_ATTR,
DomBasicRenderer.ICESUBMIT);
rendererJavascriptPartialSubmit.put(HTML.ONFOCUS_ATTR,
"setFocus(this.id);");
rendererJavascriptPartialSubmit.put(HTML.ONBLUR_ATTR,
"setFocus('');" + DomBasicRenderer.ICESUBMITPARTIAL);
And then when rendering I just select between the two of them:
Map rendererJS = ((IceExtended) uiComponent).getPartialSubmit()
? rendererJavascriptPartialSubmit : rendererJavascript;
LocalEffectEncoder.encode(
facesContext, uiComponent, jsEvents, rendererJS, null, writer);
The new LocalEffectEncoder.encode method iterates over the entries in Javascript, getting the:
1. on*effect value
2. on* application value
3. on* component renderer value
and concatenating them in that order.
Test case for ice:inputText:
<ice:inputText
id="TxtName"
required="true"
valueChangeListener="#
"
value="#
"
partialSubmit="true"
accesskey="X"
alt="Alternate"
autocomplete="false"
dir="LTR"
disabled="false"
lang="en"
maxlength="30"
readonly="false"
size="20"
style="background-color:blue;"
styleClass="STYLECLASS"
tabindex="15"
title="Title"
onblur="window.status = 'onblur';"
onchange="window.status = 'onchange';"
onclick="window.status = 'onclick';"
onclickeffect="#
ondblclick="window.status = 'ondblclick';"
ondblclickeffect="#{textFields.effect}
"
onfocus="window.status = 'onfocus';"
onkeydown="window.status = 'onkeydown';"
onkeydowneffect="#
onkeypress="window.status = 'onkeypress';"
onkeypresseffect="#{textFields.effect}
"
onkeyup="window.status = 'onkeyup';"
onkeyupeffect="#
onmousedown="window.status = 'onmousedown';"
onmousedowneffect="#{textFields.effect}
"
onmousemove="window.status = 'onmousemove';"
onmousemoveeffect="#
onmouseout="window.status = 'onmouseout';"
onmouseouteffect="#{textFields.effect}
"
onmouseover="window.status = 'onmouseover';"
onmouseovereffect="#
onmouseup="window.status = 'onmouseup';"
onmouseupeffect="#{textFields.effect}
"
onselect="window.status = 'onselect';" />
Layed some more groundwork in the utility methods, and improved InputText to be in line with changes to OutputText. For OutputText, there was more effort required, since I added a separate ice: renderer than the h: renderer. From now on we can better control the difference of behaviours between the two.
TRUNK
Subversion 17793
icefaces\component\src\com\icesoft\faces\component\ExtendedAttributeConstants.java
icefaces\core\src\com\icesoft\faces\component\AttributeConstants.java
icefaces\core\src\com\icesoft\faces\context\effects\LocalEffectEncoder.java
icefaces\component-metadata\src\main\resources\conf\ice_properties\ice-outputText-props.xml
icefaces\component\conf\META-INF\faces-config.xml
icefaces\component\src\com\icesoft\faces\component\ext\HtmlOutputText.java
icefaces\component\src\com\icesoft\faces\component\ext\renderkit\OutputTextRenderer.java
icefaces\core\conf\just-ice\faces-config.xml
icefaces\core\conf\META-INF\faces-config.xml
icefaces\core\src\com\icesoft\faces\renderkit\dom_html_basic\OutputTextRenderer.java
icefaces\core\src\com\icesoft\faces\webapp\parser\IceOutputTextTag.java
icefaces\component\src\com\icesoft\faces\component\ext\renderkit\InputTextRenderer.java
icefaces\core\src\com\icesoft\faces\renderkit\dom_html_basic\InputTextRenderer.java
Finished separating the h:outputText and ice:outputText behaviours, where only ice:outputText does Effects.
TRUNK
Subversion 17796
icefaces\core\src\com\icesoft\faces\renderkit\dom_html_basic\OutputTextRenderer.java
Next step is to add this new logic to the panelGroup component and any other components that sub-class panelGroup.
The following two components extend the renderer of the panelGroup component.
-panelPopup
-PanelTooltip
According to the TLD docs and the ExtendedAttributeConstants the above components have the following passThru attributes:
- panelGroup
{ HTML.STYLE_ATTR };
- panelPopup { HTML.STYLE_ATTR, HTML.TITLE_ATTR };
- PanelTooltip{ HTML.STYLE_ATTR }
According to the TLD docs only the panelGroup has effect related attributes and it doesn't support any javascript related attribute which means that none of the component requires any change.
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\ExtendedAttributeConstants.java
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\ext\HtmlPanelGroup.java
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\ext\renderkit\GroupRenderer.java
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component-metadata\src\main\resources\conf\ice_properties\ice-panelGroup-props.xml
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\core\src\com\icesoft\faces\renderkit\dom_html_basic\GroupRenderer.java
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\core\src\com\icesoft\faces\renderkit\dom_html_basic\PassThruAttributeRenderer.java
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\ext\renderkit\GroupRenderer.java
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component-metadata\src\main\resources\conf\ice_properties\ice-panelGroup-props.xml
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\ExtendedAttributeConstants.java
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\ext\HtmlPanelGroup.java
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\core\src\com\icesoft\faces\renderkit\dom_html_basic\GroupRenderer.java
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\core\src\com\icesoft\faces\renderkit\dom_html_basic\PassThruAttributeRenderer.java
Completed: At revision: 17873
I have also overloaded the following method :
public static String[] getAttributes(int index, String[] remove) {
signature of new overloaded method:
public static String[] getAttributes(int index, String[][] remove) {
It allows to pass more then one exclude arrays. (e.g.) Exclude the JS event as well as excluded attributes.
Changes applied to the panelPopup as well as panelTooltip.
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\ExtendedAttributeConstants.java
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\panelpopup\PanelPopupRenderer.java
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\paneltooltip\PanelTooltipRenderer.java
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component-metadata\src\main\resources\conf\ice_cust_properties\cust-panelpopup-props.xml
Modified: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component-metadata\src\main\resources\conf\ice_cust_properties\cust-paneltooltip-props.xml
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\paneltooltip\PanelTooltipRenderer.java
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\panelpopup\PanelPopupRenderer.java
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component-metadata\src\main\resources\conf\ice_cust_properties\cust-panelpopup-props.xml
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component\src\com\icesoft\faces\component\ExtendedAttributeConstants.java
Sending content: D:\work\development\head\svn\ossrepo\icefaces\trunk\icefaces\component-metadata\src\main\resources\conf\ice_cust_properties\cust-paneltooltip-props.xml
Completed: At revision: 17875
Assigning to Mandeep for testing
This optimization has been made to the following priority components:
- inputText
- outputText
- panelGroup
- panelPopup
- panelTooltip
Maybe the renderer could pass in a Map of what it wants to render to LocalEffectEncoder, where a map entry would look like "onclick" -> "iceSubmitPartial(...)". These could be statically defined, or dynamically generated if necessary.
LocalEffectEncoder could iterate over all the typical events, and combine the effect + user + framework Javascript, based on the on*effect attribute, the on* attribute, and the Map, respectively.
Also, it looks like some renderers invoke it directly, while it's also called from PassThruAttributeRenderer.renderHtmlAttributes, so we should probably make we're not double-invoking it that way too.