blob: e60c9881918e509c6242d19c09a2c89a24ee6e60 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.6
part of engine;
/// Listens to HTML "click" gestures detected by the browser.
///
/// This gestures is different from the click and tap gestures detected by the
/// framework from raw pointer events. When an assistive technology is enabled
/// the browser may not send us pointer events. In that mode we forward HTML
/// click as [ui.SemanticsAction.tap].
class Tappable extends RoleManager {
Tappable(SemanticsObject semanticsObject)
: super(Role.tappable, semanticsObject);
html.EventListener _clickListener;
@override
void update() {
final html.Element element = semanticsObject.element;
semanticsObject.setAriaRole(
'button', semanticsObject.hasFlag(ui.SemanticsFlag.isButton));
if (!semanticsObject.hasFlag(ui.SemanticsFlag.isEnabled) &&
semanticsObject.hasFlag(ui.SemanticsFlag.isButton)) {
semanticsObject.element.setAttribute('aria-disabled', 'true');
_stopListening();
} else {
// Excluding text fields because text fields have browser-specific logic
// for recognizing taps and activating the keyboard.
if (semanticsObject.hasAction(ui.SemanticsAction.tap) &&
!semanticsObject.hasFlag(ui.SemanticsFlag.isTextField)) {
if (_clickListener == null) {
_clickListener = (_) {
if (semanticsObject.owner.gestureMode !=
GestureMode.browserGestures) {
return;
}
window.invokeOnSemanticsAction(
semanticsObject.id, ui.SemanticsAction.tap, null);
};
element.addEventListener('click', _clickListener);
}
} else {
_stopListening();
}
}
}
void _stopListening() {
if (_clickListener == null) {
return;
}
semanticsObject.element.removeEventListener('click', _clickListener);
_clickListener = null;
}
@override
void dispose() {
_stopListening();
semanticsObject.setAriaRole('button', false);
}
}