/src/event/object.js
https://github.com/timeflows/kissy · JavaScript · 182 lines · 101 code · 31 blank · 50 comment · 41 complexity · 23b16c93843824da4746d4f0d066a684 MD5 · raw file
- /**
- * @module EventObject
- * @author lifesinger@gmail.com
- */
- KISSY.add('event/object', function(S, undefined) {
- var doc = document,
- props = ('altKey attrChange attrName bubbles button cancelable ' +
- 'charCode clientX clientY ctrlKey currentTarget data detail ' +
- 'eventPhase fromElement handler keyCode layerX layerY metaKey ' +
- 'newValue offsetX offsetY originalTarget pageX pageY prevValue ' +
- 'relatedNode relatedTarget screenX screenY shiftKey srcElement ' +
- 'target toElement view wheelDelta which').split(' ');
- /**
- * KISSY's 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.
- */
- function EventObject(currentTarget, domEvent, type) {
- var self = this;
- self.currentTarget = currentTarget;
- self.originalEvent = domEvent || { };
- if (domEvent) { // html element
- self.type = domEvent.type;
- self._fix();
- }
- else { // custom
- self.type = type;
- self.target = currentTarget;
- }
- // bug fix: in _fix() method, ie maybe reset currentTarget to undefined.
- self.currentTarget = currentTarget;
- self.fixed = true;
- }
- S.augment(EventObject, {
- _fix: function() {
- var self = this,
- originalEvent = self.originalEvent,
- l = props.length, prop,
- ct = self.currentTarget,
- ownerDoc = (ct.nodeType === 9) ? ct : (ct.ownerDocument || doc); // support iframe
- // 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 = self.srcElement || doc; // srcElement might not be defined either
- }
- // check if target is a textnode (safari)
- if (self.target.nodeType === 3) {
- self.target = self.target.parentNode;
- }
- // add relatedTarget, if necessary
- if (!self.relatedTarget && self.fromElement) {
- self.relatedTarget = (self.fromElement === self.target) ? self.toElement : self.fromElement;
- }
- // calculate pageX/Y if missing and clientX/Y available
- if (self.pageX === undefined && self.clientX !== undefined) {
- var docEl = ownerDoc.documentElement, bd = ownerDoc.body;
- self.pageX = self.clientX + (docEl && docEl.scrollLeft || bd && bd.scrollLeft || 0) - (docEl && docEl.clientLeft || bd && bd.clientLeft || 0);
- self.pageY = self.clientY + (docEl && docEl.scrollTop || bd && bd.scrollTop || 0) - (docEl && docEl.clientTop || bd && bd.clientTop || 0);
- }
- // add which for key events
- if (self.which === undefined) {
- self.which = (self.charCode === undefined) ? self.keyCode : self.charCode;
- }
- // add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
- if (self.metaKey === undefined) {
- self.metaKey = self.ctrlKey;
- }
- // add which for click: 1 === left; 2 === middle; 3 === right
- // Note: button is not normalized, so don't use it
- if (!self.which && self.button !== undefined) {
- self.which = (self.button & 1 ? 1 : (self.button & 2 ? 3 : ( self.button & 4 ? 2 : 0)));
- }
- },
- /**
- * Prevents the event's default behavior
- */
- preventDefault: function() {
- var e = this.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;
- }
- this.isDefaultPrevented = true;
- },
- /**
- * Stops the propagation to the next bubble target
- */
- stopPropagation: function() {
- var e = this.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;
- }
- this.isPropagationStopped = true;
- },
- /**
- * Stops the propagation to the next bubble target and
- * prevents any additional listeners from being exectued
- * on the current target.
- */
- stopImmediatePropagation: function() {
- var e = this.originalEvent;
- if (e.stopImmediatePropagation) {
- e.stopImmediatePropagation();
- } else {
- this.stopPropagation();
- }
- this.isImmediatePropagationStopped = true;
- },
- /**
- * Stops the event propagation and prevents the default
- * event behavior.
- * @param immediate {boolean} if true additional listeners
- * on the current target will not be executed
- */
- halt: function(immediate) {
- if (immediate) {
- this.stopImmediatePropagation();
- } else {
- this.stopPropagation();
- }
- this.preventDefault();
- }
- });
- if (1 > 2) {
- alert(S.cancelBubble);
- }
- return EventObject;
- });
- /**
- * NOTES:
- *
- * 2010.04
- * - http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
- *
- * TODO:
- * - pageX, clientX, scrollLeft, clientLeft 的详细测试
- */