%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/tjamichg/cursos.tjamich.gob.mx/plugin/mindmap/edit-mindmap/vendor/js/kampfer/
Upload File :
Create Path :
Current File : /home/tjamichg/cursos.tjamich.gob.mx/plugin/mindmap/edit-mindmap/vendor/js/kampfer/events.js

/*global kampfer*/
kampfer.require('data');

kampfer.provide('events');
kampfer.provide('events.Event');
kampfer.provide('events.Listener');


/*
 * 包裹浏览器event对象,提供统一的、跨浏览器的接口。
 * 新的对象将包含以下接口:
 * - type	{string}	事件种类
 * - target		{object}	触发事件的对象
 * - relatedTarget	{object}	鼠标事件mouseover和mouseout的修正
 * - currentTarget	{object}	
 * - stopPropagation	{function}	阻止冒泡
 * - preventDefault	{function}	阻止默认行为
 * - dispose	{function}
 * - which	{number}	
 * - pageX/pageY	{number}
 */
kampfer.events.Event = function(src, props) {
	var srcType = kampfer.type(src);

	if(srcType === 'object' && src.type) {
		this.src = src;
		this.type = src.type;
	} else if(srcType === 'string') {
		this.type = src;
	}

	if(kampfer.type(props) === 'object') {
		kampfer.extend(this, props);
	}

	this.isImmediatePropagationStopped = false;
	this.propagationStopped = false;
	this.isDefaultPrevented = false;

	this[kampfer.expando] = true;
};

kampfer.events.Event.prototype = {
	constructor : kampfer.events.Event,

	//停止冒泡
	stopPropagation : function() {
		//触发事件时,需要读取propagationStopped,判断冒泡是否取消。
		this.propagationStopped = true;

		var e = this.src;
		if(!e) {
			return;
		}

		if(e.stopPropagation) {
			e.stopPropagation();
		} else {
			e.cancelBubble = true;
		}
	},

	//立即停止冒泡
	stopImmediatePropagation : function() {
		this.isImmediatePropagationStopped = true;
		this.stopPropagation();
	},

	//阻止默认行为
	preventDefault : function() {
		this.isDefaultPrevented = true;
		
		var e = this.src;
		if(!e) {
			return;
		}
		
		if (e.preventDefault) {
			e.preventDefault();
		} else {
			e.returnValue = false;
		}
	},

	dispose : function() {
		delete this.src;
	}
};

//所有事件对象都拥有下面的属性
kampfer.events.Event.props = 'altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which'.split(' ');

//键盘事件对象拥有下面的属性
kampfer.events.Event.keyProps = 'char charCode key keyCode'.split(' ');

//鼠标事件对象拥有下面的属性
kampfer.events.Event.mouseProps = 'button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement'.split(' ');


/*
 * 修复event,处理兼容性问题
 * @param {object||string}event 
 * @return {object} 修复的event对象
 */
kampfer.events.fixEvent = function(event) {
	if( event[kampfer.expando] ) {
		return event;
	}

	var oriEvent = event;

	event = new kampfer.events.Event(oriEvent);

	kampfer.each(kampfer.events.Event.props, function(i, prop) {
		event[prop] = oriEvent[prop];
	});

	if(!event.target) {
		event.target = oriEvent.srcElement || document;
	}

	// Target should not be a text node (jQuery bugs#504, Safari)
	if(event.target.nodeType === 3) {
		event.target = event.target.parentNode;
	}

	event.currentTarget = null;

	// ie不支持metaKey, 设置值为false
	event.metaKey = !!event.metaKey;

	//修复鼠标事件之前必须保证event.target存在
	if( kampfer.events.isKeyEvent(event.type) ) {
		kampfer.events.fixKeyEvent(event, oriEvent);
	} else {
		kampfer.events.fixMouseEvent(event, oriEvent);
	}

	return event;
};

//判断事件是否为键盘事件
kampfer.events.isKeyEvent = function(type) {
	return /^key/.test(type);
};

//判断事件是否为鼠标事件
kampfer.events.isMouseEvent = function(type) {
	return /^(?:mouse|contextmenu)|click/.test(type);
};

