Created
December 6, 2011 18:10
-
-
Save wei-lee/1439235 to your computer and use it in GitHub Desktop.
This file contains 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
Ext.gesture.Manager = new Ext.AbstractManager({ | |
//first, add more events | |
eventNames: { | |
'touchstart': 'start', | |
'touchmove': 'move', | |
'touchend': 'end', | |
'mousedown': 'mousestart', | |
'mouseup': 'mouseend' | |
}, | |
defaultPreventedMouseEvents: [], | |
clickMoveThreshold: 5, | |
init: function () { | |
this.targets = []; | |
this.followTouches = []; | |
this.currentGestures = []; | |
this.currentTargets = []; | |
var touchScreen = false; | |
this.listenerWrappers = { | |
start: Ext.createDelegate(this.onTouchStart, this), | |
move: Ext.createDelegate(this.onTouchMove, this), | |
end: Ext.createDelegate(this.onTouchEnd, this), | |
mouse: Ext.createDelegate(this.onMouseEvent, this), | |
//and more wrappers | |
mousestart: Ext.createDelegate(this.onMouseStart, this), | |
mouseend: Ext.createDelegate(this.onMouseEnd, this) | |
}; | |
this.attachListeners(); | |
}, | |
freeze: function () { | |
this.isFrozen = true; | |
}, | |
thaw: function () { | |
this.isFrozen = false; | |
}, | |
getEventSimulator: function () { | |
if (!this.eventSimulator) { | |
this.eventSimulator = new Ext.util.EventSimulator(); | |
} | |
return this.eventSimulator; | |
}, | |
attachListeners: function () { | |
Ext.iterate(this.eventNames, function (key, name) { | |
//switch key and name to add more event listeners | |
//document.addEventListener(name, this.listenerWrappers[key], false); | |
document.addEventListener(key, this.listenerWrappers[name], false); | |
}, this); | |
if (Ext.supports.Touch) { | |
this.defaultPreventedMouseEvents.forEach(function (name) { | |
document.addEventListener(name, this.listenerWrappers['mouse'], true); | |
}, this); | |
} | |
}, | |
detachListeners: function () { | |
Ext.iterate(this.eventNames, function (key, name) { | |
//same again | |
//document.removeEventListener(name, this.listenerWrappers[key], false); | |
document.removeEventListener(key, this.listenerWrappers[name], false); | |
}, this); | |
if (Ext.supports.Touch) { | |
this.defaultPreventedMouseEvents.forEach(function (name) { | |
document.removeEventListener(name, this.listenerWrappers['mouse'], true); | |
}, this); | |
} | |
}, | |
onMouseEvent: function (e) { | |
if (!e.isSimulated) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
}, | |
//more mouse event handlers | |
onMouseStart: function (e) { | |
if (!this.touchStartFired) { | |
this.onTouchStart(e, true); | |
} else { | |
this.touchStartFired = false; | |
} | |
}, | |
onMouseEnd: function (e) { | |
if (!this.touchEndFired) { | |
this.onTouchEnd(e, true); | |
} else { | |
this.touchEndFired = false; | |
} | |
}, | |
onTouchStart: function (e, noset) { | |
var targets = [], | |
target = e.target; | |
if (e.stopped === true) { | |
return; | |
} | |
if (Ext.is.Android) { | |
if (!(target.tagName && ['input', 'textarea', 'select'].indexOf(target.tagName.toLowerCase()) !== -1)) { | |
e.preventDefault(); | |
} | |
} | |
if (this.isFrozen) { | |
return; | |
} | |
if (this.startEvent) { | |
this.onTouchEnd(e); | |
} | |
this.locks = {}; | |
this.currentTargets = [target]; | |
while (target) { | |
if (this.targets.indexOf(target) !== -1) { | |
targets.unshift(target); | |
} | |
target = target.parentNode; | |
this.currentTargets.push(target); | |
} | |
this.startEvent = e; | |
this.startPoint = Ext.util.Point.fromEvent(e); | |
this.lastMovePoint = null; | |
this.isClick = true; | |
this.touchMoveFired = false; | |
if (noset === undefined || noset === false) { | |
this.touchStartFired = true; | |
} | |
this.handleTargets(targets, e); | |
}, | |
onTouchMove: function (e) { | |
if (!Ext.is.Android) { | |
e.preventDefault(); | |
} | |
if (!this.startEvent) { | |
return; | |
} | |
if (Ext.is.Desktop) { | |
e.target = this.startEvent.target; | |
} | |
if (this.isFrozen) { | |
return; | |
} | |
var gestures = this.currentGestures, | |
gesture, touch = e.changedTouches ? e.changedTouches[0] : e; | |
this.lastMovePoint = Ext.util.Point.fromEvent(e); | |
if (Ext.supports.Touch && this.isClick && !this.lastMovePoint.isWithin(this.startPoint, this.clickMoveThreshold)) { | |
this.isClick = false; | |
} | |
for (var i = 0; i < gestures.length; i++) { | |
if (e.stopped) { | |
break; | |
} | |
gesture = gestures[i]; | |
if (gesture.listenForMove) { | |
gesture.onTouchMove(e, touch); | |
} | |
} | |
this.touchMoveFired = true; | |
}, | |
onTouchEnd: function (e, noset) { | |
if (Ext.is.Blackberry) { | |
//e.preventDefault(); | |
} | |
if (this.isFrozen) { | |
return; | |
} | |
var gestures = this.currentGestures.slice(0), | |
ln = gestures.length, | |
i, gesture, endPoint, needsAnotherMove = false, | |
touch = e.changedTouches ? e.changedTouches[0] : e; | |
if (this.startPoint) { | |
endPoint = Ext.util.Point.fromEvent(e); | |
if (!(this.lastMovePoint || this.startPoint)['equals'](endPoint)) { | |
needsAnotherMove = true; | |
} | |
} | |
for (i = 0; i < ln; i++) { | |
gesture = gestures[i]; | |
if (!e.stopped && gesture.listenForEnd) { | |
if (needsAnotherMove) { | |
gesture.onTouchMove(e, touch); | |
} | |
gesture.onTouchEnd(e, touch); | |
} | |
this.stopGesture(gesture); | |
} | |
if (Ext.supports.Touch && this.isClick) { | |
this.isClick = false; | |
this.getEventSimulator().fire('click', this.startEvent.target, touch); | |
} | |
if (noset === undefined || noset === false) { | |
this.touchEndFired = true; | |
} | |
if (this.touchMoveFired) { | |
this.touchEndFired = false; | |
} | |
this.lastMovePoint = null; | |
this.followTouches = []; | |
this.startedChangedTouch = false; | |
this.currentTargets = []; | |
this.startEvent = null; | |
this.startPoint = null; | |
}, | |
//no changes after here | |
handleTargets: function (targets, e) { | |
var ln = targets.length, | |
i; | |
this.startedChangedTouch = false; | |
this.startedTouches = Ext.supports.Touch ? e.touches : [e]; | |
for (i = 0; i < ln; i++) { | |
if (e.stopped) { | |
break; | |
} | |
this.handleTarget(targets[i], e, true); | |
} | |
for (i = ln - 1; i >= 0; i--) { | |
if (e.stopped) { | |
break; | |
} | |
this.handleTarget(targets[i], e, false); | |
} | |
if (this.startedChangedTouch) { | |
this.followTouches = this.followTouches.concat((Ext.supports.Touch && e.targetTouches) ? Ext.toArray(e.targetTouches) : [e]); | |
} | |
}, | |
handleTarget: function (target, e, capture) { | |
var gestures = Ext.Element.data(target, 'x-gestures') || [], | |
ln = gestures.length, | |
i, gesture; | |
for (i = 0; i < ln; i++) { | |
gesture = gestures[i]; | |
if (( !! gesture.capture === !! capture) && (this.followTouches.length < gesture.touches) && ((Ext.supports.Touch && e.targetTouches) ? (e.targetTouches.length === gesture.touches) : true)) { | |
this.startedChangedTouch = true; | |
this.startGesture(gesture); | |
if (gesture.listenForStart) { | |
gesture.onTouchStart(e, e.changedTouches ? e.changedTouches[0] : e); | |
} | |
if (e.stopped) { | |
break; | |
} | |
} | |
} | |
}, | |
startGesture: function (gesture) { | |
gesture.started = true; | |
this.currentGestures.push(gesture); | |
}, | |
stopGesture: function (gesture) { | |
gesture.started = false; | |
this.currentGestures.remove(gesture); | |
}, | |
addEventListener: function (target, eventName, listener, options) { | |
target = Ext.getDom(target); | |
options = options || {}; | |
var targets = this.targets, | |
name = this.getGestureName(eventName), | |
gestures = Ext.Element.data(target, 'x-gestures'), | |
gesture; | |
if (!gestures) { | |
gestures = []; | |
Ext.Element.data(target, 'x-gestures', gestures); | |
} | |
if (!name) { | |
throw new Error('Trying to subscribe to unknown event ' + eventName); | |
} | |
if (targets.indexOf(target) === -1) { | |
this.targets.push(target); | |
} | |
gesture = this.get(target.id + '-' + name); | |
if (!gesture) { | |
gesture = this.create(Ext.apply({}, options, { | |
target: target, | |
type: name | |
})); | |
gestures.push(gesture); | |
} | |
gesture.addListener(eventName, listener); | |
if (this.startedChangedTouch && this.currentTargets.contains(target) && !gesture.started && !options.subsequent) { | |
this.startGesture(gesture); | |
if (gesture.listenForStart) { | |
gesture.onTouchStart(this.startEvent, this.startedTouches[0]); | |
} | |
} | |
}, | |
removeEventListener: function (target, eventName, listener) { | |
target = Ext.getDom(target); | |
var name = this.getGestureName(eventName), | |
gestures = Ext.Element.data(target, 'x-gestures') || [], | |
gesture; | |
gesture = this.get(target.id + '-' + name); | |
if (gesture) { | |
gesture.removeListener(eventName, listener); | |
for (name in gesture.listeners) { | |
return; | |
} | |
gesture.destroy(); | |
gestures.remove(gesture); | |
Ext.Element.data(target, 'x-gestures', gestures); | |
} | |
}, | |
getGestureName: function (ename) { | |
return this.names && this.names[ename]; | |
}, | |
registerType: function (type, cls) { | |
var handles = cls.prototype.handles, | |
i, ln; | |
this.types[type] = cls; | |
cls[this.typeName] = type; | |
if (!handles) { | |
handles = cls.prototype.handles = [type]; | |
} | |
this.names = this.names || {}; | |
for (i = 0, ln = handles.length; i < ln; i++) { | |
this.names[handles[i]] = type; | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment