W3C home > Mailing lists > Public > www-dom@w3.org > July to September 2009

Detecting and Creating Events

From: Garrett Smith <dhtmlkitchen@gmail.com>
Date: Wed, 19 Aug 2009 22:18:20 -0700
Message-ID: <c9e12660908192218r74d1d14ax44af2520cd13a659@mail.gmail.com>
To: DOM mailing list <www-dom@w3.org>
The inability to easily and accurately detect events is a problem.
Programs want to know if an event is implemented at runtime. If it is,
then the feature can be used. If not, it a fallback stratety is in
order. Many new event types are being created and implemented. How can
a program feature-test to see if they are implemented?

Proposal: add a "hasEvent" method to EventTarget:

EventTarget {
  boolean hasEvent(in DOMString eventType)
}

This allows script to call the target's "hasEvent" method to see if
the event is (claimed to be) supported.

var hasFocusIn = false;

if(typeof el.hasEvent != "undefined") {
  hasFocusIn = el.hasEvent("domfocusin");
}

A potential complication would be - hasEvent("domfocusin") - returns
true, but the event handler does not fire as expected/specified, or
vice versa. Consider if the "hasEvent" inference check fails and this
failure is discovered in a browser. The program would need to be
amended so that it could detect the event where actually implemented,
not where - hasEvent - returns true. The program can create and
dispatch the event, setting a "fired" flag in the callback.

There should be a simple way to create and fire an event.

interface DocumentEvent {
  Event createInitedEvent(in domstring type, in Object options)
  raises(dom::DOMException);
}

In createInitedEvent, the type of event created is determined by the
string arg /type/, which is a prefixed with a DOM Interface (as a
string) followed by ".", followed by the event type. The event is
inited with the /options/. This is a "map" of options that the event
has, such as - offsetX - , - pageY - , etc.

The keys in /options/ depend on the event type. An option that is
unrecognized for a particular event type would be ignored. This is
important for extensibility -- new options may be possible in the
future.

The values and their types for each property/key in options is
constrained by the interface for the type of event. So, for example,
for a "click", an option - shiftKey -, - metaKey -, ctrlKey - would
require a boolean value, while - button - would require a dom unsigned
short. Options that are required but missing would get a default
value, so, for example:-

document.createInitedEvent("MouseEvent.click", null);

- would return a MouseEvent that, when dispatched on a target, would
have the following properties:-

  screenX : 0
  screenY : 0
  clientX : 0
  clientY : 0
  ctrlKey : false
  shiftKey : false
  altKey : false
  metaKey : false
  button : 0

Future versions of the API can be modified to have new types of events
and new options for existing events. These modifications can be
feature tested by a script running in a browser, so, if a browser
added a "progress" event to an object, and the program wanted to know
if it (a) "progress" was implemented on that object and (b) that event
has a "data" property, it would be able to make a feature check to
make such determination.

DOM 2 Events provides "createEvent(type)", but then required an
additional step initEvent or initMouseEvent. Method initMouseEvent
takes 15 arguments, none of them are memorable. It is painful to use.

With createInitedEvent, the following would be possible:-

function isFocusInSupported(){
  var hasFocusIn = false;

  if(typeof document.dispatchEvent != "undefined" &&
    typeof document.createInitedEvent != "undefined") {
    try {
      var fev = document.createInitedEvent("UIEvent.domfocusin", null),
          n = document.documentElement,
          ti = n.tabIndex;
      n.tabIndex = "0";
      if(n.dispatchEvent) {
        n.addEventListener("focus", gotFocus, false);
        n.dispatchEvent(fev);
      }
    } catch(ex) {
      if(ti) {
        n.tabIndex = ti;
      }
      n.removeEventListener("focus", gotFocus, false);
    }
  }
  return hasFocusIn;
}
function gotFocus(ev) {
  hasFocusIn = true;
}

(This assumes that callbacks fire synchronously, as they currently
seem to do in browsers. )

The proposed features are fully feature-testable, and so partially
backwards-compatible (failing with false negatives). Browsers that
don't support the new methods won't get there. It allows applications
to be forwards-compatible by providing the ability to check to see if
an event will fire.

isFocusInSupported();

Result: false

Garrett
Received on Thursday, 20 August 2009 05:19:01 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Friday, 22 June 2012 06:14:03 GMT