//修复鼠标键盘对象
kampfer.events.fixKeyEvent = function(event, oriEvent) {
	kampfer.each(kampfer.events.Event.keyProps, function(i, prop) {
		event[prop] = oriEvent[prop];
	});

	// Add which for key events
	if ( event.which == null ) {
		event.which = oriEvent.charCode != null ? oriEvent.charCode : oriEvent.keyCode;
	}

	return event;
};

//修复鼠标事件对象
kampfer.events.fixMouseEvent = function(event, oriEvent) {
	kampfer.each(kampfer.events.Event.mouseProps, function(i, prop) {
		event[prop] = oriEvent[prop];
	});

	var eventDoc, doc, body,
		button = oriEvent.button,
		fromElement = oriEvent.fromElement;

	// Calculate pageX/Y if missing and clientX/Y available
	if ( event.pageX == null && oriEvent.clientX != null ) {
		eventDoc = event.target.ownerDocument || document;
		doc = eventDoc.documentElement;
		body = eventDoc.body;

		event.pageX = oriEvent.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - 
			( doc && doc.clientLeft || body && body.clientLeft || 0 );
		event.pageY = oriEvent.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - 
			( doc && doc.clientTop  || body && body.clientTop  || 0 );
	}

	// Add relatedTarget, if necessary
	if ( !event.relatedTarget && fromElement ) {
		event.relatedTarget = fromElement === event.target ? oriEvent.toElement : fromElement;
	}

	// Add which for click: 1 === left; 2 === middle; 3 === right
	// Note: button is not normalized, so don't use it
	if ( !event.which && button !== undefined ) {
		event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
	}

	return event;
};


/*
 * 生成handler的一个包裹对象,记录一些额外信息,并且生成一个唯一的key值
 * @param {function}handler
 * @param {string}type
 * @param {object}scope
 */
kampfer.events.Listener = function(listener, eventType, context) {
	this.listener = listener;
	this.eventType = eventType;
	this.context = context;
	this.key = kampfer.events.Listener.key++;
};

//销毁对象中指向其他对象的引用
kampfer.events.Listener.prototype.dispose = function() {
	this.listener = null;
	this.context = null;
};

kampfer.events.Listener.key = 0;


/*
 * 添加事件
 * @param {object}elem
 * @param {string||array}eventType
 * @param {function}listener
 * @param {object}context
 */
kampfer.events.addListener = function(elem, eventType, listener, context) {
	// filter commet and text node
	// nor undefined eventType or listener
	if( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !eventType ||
		kampfer.type(listener) !== 'function' ) {
		return;
	}

	var type = kampfer.type(eventType);

	if( type === 'array' ) {
		for(var i = 0, e; e = eventType[i]; i++) {
			kampfer.events.addListener(elem, e, listener, context);
		}
		return;
	}

	if( type === 'string') {
		var listenerObj = new kampfer.events.Listener(listener, eventType, context || elem);

		var events = kampfer.data.getDataInternal(elem, 'events');
		if(!events) {
			events = {};
			kampfer.data.setDataInternal(elem, 'events', events);
		}

		if(!events.proxy) {
			events.proxy = function(e) {
				if(kampfer.events.triggered !== e.type) {
					return kampfer.events.dispatchEvent.apply(events.proxy.elem, arguments);
				}
			};
			events.proxy.elem = elem;
		}

		if(!events.listeners) {
			events.listeners = {};
		}

		if(!events.listeners[eventType]) {
			events.listeners[eventType] = [];

			//events.listeners[eventType]不存在说明没有绑定过此事件
			if(elem.addEventListener) {
				elem.addEventListener(eventType, events.proxy, false);
			} else if(elem.attachEvent) {
				elem.attachEvent('on' + eventType, events.proxy);
			}
		}

		events.listeners[eventType].push(listenerObj);
	}

	// fix ie memory leak
	elem = null;
};


/*
 * 删除事件。此方法用于删除绑定在某类事件下的全部操作。
 * @param {object}elem
 * @param {string}eventType
 */ 
