/**
* @ignore
* event object for dom
* @author yiminghe@gmail.com
*/
KISSY.add('event/dom/base/object', function (S, BaseEvent, undefined) {
var DOCUMENT = S.Env.host.document,
TRUE = true,
FALSE = false,
commonProps = [
'altKey', 'bubbles', 'cancelable',
'ctrlKey', 'currentTarget', 'eventPhase',
'metaKey', 'shiftKey', 'target',
'timeStamp', 'view', 'type'
],
eventNormalizers = [
{
reg: /^key/,
props: ['char', 'charCode', 'key', 'keyCode', 'which'],
fix: function (event, originalEvent) {
if (event.which == null) {
event.which = originalEvent.charCode != null ? originalEvent.charCode : originalEvent.keyCode;
}
// add metaKey to non-Mac browsers (use ctrl for PC 's and Meta for Macs)
if (event.metaKey === undefined) {
event.metaKey = event.ctrlKey;
}
}
},
{
reg: /^touch/,
props: ['touches', 'changedTouches', 'targetTouches']
},
{
reg: /^gesturechange$/i,
props: ['rotation', 'scale']
},
{
reg: /^(mousewheel|DOMMouseScroll)$/,
props: [],
fix: function (event, originalEvent) {
var deltaX,
deltaY,
delta,
wheelDelta = originalEvent.wheelDelta,
axis = originalEvent.axis,
wheelDeltaY = originalEvent['wheelDeltaY'],
wheelDeltaX = originalEvent['wheelDeltaX'],
detail = originalEvent.detail;
// ie/webkit
if (wheelDelta) {
delta = wheelDelta / 120;
}
// gecko
if (detail) {
// press control e.detail == 1 else e.detail == 3
delta = -(detail % 3 == 0 ? detail / 3 : detail);
}
// Gecko
if (axis !== undefined) {
if (axis === event['HORIZONTAL_AXIS']) {
deltaY = 0;
deltaX = -1 * delta;
} else if (axis === event['VERTICAL_AXIS']) {
deltaX = 0;
deltaY = delta;
}
}
// Webkit
if (wheelDeltaY !== undefined) {
deltaY = wheelDeltaY / 120;
}
if (wheelDeltaX !== undefined) {
deltaX = -1 * wheelDeltaX / 120;
}
// 默认 deltaY (ie)
if (!deltaX && !deltaY) {
deltaY = delta;
}
if (deltaX !== undefined) {
/**
* deltaX of mousewheel event
* @property deltaX
* @member KISSY.Event.DomEvent.Object
*/
event.deltaX = deltaX;
}
if (deltaY !== undefined) {
/**
* deltaY of mousewheel event
* @property deltaY
* @member KISSY.Event.DomEvent.Object
*/
event.deltaY = deltaY;
}
if (delta !== undefined) {
/**
* delta of mousewheel event
* @property delta
* @member KISSY.Event.DomEvent.Object
*/
event.delta = delta;
}
}
},
{
reg: /^mouse|contextmenu|click|mspointer|(^DOMMouseScroll$)/i,
props: [
'buttons', 'clientX', 'clientY', 'button',
'offsetX', 'relatedTarget', 'which',
'fromElement', 'toElement', 'offsetY',
'pageX', 'pageY', 'screenX', 'screenY'
],
fix: function (event, originalEvent) {
var eventDoc, doc, body,
target = event.target,
button = originalEvent.button;
// Calculate pageX/Y if missing and clientX/Y available
if (event.pageX == null && originalEvent.clientX != null) {
eventDoc = target.ownerDocument || DOCUMENT;
doc = eventDoc.documentElement;
body = eventDoc.body;
event.pageX = originalEvent.clientX +
( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
( doc && doc.clientLeft || body && body.clientLeft || 0 );
event.pageY = originalEvent.clientY +
( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
( doc && doc.clientTop || body && body.clientTop || 0 );
}
// which for click: 1 === left; 2 === middle; 3 === right
// do not use button
if (!event.which && button !== undefined) {
event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
}
// add relatedTarget, if necessary
if (!event.relatedTarget && event.fromElement) {
event.relatedTarget = (event.fromElement === target) ? event.toElement : event.fromElement;
}
return event;
}
}
];
function retTrue() {
return TRUE;
}
function retFalse() {
return FALSE;
}
/**
* Do not new by yourself.
*
* KISSY 's dom event system normalizes the event object according to
* W3C standards.
*
* The event object is guaranteed to be passed to
* the event handler.
*
* Most properties from the original event are
* copied over and normalized to the new event object
* according to [W3C standards](http://www.w3.org/TR/dom/#event).
*
* @class KISSY.Event.DomEvent.Object
* @extends KISSY.Event.Object
* @private
* @param originalEvent native dom event
*/
function DomEventObject(originalEvent) {
var self = this,
type = originalEvent.type;
/**
* altKey
* @property altKey
*/
/**
* attrChange
* @property attrChange
*/
/**
* attrName
* @property attrName
*/
/**
* bubbles
* @property bubbles
*/
/**
* button
* @property button
*/
/**
* cancelable
* @property cancelable
*/
/**
* charCode
* @property charCode
*/
/**
* clientX
* @property clientX
*/
/**
* clientY
* @property clientY
*/
/**
* ctrlKey
* @property ctrlKey
*/
/**
* data
* @property data
*/
/**
* detail
* @property detail
*/
/**
* eventPhase
* @property eventPhase
*/
/**
* fromElement
* @property fromElement
*/
/**
* handler
* @property handler
*/
/**
* keyCode
* @property keyCode
*/
/**
* metaKey
* @property metaKey
*/
/**
* newValue
* @property newValue
*/
/**
* offsetX
* @property offsetX
*/
/**
* offsetY
* @property offsetY
*/
/**
* pageX
* @property pageX
*/
/**
* pageY
* @property pageY
*/
/**
* prevValue
* @property prevValue
*/
/**
* relatedNode
* @property relatedNode
*/
/**
* relatedTarget
* @property relatedTarget
*/
/**
* screenX
* @property screenX
*/
/**
* screenY
* @property screenY
*/
/**
* shiftKey
* @property shiftKey
*/
/**
* srcElement
* @property srcElement
*/
/**
* toElement
* @property toElement
*/
/**
* view
* @property view
*/
/**
* wheelDelta
* @property wheelDelta
*/
/**
* which
* @property which
*/
/**
* changedTouches
* @property changedTouches
*/
/**
* touches
* @property touches
*/
/**
* targetTouches
* @property targetTouches
*/
/**
* rotation
* @property rotation
*/
/**
* scale
* @property scale
*/
/**
* source html node of current event
* @property target
* @type {HTMLElement}
*/
/**
* current htm node which processes current event
* @property currentTarget
* @type {HTMLElement}
*/
DomEventObject.superclass.constructor.call(self);
self.originalEvent = originalEvent;
// in case dom event has been mark as default prevented by lower dom node
var isDefaultPrevented = retFalse;
if ('defaultPrevented' in originalEvent) {
isDefaultPrevented = originalEvent['defaultPrevented'] ? retTrue : retFalse;
} else if ('getPreventDefault' in originalEvent) {
// https://bugzilla.mozilla.org/show_bug.cgi?id=691151
isDefaultPrevented = originalEvent['getPreventDefault']() ? retTrue : retFalse;
} else if ('returnValue' in originalEvent) {
isDefaultPrevented = originalEvent.returnValue === FALSE ? retTrue : retFalse;
}
self.isDefaultPrevented = isDefaultPrevented;
var fixFns = [],
fixFn,
l,
prop,
props = commonProps.concat();
S.each(eventNormalizers, function (normalizer) {
if (type.match(normalizer.reg)) {
props = props.concat(normalizer.props);
if (normalizer.fix)
fixFns.push(normalizer.fix);
}
return undefined;
});
l = props.length;
// clone properties of the original event object
while (l) {
prop = props[--l];
self[prop] = originalEvent[prop];
}
// fix target property, if necessary
if (!self.target) {
self.target = originalEvent.srcElement || DOCUMENT; // srcElement might not be defined either
}
// check if target is a text node (safari)
if (self.target.nodeType === 3) {
self.target = self.target.parentNode;
}
l = fixFns.length;
while (l) {
fixFn = fixFns[--l];
fixFn(self, originalEvent);
}
}
S.extend(DomEventObject, BaseEvent.Object, {
constructor: DomEventObject,
preventDefault: function () {
var self = this,
e = self.originalEvent;
// if preventDefault exists run it on the original event
if (e.preventDefault) {
e.preventDefault();
}
// otherwise set the returnValue property of the original event to FALSE (IE)
else {
e.returnValue = FALSE;
}
DomEventObject.superclass.preventDefault.call(self);
},
stopPropagation: function () {
var self = this,
e = self.originalEvent;
// if stopPropagation exists run it on the original event
if (e.stopPropagation) {
e.stopPropagation();
}
// otherwise set the cancelBubble property of the original event to TRUE (IE)
else {
e.cancelBubble = TRUE;
}
DomEventObject.superclass.stopPropagation.call(self);
}
});
return DomEventObject;
}, {
requires: ['event/base']
});
/*
2012-10-30
- consider touch properties
2012-10-24
- merge with mousewheel: not perfect in osx : accelerated scroll
2010.04
- http://www.w3.org/TR/2003/WD-Dom-Level-3-Events-20030331/ecma-script-binding.html
- refer:
https://github.com/brandonaaron/jquery-mousewheel/blob/master/jquery.mousewheel.js
http://www.planabc.net/2010/08/12/mousewheel_event_in_javascript/
http://www.switchonthecode.com/tutorials/javascript-tutorial-the-scroll-wheel
http://stackoverflow.com/questions/5527601/normalizing-mousewheel-speed-across-browsers/5542105#5542105
http://www.javascriptkit.com/javatutors/onmousewheel.shtml
http://www.adomas.org/javascript-mouse-wheel/
http://plugins.jquery.com/project/mousewheel
http://www.cnblogs.com/aiyuchen/archive/2011/04/19/2020843.html
http://www.w3.org/TR/Dom-Level-3-Events/#events-mousewheelevents
*/