Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: client/touch/ClickBuster.dart

Issue 9382027: Move client/{base, observable, layout, touch, util, view} to samples/ui_lib . (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « client/touch/BezierPhysics.dart ('k') | client/touch/EventUtil.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: client/touch/ClickBuster.dart
===================================================================
--- client/touch/ClickBuster.dart (revision 4144)
+++ client/touch/ClickBuster.dart (working copy)
@@ -1,215 +0,0 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/**
- * Click buster implementation, which is a behavior that prevents native clicks
- * from firing at undesirable times. There are two scenarios where we may want
- * to 'bust' a click.
- *
- * Buttons implemented with touch events usually have click handlers as well.
- * This is because sometimes touch events stop working, and the click handler
- * serves as a fallback. Here we use a click buster to prevent the native click
- * from firing if the touchend event was succesfully handled.
- *
- * When native scrolling behavior is disabled (see Scroller), click events will
- * fire after the touchend event when the drag sequence is complete. The click
- * event also happens to fire at the location of the touchstart event which can
- * lead to some very strange behavior.
- *
- * This class puts a single click handler on the body, and calls preventDefault
- * on the click event if we detect that there was a touchend event that already
- * fired in the same spot recently.
- */
-class ClickBuster {
- /**
- * The threshold for how long we allow a click to occur after a touchstart.
- */
- static final _TIME_THRESHOLD = 2500;
-
- /**
- * The threshold for how close a click has to be to the saved coordinate for
- * us to allow it.
- */
- static final _DISTANCE_THRESHOLD = 25;
-
- /**
- * The list of coordinates that we use to measure the distance of clicks from.
- * If a click is within the distance threshold of any of these coordinates
- * then we allow the click.
- * TODO(ngeoffray): Should be DoubleLinkedQueue<num>
- */
- static var _coordinates;
-
- /** The last time preventGhostClick was called. */
- static int _lastPreventedTime;
-
- /**
- * This handler will prevent the default behavior for any clicks unless the
- * click is within the distance threshold of one of the temporary allowed
- * coordinates.
- */
- static void _onClick(Event e) {
- if (TimeUtil.now() - _lastPreventedTime > _TIME_THRESHOLD) {
- return;
- }
- final coord = new Coordinate.fromClient(e);
- // TODO(rnystrom): On Android, we get spurious click events at (0, 0). We
- // *do* want those clicks to be busted, so commenting this out fixes it.
- // Leaving it commented out instead of just deleting it because I'm not sure
- // what this code was intended to do to begin with.
- /*
- if (coord.x < 1 && coord.y < 1) {
- // TODO(jacobr): implement a configurable logging framework.
- // _logger.warning(
- // "Not busting click on label elem at(${coord.x}, ${coord.y})");
- return;
- }
- */
- var entry = _coordinates.firstEntry();
- while (entry != null) {
- if (_hitTest(entry.element,
- entry.nextEntry().element,
- coord.x,
- coord.y)) {
- entry.nextEntry().remove();
- entry.remove();
- return;
- } else {
- entry = entry.nextEntry().nextEntry();
- }
- }
-
- // TODO(jacobr): implement a configurable logging framework.
- // _logger.warning("busting click at ${coord.x}, ${coord.y}");
- e.stopPropagation();
- e.preventDefault();
- }
-
- /**
- * This handler will temporarily allow a click to occur near the touch event's
- * coordinates.
- */
- static void _onTouchStart(Event e) {
- TouchEvent te = e;
- final coord = new Coordinate.fromClient(te.touches[0]);
- _coordinates.add(coord.x);
- _coordinates.add(coord.y);
- window.setTimeout(() {
- _removeCoordinate(coord.x, coord.y);
- }, _TIME_THRESHOLD);
- _toggleTapHighlights(true);
- }
-
- /**
- * Hit test for whether a coordinate is within the distance threshold of an
- * event.
- */
- static bool _hitTest(num x, num y, num eventX, num eventY) {
- return (eventX - x).abs() < _DISTANCE_THRESHOLD &&
- (eventY - y).abs() < _DISTANCE_THRESHOLD;
- }
-
- /**
- * Remove one specified coordinate from the coordinates list.
- */
- static void _removeCoordinate(num x, num y) {
- var entry = _coordinates.firstEntry();
- while (entry != null) {
- if (entry.element == x && entry.nextEntry().element == y) {
- entry.nextEntry().remove();
- entry.remove();
- return;
- } else {
- entry = entry.nextEntry().nextEntry();
- }
- }
- }
-
- /**
- * Enable or disable tap highlights. They are disabled when preventGhostClick
- * is called so that the flicker on links is not invoked when the ghost click
- * does fire. This is due to a bug: links get highlighted even if the click
- * event has preventDefault called on it.
- */
- static void _toggleTapHighlights(bool enable) {
- document.body.style.setProperty(
- "-webkit-tap-highlight-color", enable ? "" : "rgba(0,0,0,0)", "");
- }
-
- /**
- * Registers new touches to create temporary "allowable zones" and registers
- * new clicks to be prevented unless they fall in one of the current
- * "allowable zones". Note that if the touchstart and touchend locations are
- * different, it is still possible for a ghost click to be fired if you
- * called preventDefault on all touchmove events. In this case the ghost
- * click will be fired at the location of the touchstart event, so the
- * coordinate you pass in should be the coordinate of the touchstart.
- */
- static void preventGhostClick(num x, num y) {
- // First time this is called the following occurs:
- // 1) Attaches a handler to touchstart events so that each touch will
- // temporarily create an "allowable zone" for clicks to occur in.
- // 2) Attaches a handler to click events so that each click will be
- // prevented unless it is in an "allowable zone".
- //
- // Every time this is called (including the first) the following occurs:
- // 1) Removes an allowable zone that contains the specified coordinate.
- //
- // How this enables click busting:
- // 1) User performs first click.
- // - No attached touchstart handler yet.
- // - preventGhostClick is called before the click event occurs, it
- // attaches the touchstart and click handlers.
- // - The click handler captures the user's click event and prevents it
- // from propagating since there is no "allowable zone".
- //
- // 2) User performs subsequent, to-be-busted click.
- // - touchstart event triggers the attached handler and creates a
- // temporary "allowable zone".
- // - preventGhostClick is called and removes the "allowable zone".
- // - The click handler captures the user's click event and prevents it
- // from propagating since there is no "allowable zone".
- //
- // 3) User performs a should-not-be-busted click.
- // - touchstart event triggers the attached handler and creates a
- // temporary "allowable zone".
- // - The click handler captures the user's click event and allows it to
- // propagate since the click falls in the "allowable zone".
- if (_coordinates === null) {
- // Listen to clicks on capture phase so they can be busted before anything
- // else gets a chance to handle them.
- document.on.click.add((e) { _onClick(e); }, true);
- document.on.focus.add((e) { _lastPreventedTime = 0; }, true);
-
- // Listen to touchstart on capture phase since it must be called prior to
- // every click or else we will accidentally prevent the click even if we
- // don't call preventGhostClick.
- Function startFn = (e) { _onTouchStart(e); };
- if (!Device.supportsTouch) {
- startFn = mouseToTouchCallback(startFn);
- }
- EventUtil.observe(document,
- Device.supportsTouch ? document.on.touchStart : document.on.mouseDown,
- startFn, true, true);
- _coordinates = new Queue<num>();
- }
-
- // Turn tap highlights off until we know the ghost click has fired.
- _toggleTapHighlights(false);
-
- // Above all other rules, we won't bust any clicks if there wasn't some call
- // to preventGhostClick in the last time threshold.
- _lastPreventedTime = TimeUtil.now();
- var entry = _coordinates.firstEntry();
- while (entry != null) {
- if (_hitTest(entry.element, entry.nextEntry().element, x, y)) {
- entry.nextEntry().remove();
- entry.remove();
- return;
- } else {
- entry = entry.nextEntry().nextEntry();
- }
- }
- }
-}
« no previous file with comments | « client/touch/BezierPhysics.dart ('k') | client/touch/EventUtil.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698