Как создать пользовательское событие для элемента DOM в Javascript

События Javascript являются важной частью экосистемы JS, поскольку они позволяют нам знать, когда происходит событие, без ущерба для производительности браузера.

Вы можете создавать свои собственные события, используя CustomEvent API, чтобы реагировать на эти события с помощью прослушивателя событий, как вы обычно делаете с существующими событиями.

Прослушать событие

Поскольку мы собираемся отправлять события с помощью CustomEvent API, нам нужно сначала прослушать его, иначе мы никогда не получим никакого результата.

Помните, что событие может отправляться только на элемент DOM (документ, ввод, кнопки, элементы div и т. Д.). В этом случае событие будет названо "OurSuperEvent" и он будет (на следующем этапе) отправлен на documentследовательно, слушатель будет добавлен для document тоже.

var element = document;
// or
// var element = document.getElementById("aRandomId");
element.addEventListener("OurSuperEvent", function (e) {
// This is the information that we receive from the CustomEvent
console.log("The custom data of the event is : ", e.detail);
// The event as itself (object with properties like {srcElement,isTrusted,target,defaultPrevent etc})
console.log("Event is : ",e);
}, false);

detail Свойство события, содержит информацию, которую вы отправляете при отправке события.

Замечания: как уже было сказано, прослушиватель событий был добавлен к элементу документа. Следовательно, событие также должно отправляться в элементе документа, иначе событие никогда не будет прослушиваться, поскольку это не тот элемент, который мы присвоили этому событию.

Отправка пользовательского события

Теперь, когда у нас есть слушатель, который сообщает нам, когда происходит наше событие, вам нужно научиться отправлять его.

В слушателе мы добавили слушателя к документу, поэтому наше событие (для прослушивания) будет также отправлено в документе.

var myData = {
id: 1,
name: "An imaginary name",
customProperty:"I need to know this string when the event is dispatched",
moreData: [1,2,4,5,6,7]
};
var element = document;
// or
// var element = document.getElementById("aRandomId");
// The custom event that receives as first parameter the name of the type of the dispatchedEvent
var event = new CustomEvent("OurSuperEvent", { detail: myData });
element.dispatchEvent(event);

Как видите, реализация пользовательского события очень проста, минималистична и чиста.

Однако (и всегда в мире javascript) некоторые браузеры (Internet Explorer) не реализуют одну и ту же инициализацию.

В то время как window.CustomEvent объект существует в браузере, он не может быть вызван как конструктор. Вместо new CustomEvent(...), вы должны использовать event = document.createEvent('CustomEvent') а потом event.initCustomEvent(...) как показано в следующем примере:

var myData = {
id: 1,
name: "An imaginary name",
customProperty:"I need to know this string when the event is dispatched",
moreData: [1,2,4,5,6,7]
};
var element = document;
// or
// var element = document.getElementById("aRandomId");
//Dispatch an event
var event = document.createEvent("CustomEvent");
event.initCustomEvent("OurSuperEvent", true, true, myData);
element.dispatchEvent(event);

Polyfill

Обратите внимание, что CustomEvent API не поддерживается в некоторых версиях старой версии WebView для Android на основе WebKit. К счастью, для этой функции есть полифилл.

Этот фрагмент охватывает событие IE6. Этот сценарий заполняет функции addEventListener, removeEventListener, dispatchEvent, CustomEvent и DOMContentLoaded. Это меньше, чем половина килобайта, минимизировано и сжато.

Вы можете посетить репозиторий здесь и увидеть исходный код , или получите полифилл прямо здесь:

