Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
207
assets/webapps/system.gaiamobile.org/js/touch_forwarder.js
Normal file
207
assets/webapps/system.gaiamobile.org/js/touch_forwarder.js
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
*
|
||||
* A simple helper encapsulating the APZC compliant logic
|
||||
* to forward touch events.
|
||||
*
|
||||
* var tf = new TouchForwarder(element);
|
||||
* tf.forward(evt);
|
||||
*/
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
const kSignificant = 10;
|
||||
|
||||
var TouchForwarder = function TouchForwarder(destinationElement) {
|
||||
this.destination = destinationElement || null;
|
||||
this._resetState();
|
||||
};
|
||||
|
||||
TouchForwarder.prototype.forward = function(e) {
|
||||
var element = this.destination;
|
||||
var touch;
|
||||
|
||||
// Should not forward to a frame that's not displayed
|
||||
if (element.getAttribute('aria-hidden') == 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.type) {
|
||||
case 'touchstart':
|
||||
sendTouchEvent(element, e);
|
||||
|
||||
touch = e.touches[0];
|
||||
this._startX = touch.clientX;
|
||||
this._startY = touch.clientY;
|
||||
this._shouldTap = true;
|
||||
break;
|
||||
|
||||
case 'touchmove':
|
||||
sendTouchEvent(element, e);
|
||||
touch = e.touches[0];
|
||||
this._updateShouldTap(touch);
|
||||
break;
|
||||
|
||||
case 'touchend':
|
||||
sendTouchEvent(element, e);
|
||||
|
||||
touch = e.changedTouches[0];
|
||||
this._updateShouldTap(touch);
|
||||
|
||||
if (this._shouldTap) {
|
||||
sendTapMouseEvents(element, touch.clientX, touch.clientY);
|
||||
}
|
||||
|
||||
this._resetState();
|
||||
break;
|
||||
|
||||
case 'click':
|
||||
sendTapMouseEvents(element, e.clientX, e.clientY);
|
||||
break;
|
||||
|
||||
case 'touchcancel':
|
||||
sendTouchEvent(element, e);
|
||||
this._resetState();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
TouchForwarder.prototype._resetState = function() {
|
||||
this._startX = null;
|
||||
this._startY = null;
|
||||
this._shouldTap = false;
|
||||
};
|
||||
|
||||
TouchForwarder.prototype._updateShouldTap = function(touch) {
|
||||
var deltaX = Math.abs(touch.clientX - this._startX);
|
||||
var deltaY = Math.abs(touch.clientY - this._startY);
|
||||
|
||||
if (deltaX > kSignificant || deltaY > kSignificant) {
|
||||
this._shouldTap = false;
|
||||
}
|
||||
};
|
||||
|
||||
function sendTouchEvent(element, e) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only IFRAMEs support sendTouchEvent().
|
||||
var args = createSendTouchEventArgumentList(e);
|
||||
if (element.sendTouchEvent) {
|
||||
element.sendTouchEvent.apply(element, args);
|
||||
} else {
|
||||
sendTouchEventToElement.apply(element, args);
|
||||
}
|
||||
}
|
||||
|
||||
function sendTapMouseEvents(el, x, y) {
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only IFRAME supports sendMouseEvent().
|
||||
if (el.sendMouseEvent) {
|
||||
el.sendMouseEvent('mousemove', x, y, 0, 0, 0);
|
||||
el.sendMouseEvent('mousedown', x, y, 0, 1, 0);
|
||||
el.sendMouseEvent('mouseup', x, y, 0, 1, 0);
|
||||
} else {
|
||||
// For normal elements, we must synthesize our own 'click' event too.
|
||||
var mouseProps = {
|
||||
clientX: x,
|
||||
clientY: y,
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
};
|
||||
el.dispatchEvent(new MouseEvent('mousemove', mouseProps));
|
||||
el.dispatchEvent(new MouseEvent('mousedown', mouseProps));
|
||||
el.dispatchEvent(new MouseEvent('mouseup', mouseProps));
|
||||
el.dispatchEvent(new MouseEvent('click', mouseProps));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Like HTMLIFrameElement.sendTouchEvent(), but for all other elements.
|
||||
*
|
||||
* @this {HTMLElement}
|
||||
*/
|
||||
function sendTouchEventToElement(
|
||||
type, identifiers, xs, ys, rxs, rys, rs, fs, count, modifiers) {
|
||||
|
||||
var touchEvent = document.createEvent('TouchEvent');
|
||||
|
||||
var touches = document.createTouchList(identifiers.map((ident, idx) => {
|
||||
return document.createTouch(
|
||||
/* view: */ window,
|
||||
/* target: */ this,
|
||||
/* identifier: */ ident,
|
||||
/* pageX: */ xs[idx],
|
||||
/* pageY: */ ys[idx],
|
||||
/* screenX: */ xs[idx],
|
||||
/* screenY: */ ys[idx],
|
||||
/* clientX: */ xs[idx],
|
||||
/* clientY: */ ys[idx],
|
||||
/* radiusX: */ rxs[idx],
|
||||
/* radiusY: */ rys[idx],
|
||||
/* rotationAngle: */ rs[idx],
|
||||
/* force: */ fs[idx]
|
||||
);
|
||||
}));
|
||||
|
||||
var emptyTouches = document.createTouchList([]);
|
||||
|
||||
touchEvent.initTouchEvent(
|
||||
/* type: */ type,
|
||||
/* canBubble: */ true,
|
||||
/* cancelable: */ true,
|
||||
/* view: */ window,
|
||||
/* detail: */ 0,
|
||||
/* ctrlKey: */ modifiers & 2,
|
||||
/* altKey: */ modifiers & 1,
|
||||
/* shiftKey: */ modifiers & 4,
|
||||
/* metaKey: */ modifiers & 8,
|
||||
/* touches: */
|
||||
(type === 'touchend' || type === 'touchcancel') ? emptyTouches : touches,
|
||||
/* targetTouches: */
|
||||
(type === 'touchend' || type === 'touchcancel') ? emptyTouches : touches,
|
||||
/* changedTouches: */ touches
|
||||
);
|
||||
|
||||
|
||||
/* jshint validthis:true */
|
||||
this.dispatchEvent(touchEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an argument list suitable for HTMLIFrameElement.sendTouchEvent().
|
||||
*/
|
||||
function createSendTouchEventArgumentList(e) {
|
||||
var type = e.type;
|
||||
var relevantTouches = (e.type === 'touchend') ?
|
||||
e.changedTouches : e.touches;
|
||||
var identifiers = [];
|
||||
var xs = [];
|
||||
var ys = [];
|
||||
var rxs = [];
|
||||
var rys = [];
|
||||
var rs = [];
|
||||
var fs = [];
|
||||
var modifiers = 0;
|
||||
|
||||
for (var i = 0; i < relevantTouches.length; i++) {
|
||||
var t = relevantTouches[i];
|
||||
|
||||
identifiers.push(t.identifier);
|
||||
xs.push(t.pageX);
|
||||
ys.push(t.pageY);
|
||||
rxs.push(t.radiusX);
|
||||
rys.push(t.radiusY);
|
||||
rs.push(t.rotationAngle);
|
||||
fs.push(t.force);
|
||||
}
|
||||
|
||||
return [type, identifiers, xs, ys, rxs, rys, rs, fs, xs.length, modifiers];
|
||||
}
|
||||
|
||||
exports.TouchForwarder = TouchForwarder;
|
||||
}(window));
|
||||
Loading…
Reference in a new issue