can
Version:
MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.
135 lines (110 loc) • 4.14 kB
JavaScript
/*
---
name: Event
description: Contains the Event Type, to make the event object cross-browser.
license: MIT-style license.
requires: [Window, Document, Array, Function, String, Object]
provides: Event
...
*/
(function(){
var _keys = {};
var normalizeWheelSpeed = function(event){
var normalized;
if (event.wheelDelta){
normalized = event.wheelDelta % 120 == 0 ? event.wheelDelta / 120 : event.wheelDelta / 12;
} else {
var rawAmount = event.deltaY || event.detail || 0;
normalized = -(rawAmount % 3 == 0 ? rawAmount / 3 : rawAmount * 10);
}
return normalized;
}
var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){
if (!win) win = window;
event = event || win.event;
if (event.$extended) return event;
this.event = event;
this.$extended = true;
this.shift = event.shiftKey;
this.control = event.ctrlKey;
this.alt = event.altKey;
this.meta = event.metaKey;
var type = this.type = event.type;
var target = event.target || event.srcElement;
while (target && target.nodeType == 3) target = target.parentNode;
this.target = document.id(target);
if (type.indexOf('key') == 0){
var code = this.code = (event.which || event.keyCode);
if (!this.shift || type != 'keypress') this.key = _keys[code]/*<1.3compat>*/ || Object.keyOf(Event.Keys, code)/*</1.3compat>*/;
if (type == 'keydown' || type == 'keyup'){
if (code > 111 && code < 124) this.key = 'f' + (code - 111);
else if (code > 95 && code < 106) this.key = code - 96;
}
if (this.key == null) this.key = String.fromCharCode(code).toLowerCase();
} else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'wheel' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){
var doc = win.document;
doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
this.page = {
x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
};
this.client = {
x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
};
if (type == 'DOMMouseScroll' || type == 'wheel' || type == 'mousewheel') this.wheel = normalizeWheelSpeed(event);
this.rightClick = (event.which == 3 || event.button == 2);
if (type == 'mouseover' || type == 'mouseout' || type == 'mouseenter' || type == 'mouseleave'){
var overTarget = type == 'mouseover' || type == 'mouseenter';
var related = event.relatedTarget || event[(overTarget ? 'from' : 'to') + 'Element'];
while (related && related.nodeType == 3) related = related.parentNode;
this.relatedTarget = document.id(related);
}
} else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){
this.rotation = event.rotation;
this.scale = event.scale;
this.targetTouches = event.targetTouches;
this.changedTouches = event.changedTouches;
var touches = this.touches = event.touches;
if (touches && touches[0]){
var touch = touches[0];
this.page = {x: touch.pageX, y: touch.pageY};
this.client = {x: touch.clientX, y: touch.clientY};
}
}
if (!this.client) this.client = {};
if (!this.page) this.page = {};
});
DOMEvent.implement({
stop: function(){
return this.preventDefault().stopPropagation();
},
stopPropagation: function(){
if (this.event.stopPropagation) this.event.stopPropagation();
else this.event.cancelBubble = true;
return this;
},
preventDefault: function(){
if (this.event.preventDefault) this.event.preventDefault();
else this.event.returnValue = false;
return this;
}
});
DOMEvent.defineKey = function(code, key){
_keys[code] = key;
return this;
};
DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true);
DOMEvent.defineKeys({
'38': 'up', '40': 'down', '37': 'left', '39': 'right',
'27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab',
'46': 'delete', '13': 'enter'
});
})();
/*<1.3compat>*/
var Event = DOMEvent;
Event.Keys = {};
/*</1.3compat>*/
/*<1.2compat>*/
Event.Keys = new Hash(Event.Keys);
/*</1.2compat>*/