StatusThis is essentially implemented in Orbeon Forms since 2011-12-16.
(Some side issues have been entered separately in the issues tracker.) RationaleThe current code in EventHandlerImpl and the way event handlers are extracted has a long "history".The code is hard to understand and has at least one bug (possible duplicates here): The first idea is to refactor this code to make it more sane and fix the above.
This might helps also fixing/implementing the following: This should also open the door to improving event dispatch, which is: - not very well written
- probably inefficient as well (navigating up and down the DOM while checking a lot of things)
How things work now- event handlers are extracted during static analysis
- instances of
EventHandlerImpl are created based on searching for event handler events in - control trees (via XPath)
- models (via XPath)
- XBL's xbl:handler (direct extraction)
- information kept is purely static, and dynamic aspects obtained during actual event dispatch
Current difficulties- event extraction code is not very well written and error-prone
- semantic of EventHandlerImpl fields is unclear (XBL-container related information in particular)
- registration of EventHandlerImpl for XBL handlers is clumsy
- extracting handlers under XBL bound nodes is incorrectly done (see TODOs in code)
- currently they are specially treated and extracted "from the outside"
- other descendants not handled
- events are not properly contained within XBL scopes and can impact other scopes
- retargeting is not done properly
How things should work- event handler extraction still takes place during static analysis [DONE]
- since we already iterate over controls, don't use XPath to extract information, do this during visiting of DOM [DONE]
- actual creation of handlers is done once XBL bindings have been analyzed fully so that information about all controls is available [DONE]
- event handlers under bound nodes
- direct children
- we might want to change that and let the XBL component handle this
⇒ refactor existing XBL components (or could be compatibility flag)
- for other descendants, this is handled by component itself when including bound node content
- refactor EventHandlerImpl to have proper semantic [DONE]
- also refactor
XFormsActionInterpreter as needed [DONE] - containment of events: skip XBL scope boundaries as needed
- retargeting:
- implement correctly: only for focus events
Invariants- target, observer, and action are all in the same XBL scope (containment)
- BUT they can have different prefixed ids (with current id naming)
- NOTE: original target can be in different scope
- NOTE: there was idea of changing prefixed ids to reflect scopes!
- observer is always ancestor-of-self of target
- BUT action can be defined somewhere else (using ev:observer)
Observers- what can be an observer at this point
- controls
- XBL components
- xforms:model,
- xforms:instance
- xforms:submission
- top-level of document: #document
- top-level of part
- top-level of XBL component
- what could reasonably be an observer
- xforms:bind
- xforms:itemset
- xforms:item
- what should probably NOT be an observer (not much bang for buck)
Determination of the observer- if ev:observer:
- find prefixed ids (in same scope) for given observer ids [DONE]
- if no ev:observer:
- find ancestor observer in scope
- currently, might be None!
⇒ this should be fixed?
Handling an eventInformation to execute an event: - concrete the event information itself, including its target and event name
- concrete event observer
- XPath context information
- ideally BindingContext
- but currently XFormsContextStack initialized at BindingContext (we want to eliminate XFormsContextStack in the future)
XBL containers involved: - containerForObserver: container where the observer is located
- container where action is located: derive from concrete observer AND action prefixed id
- used for
- dispatching events from actions
- XXFormsScriptAction: obtain prefixed id [TODO: no need for container here!]
- XFormsActionAction: Variable: obtain prefixed id, getNamespaceMappings, getPartAnalysis [TODO: no need for container here!]
- XFormsMessageAction: XFormsUtils.getElementValue: getNamespaceMappings, getContainingDocument, get element value [TODO: no need for container here! but container goes far down]
- XFormsAPI.instanceRoot [TODO: incorrect, should be XBLContainer for action scope == target scope == observer scope]
- XFormsActionInterpreter.new
- ⇒ should be able to remove this entirely!
What XFormsActionInterpreter needs to run: - XFormsContainingDocument
- XFormsContextStack for the outer action
Next steps- static: EventHandlerImpl extends SimpleElementAnalysis [DONE]
- dynamic: XFormsActionControl [DONE]
- effective id
- points to EventHandlerImpl
- context but no binding
- if action-nested-within-action, then use closest ancestor action and use same context
- update Variable within action [DONE]
This allows to easily find the XPath context of an event handler. Then: - update EventHandlerImpl [DONE]
- update XFormsActionInterpreter [DONE]
|
|