kampfer.events.removeListener = function(elem, eventType, listener) {
	var events = kampfer.data.getDataInternal(elem, 'events');

	if( !events || !events.listeners ) {
		return;
	}

	var type = kampfer.type(eventType);

	if(type === 'array') {
		for(var i = 0; type = eventType[0]; i++) {
			kampfer.events.removeListener(elem, type, listener);
		}
		return;
	}

	if(type === 'undefined') {
		for(type in events.listeners) {
			kampfer.events.removeListener(elem, type, listener);
		}
		return;
	}

	if(type === 'string') {
		for(var i = 0, l; l = events.listeners[eventType][i]; i++) {
			if( !listener || (l.eventType === eventType && l.listener === listener) ) {
				// 注意splice会改变数组长度以及元素对应的下标
				events.listeners[eventType].splice(i--, 1);
			}
		}

		if(!events.listeners[eventType].length) {
			if(elem.removeEventListener) {
				elem.removeEventListener(eventType, events.proxy, false);
			} else if(elem.detachEvent) {
				elem.detachEvent('on' + eventType, events.proxy);
			}
			delete events.listeners[eventType];
		}

		if( kampfer.isEmptyObject(events.listeners) ) {
			delete events.listeners;
			delete events.proxy;
			kampfer.data.removeDataInternal(elem, 'events');
		}
	}

};


/*
 * 触发对象的指定事件
 * @param {object}elem
 * @param {string||array}eventType
 */
kampfer.events.dispatch = function(elem, event) {
	if(elem.nodeType === 3 || elem.nodeType === 8 || !event) {
		return;
	}

	var eventType = event.type || event,
		args = Array.prototype.slice.call(arguments),
		bubblePath = [],
		onType = 'on' + eventType;

	if(typeof event === 'object') {
		if( !event[kampfer.expando] ) {
			event = new kampfer.events.Event(eventType, event);
		}
	} else {
		event = new kampfer.events.Event(event);
	}

	args = Array.prototype.slice.call(arguments, 2);
	args.unshift(event);

	// event.target始终指向事件的起点对象
	if(!event.target) {
		event.target = elem;
	}

	//建立冒泡的dom树路径
	for(var cur = elem; cur; cur = cur.parentNode) {
		bubblePath.push(cur);
	}
	//W3C标准中事件冒泡的终点时document,而jQuery.trigger会冒泡到window
	//这里有必要跟jQuery一样吗????
	//冒泡的最后一站始终是window对象
	if( cur === (elem.ownerDocument || document) ) {
		bubblePath.push(elem.defaultView || elem.parentWindow || window);
	}

	for(i = 0; cur = !event.propagationStopped && bubblePath[i]; i++) {

		var eventsObj = kampfer.data.getDataInternal(cur, 'events');

		if( !eventsObj || !eventsObj.listeners[eventType] ) {
			continue;
		}

		// 冒泡的每一阶段currentTarget都不同
		event.currentTarget = cur;

		// 执行kampfer绑定的事件处理函数
		var proxy = eventsObj.proxy;
		proxy.apply(cur, args);

		// 执行使用行内方式绑定的事件处理函数
		proxy = cur[onType];
		if(proxy && proxy.apply(cur, args) === false) {
			event.preventDefault();
			event.stopPropagation();
		}

	}

	// 触发浏览器default action
	if(!event.isDefaultPrevented && !kampfer.isWindow(elem) && elem[eventType]) {
		var old = elem[onType];
		if(old) {
			elem[onType] = null;
		}

		kampfer.events.triggered = eventType;
		try {
			elem[eventType]();
		} catch(e) {}
		delete kampfer.events.triggered;

		if(old) {
			elem[onType] = old;
		}
	}

	return event.result;
};


/**
 * 正确的将一个事件派发给所有相关对象
 */
kampfer.events.dispatchEvent = function(event) {
	event = kampfer.events.fixEvent(event);

	// ie6/7/8不支持event.currentTarget 于是无法使用解决this的问题
	var eventsObj = kampfer.data.getDataInternal(this, 'events'),
		listeners = eventsObj && eventsObj.listeners[event.type],
		args = Array.prototype.slice.call(arguments);

	if(!listeners) {
		return;
	}

	// fix currentTarget in ie6/7/8
	event.currentTarget = this;

	for(var i = 0, l; l = listeners[i]; i++) {
		event.result = l.listener.apply(l.context, args);
		if(event.result === false) {
			event.preventDefault();
			event.stopPropagation();
		}
		if(event.isImmediatePropagationStopped) {
			break;
		}
	}

	// for beforeunload on firefox
	if(event.result !== undefined && event.src) {
		event.src.returnValue = event.result;
	}

	return event.result;
};

Zerion Mini Shell 1.0