// EventListener | CC0 | github.com/jonathantneal/EventListener
this.Element && Element.prototype.attachEvent && !Element.prototype.addEventListener && (function () {
function addToPrototype(name, method) {
Window.prototype[name] = HTMLDocument.prototype[name] = Element.prototype[name] = method;
}
// add
addToPrototype("addEventListener", function (type, listener) {
var
target = this,
listeners = target.addEventListener.listeners = target.addEventListener.listeners || {},
typeListeners = listeners[type] = listeners[type] || [];
// if no events exist, attach the listener
if (!typeListeners.length) {
target.attachEvent("on" + type, typeListeners.event = function (event) {
var documentElement = target.document && target.document.documentElement || target.documentElement || { scrollLeft: 0, scrollTop: 0 };
// polyfill w3c properties and methods
event.currentTarget = target;
event.pageX = event.clientX + documentElement.scrollLeft;
event.pageY = event.clientY + documentElement.scrollTop;
event.preventDefault = function () { event.returnValue = false };
event.relatedTarget = event.fromElement || null;
event.stopImmediatePropagation = function () { immediatePropagation = false; event.cancelBubble = true };
event.stopPropagation = function () { event.cancelBubble = true };
event.target = event.srcElement || target;
event.timeStamp = +new Date;
var plainEvt = {};
for (var i in event) {
plainEvt[i] = event[i];
}
// create an cached list of the master events list (to protect this loop from breaking when an event is removed)
for (var i = 0, typeListenersCache = [].concat(typeListeners), typeListenerCache, immediatePropagation = true; immediatePropagation && (typeListenerCache = typeListenersCache[i]); ++i) {
// check to see if the cached event still exists in the master events list
for (var ii = 0, typeListener; typeListener = typeListeners[ii]; ++ii) {
if (typeListener == typeListenerCache) {
typeListener.call(target, plainEvt);
break;
}
}
}
});
}
// add the event to the master event list
typeListeners.push(listener);
});
// remove
addToPrototype("removeEventListener", function (type, listener) {
var
target = this,
listeners = target.addEventListener.listeners = target.addEventListener.listeners || {},
typeListeners = listeners[type] = listeners[type] || [];
// remove the newest matching event from the master event list
for (var i = typeListeners.length - 1, typeListener; typeListener = typeListeners[i]; --i) {
if (typeListener == listener) {
typeListeners.splice(i, 1);
break;
}
}
// if no events exist, detach the listener
if (!typeListeners.length && typeListeners.event) {
target.detachEvent("on" + type, typeListeners.event);
}
});
// dispatch
addToPrototype("dispatchEvent", function (eventObject) {
var
target = this,
type = eventObject.type,
listeners = target.addEventListener.listeners = target.addEventListener.listeners || {},
typeListeners = listeners[type] = listeners[type] || [];
try {
return target.fireEvent("on" + type, eventObject);
} catch (error) {
if (typeListeners.event) {
typeListeners.event(eventObject);
}
return;
}
});
// CustomEvent
Object.defineProperty(Window.prototype, "CustomEvent", {
get: function () {
var self = this;
return function CustomEvent(type, eventInitDict) {
var event = self.document.createEventObject(), key;
event.type = type;
for (key in eventInitDict) {
if (key == 'cancelable'){
event.returnValue = !eventInitDict.cancelable;
} else if (key == 'bubbles'){
event.cancelBubble = !eventInitDict.bubbles;
} else if (key == 'detail'){
event.detail = eventInitDict.detail;
}
}
return event;
};
}
});
// ready
function ready(event) {
if (ready.interval && document.body) {
ready.interval = clearInterval(ready.interval);
document.dispatchEvent(new CustomEvent("DOMContentLoaded"));
}
}
ready.interval = setInterval(ready, 1);
window.addEventListener("load", ready);
})();
(!this.CustomEvent || typeof this.CustomEvent === "object") && (function() {
// CustomEvent for browsers which don't natively support the Constructor method
this.CustomEvent = function CustomEvent(type, eventInitDict) {
var event;
eventInitDict = eventInitDict || {bubbles: false, cancelable: false, detail: undefined};
try {
event = document.createEvent('CustomEvent');
event.initCustomEvent(type, eventInitDict.bubbles, eventInitDict.cancelable, eventInitDict.detail);
} catch (error) {
// for browsers which don't support CustomEvent at all, we use a regular event instead
event = document.createEvent('Event');
event.initEvent(type, eventInitDict.bubbles, eventInitDict.cancelable);
event.detail = eventInitDict.detail;
}
return event;
};
})();

Повеселись !

Ссылка на основную публикацию
Adblock
detector