Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't GWT let us add key event handlers on document element?

I know there's FocusPanel on which I can attach such handlers, but in my experience this component does not behave that well. So I'd like to avoid it as much as possible.

So I'm wondering why there's no way to attach key handlers on document too? According to quirksmode.org it works cross-browser, so this shouldn't be a concern.

I've also tried writing some JSNI code to do this myself, which works ok for most cases. However, if there's any other widget that listens for the same event as me on document, and that widget lets the event propagate, I can do pretty much nothing with the event that reached the document, because it's marked as dead and an exception will be thrown whenever I try to access data on that event.

Here's my code so far:

public class RichDocument implements HasKeyPressHandlers, HasKeyDownHandlers,
    HasKeyUpHandlers, HasClickHandlers {

  private static final RichDocument instance = new RichDocument();

  public static RichDocument get() {
    return instance;
  }

  private final EventBus eventBus = new SimpleEventBus();

  private RichDocument() {
    startListening();
  }

  @Override
  public HandlerRegistration addClickHandler(ClickHandler handler) {
    return eventBus.addHandler(ClickEvent.getType(), handler);
  }

  @Override
  public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
    return eventBus.addHandler(KeyDownEvent.getType(), handler);
  }

  @Override
  public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
    return eventBus.addHandler(KeyPressEvent.getType(), handler);
  }

  @Override
  public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
    return eventBus.addHandler(KeyUpEvent.getType(), handler);
  }

  @Override
  public void fireEvent(GwtEvent<?> event) {
    eventBus.fireEvent(event);
  }

  private native void startListening()/*-{
    var self = this;

    var fire = function (event) {
      event = event || $wnd.event;
      @com.google.gwt.event.dom.client.DomEvent::fireNativeEvent(Lcom/google/gwt/dom/client/NativeEvent;Lcom/google/gwt/event/shared/HasHandlers;)(event, self);
    };

    if ($wnd.document.addEventListener) {
      $wnd.document.addEventListener("click", fire, false);
      $wnd.document.addEventListener("keydown", fire, false);
      $wnd.document.addEventListener("keypress", fire, false);
      $wnd.document.addEventListener("keyup", fire, false);
    } else {
      $wnd.document.attachEvent("onclick", fire);
      $wnd.document.attachEvent("onkeydown", fire);
      $wnd.document.attachEvent("onkeypress", fire);
      $wnd.document.attachEvent("onkeyup", fire);
    }
  }-*/;
}
like image 748
Ionuț G. Stan Avatar asked Jan 19 '23 12:01

Ionuț G. Stan


1 Answers

How about the following?

RootPanel.get().addDomHandler(handler, KeyDownEvent.getType());

It adds them on the document's body, but that's not much different.

like image 148
Thomas Broyer Avatar answered Mar 22 '23 22:03

Thomas Broyer