Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Use a per-element gesture registration system.
Browse files Browse the repository at this point in the history
This provides better ergonomics for touch, removes a global per-shadowroot MutationObserver, and only generates gestures
that are being listened for.

Need metadata for event -> dependency mappings

Remove ShadowDOM Polyfill logic

Handling gestures at the element level rather than the scope level should be a much cleaner fix for #4

Remove MutationObserver and Installer

Per-element tracking removes need for watching DOM

addGesture and removeGesture

only set touch-action if one is given

remove installer from karma config
  • Loading branch information
dfreedm committed Jul 16, 2014
1 parent 2a3ea64 commit 649f44f
Show file tree
Hide file tree
Showing 16 changed files with 124 additions and 235 deletions.
1 change: 0 additions & 1 deletion build.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"src/eventFactory.js",
"src/pointermap.js",
"src/dispatcher.js",
"src/installer.js",
"src/mouse.js",
"src/touch.js",
"src/ms.js",
Expand Down
1 change: 0 additions & 1 deletion conf/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ module.exports = function(karma) {
'polymer-gestures/src/eventFactory.js',
'polymer-gestures/src/pointermap.js',
'polymer-gestures/src/dispatcher.js',
'polymer-gestures/src/installer.js',
'polymer-gestures/src/mouse.js',
'polymer-gestures/src/touch.js',
'polymer-gestures/src/ms.js',
Expand Down
1 change: 0 additions & 1 deletion polymer-gestures.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
<script src="src/eventFactory.js"></script>
<script src="src/pointermap.js"></script>
<script src="src/dispatcher.js"></script>
<script src="src/installer.js"></script>
<script src="src/mouse.js"></script>
<script src="src/touch.js"></script>
<script src="src/ms.js"></script>
Expand Down
1 change: 0 additions & 1 deletion polymer-gestures.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
'src/eventFactory.js',
'src/pointermap.js',
'src/dispatcher.js',
'src/installer.js',
'src/mouse.js',
'src/touch.js',
'src/ms.js',
Expand Down
92 changes: 71 additions & 21 deletions src/dispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,6 @@

var eventFactory = scope.eventFactory;

var hasSDPolyfill = scope.hasSDPolyfill;
var wrap = scope.wrap;

/**
* This module is for normalizing events. Mouse and Touch events will be
* collected here, and fire PointerEvents that have the same semantics, no
Expand All @@ -117,6 +114,8 @@
eventSources: Object.create(null),
eventSourceList: [],
gestures: [],
// map gesture event -> {listeners: int, index: gestures[int]}
dependencyMap: Object.create(null),
gestureQueue: [],
/**
* Add a new event source that will generate pointer events.
Expand All @@ -140,6 +139,13 @@
}
},
registerGesture: function(name, source) {
var obj = Object.create(null);
obj.listeners = 0;
obj.index = this.gestures.length;
for (var i = 0, g; i < source.exposes.length; i++) {
g = source.exposes[i];
this.dependencyMap[g] = obj;
}
this.gestures.push(source);
},
register: function(element) {
Expand Down Expand Up @@ -177,6 +183,9 @@
// This is used to prevent multiple dispatch of events from
// platform events. This can happen when two elements in different scopes
// are set up to create pointer events, which is relevant to Shadow DOM.

// TODO(dfreedm): make this check more granular, allow for minimal event generation
// e.g inEvent._handledByPG['tap'] and inEvent._handledByPG['track'], etc
if (inEvent._handledByPG) {
return;
}
Expand All @@ -200,20 +209,10 @@
}
},
addEvent: function(target, eventName) {
// NOTE: Work around for #4, use native event listener in SD Polyfill
if (hasSDPolyfill) {
target.addEventListener_(eventName, this.boundHandler);
} else {
target.addEventListener(eventName, this.boundHandler);
}
target.addEventListener(eventName, this.boundHandler);
},
removeEvent: function(target, eventName) {
// NOTE: Work around for #4, use native event listener in SD Polyfill
if (hasSDPolyfill) {
target.removeEventListener_(eventName, this.boundHandler);
} else {
target.removeEventListener(eventName, this.boundHandler);
}
target.removeEventListener(eventName, this.boundHandler);
},
// EVENT CREATION AND TRACKING
/**
Expand Down Expand Up @@ -255,7 +254,6 @@
if (HAS_SVG_INSTANCE && eventCopy[p] instanceof SVGElementInstance) {
eventCopy[p] = eventCopy[p].correspondingUseElement;
}
eventCopy[p] = wrap(eventCopy[p]);
}
}
// keep the semantics of preventDefault
Expand Down Expand Up @@ -288,7 +286,7 @@
for (var j = 0, g, fn; j < this.gestures.length; j++) {
g = this.gestures[j];
fn = g[e.type];
if (fn) {
if (g.enabled && fn) {
fn.call(g, e);
}
}
Expand All @@ -306,9 +304,61 @@
dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);
dispatcher.boundGestureTrigger = dispatcher.gestureTrigger.bind(dispatcher);
scope.dispatcher = dispatcher;
scope.register = function(root) {
dispatcher.register(root);

/**
*
* Initializes `node` for receiving events of type `gesture`
*
* Optionally, `touchAction` will set the touch-action of the node.
* The default is `auto`.
*
* If `gesture` is the only listener set up, the underlying gesture is then enabled.
*
* @param {Element} node
* @param {string} gesture
* @param {string} touchAction
*/
scope.addGesture = function(node, gesture, touchAction) {
var dep = dispatcher.dependencyMap[gesture];
if (dep) {
if (touchAction && !node.hasAttribute('touch-action')) {
node.setAttribute('touch-action', touchAction);
}
if (dep.listeners === 0) {
dispatcher.gestures[dep.index].enabled = true;
}
dep.listeners++;
if (!node._pgListeners) {
dispatcher.register(node);
node._pgListeners = 0;
}
node._pgListeners++;
}
};

/**
* Tears down the gesture configuration for `node`
*
* If no more listeners for `gesture` exist, the underlying gesture recognizer is disabled.
*
* @param {Element} node
* @param {string} gesture
*/
scope.removeGesture = function(node, gesture) {
var dep = dispatcher.dependencyMap[gesture];
if (dep) {
if (dep.listeners > 0) {
dep.listeners--;
}
if (dep.listeners === 0) {
dispatcher.gestures[dep.index].enabled = false;
}
if (node._pgListeners > 0) {
node._pgListeners--;
}
if (node._pgListeners === 0) {
dispatcher.unregister(node);
}
}
};
scope.unregister = dispatcher.unregister.bind(dispatcher);
scope.wrap = wrap;
})(window.PolymerGestures);
5 changes: 5 additions & 0 deletions src/hold.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
'move',
'up',
],
exposes: [
'hold',
'holdpulse',
'release'
],
heldPointer: null,
holdJob: null,
pulse: function() {
Expand Down
124 changes: 0 additions & 124 deletions src/installer.js

This file was deleted.

12 changes: 7 additions & 5 deletions src/mouse.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@
'mousemove',
'mouseup'
],
exposes: [
'down',
'up',
'move'
],
register: function(target) {
if (target !== document) {
return;
}
dispatcher.listen(target, this.events);
},
unregister: function(target) {
Expand Down Expand Up @@ -71,7 +73,7 @@
this.mouseup(inEvent);
}
var e = this.prepareEvent(inEvent);
e.target = scope.wrap(scope.findTarget(inEvent));
e.target = scope.findTarget(inEvent);
pointermap.set(this.POINTER_ID, e.target);
dispatcher.down(e);
}
Expand All @@ -95,7 +97,7 @@
mouseup: function(inEvent) {
if (!this.isEventSimulatedFromTouch(inEvent)) {
var e = this.prepareEvent(inEvent);
e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
e.relatedTarget = scope.findTarget(inEvent);
e.target = pointermap.get(this.POINTER_ID);
dispatcher.up(e);
this.cleanupMouse();
Expand Down
6 changes: 3 additions & 3 deletions src/ms.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
},
MSPointerDown: function(inEvent) {
var e = this.prepareEvent(inEvent);
e.target = scope.wrap(scope.findTarget(inEvent));
e.target = scope.findTarget(inEvent);
pointermap.set(inEvent.pointerId, e.target);
dispatcher.down(e);
},
Expand All @@ -59,14 +59,14 @@
},
MSPointerUp: function(inEvent) {
var e = this.prepareEvent(inEvent);
e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
e.relatedTarget = scope.findTarget(inEvent);
e.target = pointermap.get(e.pointerId);
dispatcher.up(e);
this.cleanup(inEvent.pointerId);
},
MSPointerCancel: function(inEvent) {
var e = this.prepareEvent(inEvent);
e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
e.relatedTarget = scope.findTarget(inEvent);
e.target = pointermap.get(e.pointerId);
dispatcher.cancel(e);
this.cleanup(inEvent.pointerId);
Expand Down
Loading

0 comments on commit 649f44f

Please sign in to comment.