Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: EE-2.0.0.GA, 3.0.RC1, 3.0.RC2
-
Fix Version/s: 3.0
-
Component/s: ACE-Components
-
Labels:None
-
Environment:ICEfaces EE 2.0, ICEfaces 3.0RC
-
Assignee Priority:P1
Description
-
Hide
- Case10754Example2.zip
- 20 kB
- Arran Mccullough
-
- Case10754Example2/build.xml 3 kB
- Case10754Example2/.../ant-deploy.xml 2 kB
- Case10754Example2/.../build-impl.xml 58 kB
- Case10754Example2/.../genfiles.properties 0.5 kB
- Case10754Example2/.../private.properties 0.5 kB
- Case10754Example2/.../project.properties 3 kB
- Case10754Example2/nbproject/project.xml 1 kB
- Case10754Example2/src/conf/MANIFEST.MF 0.0 kB
- Case10754Example2/src/.../example/Tab.java 0.8 kB
- Case10754Example2/src/.../TestBean.java 3 kB
- Case10754Example2/web/css/style.css 0.1 kB
- Case10754Example2/web/.../context.xml 0.1 kB
- Case10754Example2/web/tabControl.xhtml 1 kB
- Case10754Example2/web/tabFour.xhtml 0.5 kB
- Case10754Example2/web/tabOne.xhtml 0.5 kB
- Case10754Example2/web/tabThree.xhtml 0.5 kB
- Case10754Example2/web/tabTwo.xhtml 0.5 kB
- Case10754Example2/web/WEB-INF/web.xml 2 kB
- Case10754Example2/.../welcomeICEfaces.xhtml 2 kB
-
Activity
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion
Bugs about dynamic properties are generally caused by the change of property not causing a sufficient Dom update. Here, it's likely that the tapPane renders some disabled style, but that the tabSet's JavaScript still needs to execute to make the relevant JavaScript objects know it's disabled. Forcing the JavaScript to update, given some property change that's not rendered in the script tag is generally accomplished by adding the property to the hash field.
I've attempted the technique Mark suggests, but it was complicated by the fact that the TabPane doesn't have a JS implementation supplied by ICEfaces, it is just the basic YUI component. The disabled state is determined in initialization of the parent tabset according to the presence of the disabled style class on the tab markup, as rendered by the TabSetRenderer (read from TabPane.isDisabled()). My plan was to have the TabSetRenderer calculate a hash of all the disabled values of the TabPanes, and have the JS 'refresh' the state of the tabs whenever it changed.
Without a ICEfaces instance of TabPane available, I referenced the TabSet instance, used it to reference the YUI tab, and attempted to set disabled that way. This worked (when checked afterwards with Tab.get('disabled')), however the tabset became totally unresponsive after any use of ice.ace.tabset.getInstance.
I attempted again, and had greater success but my results appears to indicate that we need to send disabled property per-tab rather than as a hash.
After adding:
if (oldJSFProps && oldJSFProps['hashCode'] != jsfProps['hashCode']) {
var tabs = context.getComponent().get('tabs');
for (var i = 0; i < tabs.length; i++)
}
to ice.ace.tabset.updateProperties, I discovered that while the attached updateProperties script is run for every tabset render, it is run before the update is applied to the DOM. This means that though we are trying to inspect which tab has been disabled/enabled, and carry over the change into JS, the JS is running before the change to the style class, and that style class change is the one indication on the DOM of which TabPane is responsible for the hash code change. Without sending per-tab information, or running some sort of event following the DOM update, I'm not sure how this will be possible.
Problem now lies with the DOMEventHandler for the tabset. It's eating the events for the newly enabled tabs.
DOMEventHandler required that the DOM element causing the event was the child of one of the tabs elements that was initialized with tabset. The tab has been updated since the initialization due to the disabled style class changing on the server, so the DOMEventHandler didn't find a parent tab and ate the event.
When setAttributeConfig('disabled',
{value: newDOMElem}, true) was used to configure the tab JS object with the updated element, the DOMEventHandler passed the events on to the tab correctly, however it now appears the tab DOM element hasn't been configured with all the YUI Tab JS synthetic events. YUI sure doesn't make anything easy.
Not sure how to rebind these events to the new DOM element so, to avoid the problem above entirely, I'm attempting to modify the way in which tabs are disabled to avoid the DOM update, and let the tabset JS solely handle tab disabling.
I'd attempted to remove the tabs following the DOM update and adding the new DOM element as a 'new' tab at the old index, however the out-of-sync Tab object cannot be removed from the tabset either, due to an error related to the tabset attempting to remove the absent DOM element from its subtree.
I've made some success with the last technique I mention above.
The tabset diffs the updated set of disabled indexes with old one (if one exists) and uses JS to disable the individual tabs.
This solution unfortunately allows the selectedIndex to be loaded at the tabset construction, even though it may be disabled. This may be able to be corrected.
There may also be styling difference between this client-managed approach and the previous server-managed disabled styling.
The styling issues I mention above aren't of concern. The fixed version looks fine.
However the on-construction selection of the selectedIndex that occurs before our JS can apply the disabled property, will be very problematic. I don't see how this could be avoided without large modifications to the YUI code, or fixing the larger issue using yet some other technique.
The issue is we want to initialize the tabs with the disabled style class so the YUI construction won't do an initial selection. However later when we remove that disabled style class and enable the tab, we don't want an update (that kills our events), or that update has to somehow play nice with YUI, and rebind the new DOM element.
ICE-7627 - Partial fix for dynamic tabpane disabled issues. Using JS-managed state as DOM update ruined the existing Tab object, and I could not find a way to rebind the Tab object to the new DOM element; and removing the now DOM-less Tab from the TabView caused an error, so a newly created Tab object could not be added in its place. This change to JS initialized state however has introduced another problematic behaviour, that the selectedIndex is always loaded at tabset creation even though it is disabled by further constructor calls shortly after. Either the disabling will need to occur at Tab creation, during TabSet creation, or eventually the old technique will need to be used, and must elegantly update or replace the existing Tab object, rather than breaking it.
Reassigning to Mark for eventual revision to fix selectedIndex initialization.
More extensive YUI knowledge will be required to gracefully update/replace the Tab object that has been destroyed by the DOM update, or modify the TabView construction so that my technique of JS disabled initialization occurs soon enough to prevent the invalid initial selection.
Added custom styling and backported change to 2.X EE maintenance.
Fixed again in this other branch.
Revision #27275
ICE-7627 - Backporting tabset dynamic disabled attribute fix.
Attached source code and built war file to reproduce issue.
Steps to reproduce: