Почему GWT не позволяет нам добавлять обработчики ключевых событий в элемент документа?

#events #gwt #keyboard-events

#Мероприятия #gwt #клавиатура-события

Вопрос:

Я знаю, что есть FocusPanel , к чему я могу прикрепить такие обработчики, но, по моему опыту, этот компонент ведет себя не так хорошо. Поэтому я хотел бы избежать этого, насколько это возможно.

Итак, мне интересно, почему нет способа прикрепить обработчики ключей и к документу? Согласно quirksmode.org он работает в кроссбраузерном режиме, так что это не должно вызывать беспокойства.

Я также пытался написать некоторый код JSNI, чтобы сделать это самостоятельно, который работает нормально для большинства случаев. Однако, если есть какой-либо другой виджет, который прослушивает то же событие, что и я, в документе, и этот виджет позволяет событию распространяться, я практически ничего не могу сделать с событием, которое дошло до документа, потому что оно помечено как мертвое, и исключение будет выдаваться всякий раз, когда я пытаюсь получить доступ к данным в документе.это событие.

Вот мой код на данный момент:

 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);
    }
  }-*/;
}
  

Комментарии:

1. У вас есть конкретная причина, по которой вы хотите добавить в документ вместо использования Event.addNativePreviewHandler() ?

2. Обратите внимание, что это addNativePreviewHandler действует на этапе захвата (эмулируется в IE), в то время как «присоединение к документу» будет находиться на стадии пузырьков. Это может иметь значение. Зависит от ваших потребностей.

3. @HilbrandBouwkamp, @ThomasBroyer addNativePreviewHandler, похоже, работает, но как мне преобразовать это событие в правильное KeyUpEvent ?

Ответ №1:

Как насчет следующего?

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

Он добавляет их в тело документа, но это не сильно отличается.

Комментарии:

1. Это отличается тем, что документ всегда занимает весь экран просмотра, а элемент body не обязательно. Например, если в теле есть CSS width: 200px; height: 200px; margin: 200px auto; , область тела действительно мала. Просто пример.

2. Вот почему я сказал «не сильно отличается», а не «то же самое». Однако относительно легко заставить body занимать весь экран просмотра. Я полагаю, что есть какой-то хакерский способ, который позволил бы зарегистрироваться в документе, даже не касаясь JSNI (используя Document.get().<Element>cast() , DOM.setEventListener и DOM.sinkEvents ).

3. да, кажется, это может сработать, но как мне преобразовать это событие в KeyUpEvent или подобное.

4. DomEvent.fireNativeEvent , где вы можете передать любую HasKeyUpHandlers или свою собственную реализацию HasHandlers , или просто использовать HandlerManager там, где вы бы ранее зарегистрировали свой HasKeyUpHandlers (как в виджетах).