#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
(как в виджетах).