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

Unified Diff: third_party/polymer/v0_8/components/polymer/src/lib/gestures.html

Issue 1082403004: Import Polymer 0.8 and several key elements. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Also remove polymer/explainer Created 5 years, 8 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
Index: third_party/polymer/v0_8/components/polymer/src/lib/gestures.html
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/gestures.html b/third_party/polymer/v0_8/components/polymer/src/lib/gestures.html
new file mode 100644
index 0000000000000000000000000000000000000000..c8ac3fb99bfa58718c8211c0f1d7be5dc4815484
--- /dev/null
+++ b/third_party/polymer/v0_8/components/polymer/src/lib/gestures.html
@@ -0,0 +1,284 @@
+<!--
+@license
+Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<script>
+
+(function(scope) {
+
+ 'use strict';
+
+ var async = scope.Base.async;
+
+ var Gestures = {
+ gestures: {},
+
+ // automate the event listeners for the native events
+ // TODO(dfreedm): add a way to remove handlers.
+ add: function(evType, node, handler) {
+ // listen for events in order to "recognize" this event
+ var g = this.gestures[evType];
+ var gn = '_' + evType;
+ var info = {started: false, abortTrack: false, oneshot: false};
+ if (g && !node[gn]) {
+ if (g.touchaction) {
+ this._setupTouchAction(node, g.touchaction, info);
+ }
+ for (var i = 0, n, sn, fn; i < g.deps.length; i++) {
+ n = g.deps[i];
+ fn = g[n].bind(g, info);
+ sn = '_' + evType + '-' + n;
+ // store the handler on the node for future removal
+ node[sn] = fn;
+ node.addEventListener(n, fn);
+ }
+ node[gn] = 0;
+ }
+ // listen for the gesture event
+ node[gn]++;
+ node.addEventListener(evType, handler);
+ },
+
+ remove: function(evType, node, handler) {
+ var g = this.gestures[evType];
+ var gn = '_' + evType;
+ if (g && node[gn]) {
+ for (var i = 0, n, sn, fn; i < g.deps.length; i++) {
+ n = g.deps[i];
+ sn = '_' + evType + '-' + n;
+ fn = node[sn];
+ if (fn){
+ node.removeEventListener(n, fn);
+ // remove stored handler to allow GC
+ node[sn] = undefined;
+ }
+ }
+ node[gn] = node[gn] ? (node[gn] - 1) : 0;
+ node.removeEventListener(evType, handler);
+ }
+ },
+
+ register: function(recog) {
+ this.gestures[recog.name] = recog;
+ },
+
+ // touch will make synthetic mouse events
+ // preventDefault on touchend will cancel them,
+ // but this breaks <input> focus and link clicks
+ // Disabling "mouse" handlers for 500ms is enough
+
+ _cancelFunction: null,
+
+ cancelNextClick: function(timeout) {
+ if (!this._cancelFunction) {
+ timeout = timeout || 500;
+ var self = this;
+ var reset = function() {
+ var cfn = self._cancelFunction;
+ if (cfn) {
+ clearTimeout(cfn.id);
+ document.removeEventListener('click', cfn, true);
+ self._cancelFunction = null;
+ }
+ };
+ var canceller = function(e) {
+ e.tapPrevented = true;
+ reset();
+ };
+ canceller.id = setTimeout(reset, timeout);
+ this._cancelFunction = canceller;
+ document.addEventListener('click', canceller, true);
+ }
+ },
+
+ // try to use the native touch-action, if it exists
+ _hasNativeTA: typeof document.head.style.touchAction === 'string',
+
+ // set scrolling direction on node to check later on first move
+ // must call this before adding event listeners!
+ setTouchAction: function(node, value) {
+ if (this._hasNativeTA) {
+ node.style.touchAction = value;
+ }
+ node.touchAction = value;
+ },
+
+ _setupTouchAction: function(node, value, info) {
+ // reuse custom value on node if set
+ var ta = node.touchAction;
+ value = ta || value;
+ // set an anchor point to see how far first move is
+ node.addEventListener('touchstart', function(e) {
+ var t = e.changedTouches[0];
+ info.initialTouch = {x: t.clientX, y: t.clientY};
+ info.abortTrack = false;
+ info.oneshot = false;
+ });
+ node.addEventListener('touchmove', function(e) {
+ // only run this once
+ if (info.oneshot) {
+ return;
+ }
+ info.oneshot = true;
+ // "none" means always track
+ if (value === 'none') {
+ return;
+ }
+ // "auto" is default, always scroll
+ // bail-out if touch-action did its job
+ // the touchevent is non-cancelable if the page/area is scrolling
+ if (value === 'auto' || !value || (ta && !e.cancelable)) {
+ info.abortTrack = true;
+ return;
+ }
+ // check first move direction
+ // unfortunately, we can only make the decision in the first move,
+ // so we have to use whatever values are available.
+ // Typically, this can be a really small amount, :(
+ var t = e.changedTouches[0];
+ var x = t.clientX, y = t.clientY;
+ var dx = Math.abs(info.initialTouch.x - x);
+ var dy = Math.abs(info.initialTouch.y - y);
+ // scroll in x axis, abort track if we move more in x direction
+ if (value === 'pan-x') {
+ info.abortTrack = dx >= dy;
+ // scroll in y axis, abort track if we move more in y direction
+ } else if (value === 'pan-y') {
+ info.abortTrack = dy >= dx;
+ }
+ });
+ },
+
+ fire: function(target, type, detail, bubbles, cancelable) {
+ return target.dispatchEvent(
+ new CustomEvent(type, {
+ detail: detail,
+ bubbles: bubbles,
+ cancelable: cancelable
+ })
+ );
+ }
+
+ };
+
+ Gestures.register({
+ name: 'track',
+ touchaction: 'none',
+ deps: ['mousedown', 'touchmove', 'touchend'],
+
+ mousedown: function(info, e) {
+ var t = e.currentTarget;
+ var self = this;
+ var movefn = function movefn(e, up) {
+ if (!info.tracking && !up) {
+ // set up tap prevention
+ Gestures.cancelNextClick();
+ }
+ // first move is 'start', subsequent moves are 'move', mouseup is 'end'
+ var state = up ? 'end' : (!info.started ? 'start' : 'move');
+ info.started = true;
+ self.fire(t, e, state);
+ e.preventDefault();
+ };
+ var upfn = function upfn(e) {
+ // call mousemove function with 'end' state
+ movefn(e, true);
+ info.started = false;
+ // remove the temporary listeners
+ document.removeEventListener('mousemove', movefn);
+ document.removeEventListener('mouseup', upfn);
+ };
+ // add temporary document listeners as mouse retargets
+ document.addEventListener('mousemove', movefn);
+ document.addEventListener('mouseup', upfn);
+ },
+
+ touchmove: function(info, e) {
+ var t = e.currentTarget;
+ var ct = e.changedTouches[0];
+ // if track was aborted, stop tracking
+ if (info.abortTrack) {
+ return;
+ }
+ e.preventDefault();
+ // the first track event is sent after some hysteresis with touchmove.
+ // Use `started` state variable to differentiate the "first" move from
+ // the rest to make track.state == 'start'
+ // first move is 'start', subsequent moves are 'move'
+ var state = !info.started ? 'start' : 'move';
+ info.started = true;
+ this.fire(t, ct, state);
+ },
+
+ touchend: function(info, e) {
+ var t = e.currentTarget;
+ var ct = e.changedTouches[0];
+ // only trackend if track was started and not aborted
+ if (info.started && !info.abortTrack) {
+ // reset started state on up
+ info.started = false;
+ var ne = this.fire(t, ct, 'end');
+ // iff tracking, always prevent tap
+ e.tapPrevented = true;
+ }
+ },
+
+ fire: function(target, touch, state) {
+ return Gestures.fire(target, 'track', {
+ state: state,
+ x: touch.clientX,
+ y: touch.clientY
+ });
+ }
+
+ });
+
+ // dispatch a *bubbling* "tap" only at the node that is the target of the
+ // generating event.
+ // dispatch *synchronously* so that we can implement prevention of native
+ // actions like links being followed.
+ //
+ // TODO(dfreedm): a tap should not occur when there's too much movement.
+ // Right now, a tap can occur when a touchend happens very far from the
+ // generating touch.
+ // This *should* obviate the need for tapPrevented via track.
+ Gestures.register({
+ name: 'tap',
+ deps: ['click', 'touchend'],
+
+ click: function(info, e) {
+ this.forward(e);
+ },
+
+ touchend: function(info, e) {
+ Gestures.cancelNextClick();
+ this.forward(e);
+ },
+
+ forward: function(e) {
+ // prevent taps from being generated from events that have been
+ // canceled (e.g. via cancelNextClick) or already handled via
+ // a listener lower in the tree.
+ if (!e.tapPrevented) {
+ e.tapPrevented = true;
+ this.fire(e.target);
+ }
+ },
+
+ // fire a bubbling event from the generating target.
+ fire: function(target) {
+ Gestures.fire(target, 'tap', {}, true);
+ }
+
+ });
+
+ scope.Gestures = Gestures;
+
+})(Polymer);
+
+</script>

Powered by Google App Engine
This is Rietveld 408576698