Projects‎ > ‎XForms‎ > ‎

Improved implementation of event handlers


This is essentially implemented in Orbeon Forms since 2011-12-16.

(Some side issues have been entered separately in the issues tracker.)


The 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):
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


  • 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)


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 event

Information 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]
    • ⇒ should be able to remove this entirely!
What XFormsActionInterpreter needs to run:
  • XFormsContainingDocument
  • XFormsContextStack for the outer action

Next steps

Current way of dealing with event handlers is messy ⇒ implement Representation of outer action handlers within controls.
  • 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]