• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5part of engine;
6
7/// Listens to HTML "click" gestures detected by the browser.
8///
9/// This gestures is different from the click and tap gestures detected by the
10/// framework from raw pointer events. When an assistive technology is enabled
11/// the browser may not send us pointer events. In that mode we forward HTML
12/// click as [ui.SemanticsAction.tap].
13class Tappable extends RoleManager {
14  Tappable(SemanticsObject semanticsObject)
15      : super(Role.tappable, semanticsObject);
16
17  html.EventListener _clickListener;
18
19  @override
20  void update() {
21    final html.Element element = semanticsObject.element;
22
23    semanticsObject.setAriaRole(
24        'button', semanticsObject.hasFlag(ui.SemanticsFlag.isButton));
25
26    if (!semanticsObject.hasFlag(ui.SemanticsFlag.isEnabled) &&
27        semanticsObject.hasFlag(ui.SemanticsFlag.isButton)) {
28      semanticsObject.element.setAttribute('aria-disabled', 'true');
29      _stopListening();
30    } else {
31      // Excluding text fields because text fields have browser-specific logic
32      // for recognizing taps and activating the keyboard.
33      if (semanticsObject.hasAction(ui.SemanticsAction.tap) &&
34          !semanticsObject.hasFlag(ui.SemanticsFlag.isTextField)) {
35        if (_clickListener == null) {
36          _clickListener = (_) {
37            if (semanticsObject.owner.gestureMode !=
38                GestureMode.browserGestures) {
39              return;
40            }
41            ui.window.onSemanticsAction(
42                semanticsObject.id, ui.SemanticsAction.tap, null);
43          };
44          element.addEventListener('click', _clickListener);
45        }
46      } else {
47        _stopListening();
48      }
49    }
50  }
51
52  void _stopListening() {
53    if (_clickListener == null) {
54      return;
55    }
56
57    semanticsObject.element.removeEventListener('click', _clickListener);
58    _clickListener = null;
59  }
60
61  @override
62  void dispose() {
63    _stopListening();
64    semanticsObject.setAriaRole('button', false);
65  }
66}
67