/**
* @file src/js/event-target.js
*/
import * as Events from './utils/events.js';
從“全局/窗口”導入窗口;
/**
* `EventTarget` 是一個可以與 DOM `EventTarget` 具有相同 API 的類。它
* 添加了環繞冗長函數的速記函數。例如:
* `on` 函數是 `addEventListener` 的包裝器。
*
* @see [EventTarget 規範]{@link https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget}
* @class 事件目標
*/
const EventTarget = function() {};
/**
* 自定義 DOM 事件。
*
* @typedef {Object} EventTarget~Event
* @see [屬性]{@link https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent}
*/
/**
* 所有事件偵聽器都應遵循以下格式。
*
* @callback EventTarget~EventListener
* @this {EventTarget}
*
* @param {EventTarget~Event} 事件
* 觸發此功能的事件
*
* @param {對象} [哈希]
* 事件期間發送的數據哈希
*/
/**
* 包含事件名稱作為鍵和布爾值作為值的對象。
*
* > 注意:如果在此處將事件名稱設置為真值 {@link EventTarget#trigger}
* 將具有額外的功能。有關詳細信息,請參閱該函數。
*
* @property EventTarget.prototype.allowedEvents_
* @私人的
*/
EventTarget.prototype.allowedEvents_ = {};
/**
* 向 `EventTarget` 的實例添加一個 `event listener`。一個“事件監聽器”是
* 當具有特定名稱的事件被觸發時將被調用的函數。
*
* @param {string|string[]} 類型
* 事件名稱或事件名稱數組。
*
* @param {EventTarget~EventListener} fn
* 使用 `EventTarget` 調用的函數
*/
EventTarget.prototype.on = function(type, fn) {
// 在調用 Events.on 之前移除 addEventListener 別名
// 這樣我們就不會陷入無限循環
const ael = this.addEventListener;
this.addEventListener = () => {};
事件.on(這個,類型,fn);
this.addEventListener = ael;
};
/**
* {@link EventTarget#on} 的別名。允許“EventTarget”模仿
* 標準的 DOM API。
*
* @功能
* @see {@link EventTarget#on}
*/
EventTarget.prototype.addEventListener = EventTarget.prototype.on;
/**
* 從 `EventTarget` 的實例中刪除特定事件的 `event listener`。
* 這使得 `event listener` 將不再被調用
* 命名事件發生。
*
* @param {string|string[]} 類型
* 事件名稱或事件名稱數組。
*
* @param {EventTarget~EventListener} fn
* 要刪除的函數。
*/
EventTarget.prototype.off = function(type, fn) {
Events.off(這個,類型,fn);
};
/**
* {@link EventTarget#off} 的別名。允許“EventTarget”模仿
* 標準的 DOM API。
*
* @功能
* @see {@link EventTarget#off}
*/
EventTarget.prototype.removeEventListener = EventTarget.prototype.off;
/**
* 此函數將添加一個僅觸發一次的“事件偵聽器”。之後
* 第一次觸發它將被刪除。這就像添加一個“事件監聽器”
* 與 {@link EventTarget#on} 一起調用 {@link EventTarget#off}。
*
* @param {string|string[]} 類型
* 事件名稱或事件名稱數組。
*
* @param {EventTarget~EventListener} fn
* 為每個事件名稱調用一次的函數。
*/
EventTarget.prototype.one = function(type, fn) {
// 移除 addEventListener 別名 Events.on
// 這樣我們就不會陷入無限循環
const ael = this.addEventListener;
this.addEventListener = () => {};
Events.one(這個,類型,fn);
this.addEventListener = ael;
};
EventTarget.prototype.any = function(type, fn) {
// 移除 addEventListener 別名 Events.on
// 這樣我們就不會陷入無限循環
const ael = this.addEventListener;
this.addEventListener = () => {};
Events.any(這個,類型,fn);
this.addEventListener = ael;
};
/**
* 此函數導致事件發生。這將導致任何“事件監聽器”
* 正在等待那個事件,被調用。如果沒有“事件監聽器”
* 對於一個事件,那麼什麼都不會發生。
*
* 如果正在觸發的“事件”的名稱在“EventTarget.allowedEvents_”中。
* 觸發器還會調用 `on` + `uppercaseEventName` 函數。
*
* 例子:
* 'click' 在 `EventTarget.allowedEvents_` 中,因此,觸發器將嘗試調用
* `onClick` 如果存在。
*
* @param {string|EventTarget~Event|Object} 事件
* 事件名稱、“Event”或鍵類型設置為的對象
* 事件名稱。
*/
EventTarget.prototype.trigger = 函數(事件){
const type = event.type ||事件;
//棄用
// 在未來的版本中,我們應該默認目標為 `this`
// 類似於我們將目標默認為 `elem` 的方式
// `Events.trigger`。現在默認的“目標”將是
// `document` 由於調用了 `Event.fixEvent`。
如果(事件類型==='字符串'){
事件={類型};
}
event = Events.fixEvent(事件);
如果(this.allowedEvents_[type] && this['on' + type]){
這個['on' + type](事件);
}
Events.trigger(這個,事件);
};
/**
* {@link EventTarget#trigger} 的別名。允許“EventTarget”模仿
* 標準的 DOM API。
*
* @功能
* @see {@link EventTarget#trigger}
*/
EventTarget.prototype.dispatchEvent = EventTarget.prototype.trigger;
讓EVENT_MAP;
EventTarget.prototype.queueTrigger = 函數(事件){
// 只有在使用時才設置 EVENT_MAP
如果(!EVENT_MAP){
EVENT_MAP = 新地圖();
}
const type = event.type ||事件;
讓 map = EVENT_MAP.get(this);
如果(!地圖){
地圖=新地圖();
EVENT_MAP.set(this, map);
}
const oldTimeout = map.get(type);
地圖.刪除(類型);
window.clearTimeout(oldTimeout);
const timeout = window.setTimeout(() => {
地圖.刪除(類型);
// 如果我們清除了當前目標的所有超時,則刪除它的地圖
如果(地圖大小=== 0){
地圖=空;
EVENT_MAP.delete(這個);
}
這個。觸發器(事件);
}, 0);
map.set(類型,超時);
};
導出默認事件目標;