Created
December 26, 2014 05:30
-
-
Save sousk/4abd5c9bdf6c4f658988 to your computer and use it in GitHub Desktop.
Dispatching touch events between HTML which contains iframe and the document of that iframe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
@license WTFPL | |
@author @sou | |
This library dispatches touch events from an element to another on the different document through iframe. | |
NOTE: | |
This library only suports Mobile Safari as each browsers have different specifications for touch event creation. | |
You might expand _dispatch method if you want to deal with other browsers. | |
NOTE: | |
Origins of src attribute of the iframe and HTML you work with should be the same as we need to access contentDocument via iframe. | |
**/ | |
function TouchEventDispatcher(source, iframe) { | |
if (! 'ontouchstart' in source || ! 'contentDocument' in iframe) { | |
throw new TypeError("Unexpected type of objects has been passed"); | |
} | |
this._source = source; | |
this._iframe = iframe; | |
this._listeners = {}; | |
} | |
TouchEventDispatcher.prototype = { | |
start: TouchEventDispatcher_start, | |
end: TouchEventDispatcher_end, | |
listen: TouchEventDispatcher_listen, | |
once: TouchEventDispatcher_once, | |
_reset: TouchEventDispatcher_reset, | |
_dispatch: TouchEventDispatcher_dispatch, | |
handleEvent: TouchEventDispatcher_handleEvent | |
}; | |
function TouchEventDispatcher_handleEvent(evt) { | |
var listeners = this._listeners[evt.type]; | |
if (listeners) { | |
for (var i = 0; i < listeners.every.length; i++) { | |
listeners.every[i](evt); | |
} | |
for (var j = 0; j < listeners.once.length; j++) { | |
listeners.once[j](evt); | |
} | |
listeners.once = []; | |
} | |
} | |
function TouchEventDispatcher_listen(type, fn, isOnce) { | |
if (! this._listeners[type]) { | |
this._listeners[type] = { | |
every: [], | |
once: [] | |
}; | |
this._source.addEventListener(type, this, false); | |
} | |
if (isOnce) { | |
this._listeners[type].once.push(fn); | |
} | |
else { | |
this._listeners[type].every.push(fn); | |
} | |
} | |
function TouchEventDispatcher_once(type, fn) { | |
this.listen(type, fn, true); | |
} | |
function TouchEventDispatcher_start() { | |
var that = this; | |
this.listen('touchstart', function (evt) { | |
that._touched = true; | |
var t = evt.touches[0]; | |
if (t) { | |
that._point = [t.clientX, t.clientY]; | |
that._dispatch('touchstart'); | |
} | |
}); | |
this.listen('touchmove', function (evt) { | |
if (this._touched) { | |
var t = evt.touches[0]; | |
if (t) { | |
that._point = [t.clientX, t.clientY]; | |
} | |
// dispatching touchmove costs so high that we do not support it by default | |
// that._dispatch('touchmove'); | |
} | |
}); | |
this.listen('touchend', function (evt) { | |
if (that._touched) { | |
that._dispatch('touchend'); | |
} | |
that._reset(); | |
}); | |
this.listen('touchcancel', function (evt) { | |
that._reset(); | |
}); | |
} | |
function TouchEventDispatcher_end() { | |
var types = this._listeners; | |
for (var i = 0; i < types.length; i++) { | |
this._source.removeEventListener(types[i], this); | |
} | |
this._reset(); | |
} | |
function TouchEventDispatcher_reset() { | |
this._point = [null, null]; | |
this._touched = false; | |
} | |
function TouchEventDispatcher_dispatch(type) { | |
var identifier = Date.now(); | |
var x = this._point[0], y = this._point[1]; | |
var doc = this._iframe.contentDocument; | |
var touch = doc.createTouch( | |
doc.defaultView, // view | |
doc.body, | |
identifier, | |
x, y, x, y | |
); | |
var touches = doc.createTouchList(touch); | |
var evt = doc.createEvent('TouchEvent'); | |
evt.initTouchEvent( | |
type, // {String} type | |
true, // {Boolean} canBubble | |
true, // {Boolean} cancelable | |
doc.defaultView, // {Window} view | |
1, // {Number} detail | |
0, // {Number} screenX | |
0, // {Number} screenY | |
0, // {Number} clientX | |
0, // {Number} clientY | |
false, // {Boolean} ctrlKey | |
false, // {Boolean} altKey | |
false, // {Boolean} shiftKey | |
false, // {Boolean} metaKey | |
touches, // {TouchList} touches | |
touches, // {TouchList} targetTouches | |
touches, // {TouchList} changedTouches | |
0, // {Number} scale(0 - 1) | |
0 // {Number} rotation | |
); | |
var elm = doc.elementFromPoint(x, y); | |
elm.dispatchEvent(evt); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment