DOM 이벤트를 복제하거나 다시 배포하는 방법은 무엇입니까?
DOM 이벤트 만 복제하거나 다시 배포하는 간단하고 추상적 인 방법을 찾고 있습니다. DOM 노드 복제에 관심이 없습니다.
나는 약간 실험하고 DOM 이벤트 사양을 읽었 으며 명확한 답을 찾지 못했습니다.
이상적으로는 다음과 같이 간단한 것을 찾고 있습니다.
handler = function(e){
document.getElementById("decoy").dispatchEvent(e)
}
document.getElementById("source").addEventListener("click", handler)
물론이 코드 예제는 작동하지 않습니다. 이벤트가 현재 전달되고 있음을 나타내는 DOM 예외가 있습니다.
을 사용하여 수동으로 새 이벤트를 만들고 document.createEvent()
초기화하고 발송하는 것을 피하고 싶습니다 .
이 사용 사례에 대한 간단한 해결책이 있습니까?
나는 질문이 오래되었고 OP는 접근 방식을 생성 / 초기화하는 것을 피하고 싶었지만 이벤트를 복제하는 비교적 간단한 방법이 있습니다.
new_event = new MouseEvent(old_event.type, old_event)
마우스 이벤트 이상의 것을 원한다면 다음과 같이 할 수 있습니다.
new_event = new old_event.constructor(old_event.type, old_event)
그리고 원래의 맥락에서 :
handler = function(e) {
new_e = new e.constructor(e.type, e);
document.getElementById("decoy").dispatchEvent(new_e);
}
document.getElementById("source").addEventListener("click", handler);
(jQuery 사용자의 경우 : e.originalEvent.constructor
대신 을 사용해야 할 수 있습니다. e.constructor
)
수정 Internet Explorer
Alexis는 좋은 솔루션을 게시했지만 그의 솔루션은 Internet Explorer에서 작동하지 않습니다. 아래 해결책이 있습니다. 안타깝게도 Internet Explorer의 이벤트 생성자만큼 일관된 시스템이 없으므로 아래의 코드 부풀림이 필요합니다.
var allModifiers = ["Alt","AltGraph","CapsLock","Control",
"Meta","NumLock","Scroll","Shift","Win"];
function redispatchEvent(original, newTargetId) {
if (typeof Event === "function") {
var eventCopy = new original.constructor(original.type, original);
} else {
// Internet Explorer
var eventType = original.constructor.name;
var eventCopy = document.createEvent(eventType);
if (original.getModifierState)
var modifiersList = allModifiers.filter(
original.getModifierState,
original
).join(" ");
if (eventType === "MouseEvent") original.initMouseEvent(
original.type, original.bubbles, original.cancelable,
original.view, original.detail, original.screenX, original.screenY,
original.clientX, original.clientY, original.ctrlKey,
original.altKey, original.shiftKey, original.metaKey,
original.button, original.relatedTarget
);
if (eventType === "DragEvent") original.initDragEvent(
original.type, original.bubbles, original.cancelable,
original.view, original.detail, original.screenX, original.screenY,
original.clientX, original.clientY, original.ctrlKey,
original.altKey, original.shiftKey, original.metaKey,
original.button, original.relatedTarget, original.dataTransfer
);
if (eventType === "WheelEvent") original.initWheelEvent(
original.detail, original.screenX, original.screenY,
original.clientX, original.clientY, original.button,
original.relatedTarget, modifiersList,
original.deltaX, original.deltaY, original.deltaZ, original.deltaMode
);
if (eventType === "PointerEvent") original.initPointerEvent(
original.type, original.bubbles, original.cancelable,
original.view, original.detail, original.screenX, original.screenY,
original.clientX, original.clientY, original.ctrlKey,
original.altKey, original.shiftKey, original.metaKey,
original.button, original.relatedTarget,
original.offsetX, original.offsetY, original.width, original.height,
original.pressure, original.rotation,
original.tiltX, original.tiltY,
original.pointerId, original.pointerType,
original.timeStamp, original.isPrimary
);
if (eventType === "TouchEvent") original.initTouchEvent(
original.type, original.bubbles, original.cancelable,
original.view, original.detail, original.screenX, original.screenY,
original.clientX, original.clientY, original.ctrlKey,
original.altKey, original.shiftKey, original.metaKey,
original.touches, original.targetTouches, original.changedTouches,
original.scale, original.rotation
);
if (eventType === "TextEvent") original.initTextEvent(
original.type, original.bubbles, original.cancelable,
original.view,
original.data, original.inputMethod, original.locale
);
if (eventType === "CompositionEvent") original.initTextEvent(
original.type, original.bubbles, original.cancelable,
original.view,
original.data, original.inputMethod, original.locale
);
if (eventType === "KeyboardEvent") original.initKeyboardEvent(
original.type, original.bubbles, original.cancelable,
original.view, original.char, original.key,
original.location, modifiersList, original.repeat
);
if (eventType === "InputEvent" || eventType === "UIEvent")
original.initUIEvent(
original.type, original.bubbles, original.cancelable,
original.view, original.detail
);
if (eventType === "FocusEvent") original.initFocusEvent(
original.type, original.bubbles, original.cancelable,
original.view, original.detail, original.relatedTarget
);
}
document.getElementById(newTargetId).dispatchEvent(eventCopy);
if (eventCopy.defaultPrevented) newTargetId.preventDefault();
}
<button onclick="redispatchEvent(arguments[0], '2nd')">Click Here</button>
<button id="2nd" onclick="console.log('Alternate clicked!')">Alternate Button</button>
보다 일반적인 솔루션
필요에 따라 원래 이벤트를 다시 배포하는 것보다 훨씬 더 나은 솔루션은 합성 이벤트 전 파일 수 있습니다. 수동으로 호출 할 수 있도록 이러한 리스너를 코드에 노출하는 이벤트 리스너를 등록하는 특별한 방법을 만듭니다. 실제로 getEventListeners
현재 이벤트 리스너를 검색하는 데 사용할 수 있는 함수가 있습니다. 그러나 getEventListeners
Chrome / Safari에서만 지원됩니다. 따라서 다음 대체품을 설계했습니다. 아래 코드는 너무 커 보이지만 아래 코드는 대부분 변수 이름이므로 축소 후 매우 작아집니다.
/**@type{WeakMap}*/ var registeredListeners = new WeakMap();
hearEvent(document.getElementById("1st"), "click", function propagate(evt) {
fireEvent(document.getElementById("2nd"), evt, propagate);
});
hearEvent(document.getElementById("2nd"), "click", function(evt) {
console.log( evt.target.textContent );
});
/**
* @param{Element} target
* @param{string} name
* @param{function(Event=):(boolean|undefined)} handle
* @param{(Object<string,boolean>|boolean)=} options
* @return {undefined}
*/
function hearEvent(target, name, handle, options) {
target.addEventListener(name, handle, options);
var curArr = registeredListeners.get(target);
if (!curArr) registeredListeners.set(target, (curArr = []));
curArr.push([
"" + name,
handle,
typeof options=="object" ? !!options.capture : !!options,
target
]);
}
/**
* @param{Element} target
* @param{string} name
* @param{function(Event=):(boolean|undefined)} handle
* @param{(Object<string,boolean>|boolean)=} options
* @return {undefined}
*/
function muteEvent(target, name, handle, options) {
name += "";
target.removeEventListener(name, handle, options);
var capturing = typeof options=="object"?!!options.capture:!!options;
var curArr = registeredListeners.get(target);
if (curArr)
for (var i=(curArr.length|0)-1|0; i>=0; i=i-1|0)
if (curArr[i][0] === name && curArr[i][2] === capturing)
curArr.splice(i, 1);
if (!curArr.length) registeredListeners.delete(target);
}
/**
* @param{Element} target
* @param{Event} eventObject
* @param{Element=} caller
* @return {undefined}
*/
function fireEvent(target, eventObject, caller) {
var deffered = [], name = eventObject.type, curArr, listener;
var immediateStop = false, keepGoing = true, lastTarget;
var currentTarget = target, doesBubble = !!eventObject.bubbles;
var trueObject = Object.setPrototypeOf({
stopImmediatePropagation: function(){immediateStop = true},
stopPropagation: function(){keepGoing = false},
get target() {return target},
get currentTarget() {return currentTarget}
}, eventObject);
do {
if (curArr = registeredListeners.get(currentTarget))
for (var i=0; i<(curArr.length|0) && !immediateStop; i=i+1|0)
if (curArr[i][0] === name && curArr[i][1] !== caller) {
listener = curArr[i];
if (listener[2]) {
listener[1].call(trueObject, trueObject);
} else if (doesBubble || currentTarget === target) {
deffered.push( listener );
}
}
if (target.nodeType === 13) {
// for the ShadowDOMv2
deffered.push([ target ]);
currentTarget = target = currentTarget.host;
}
} while (keepGoing && (currentTarget = currentTarget.parentNode));
while (
(listener = deffered.pop()) &&
!immediateStop &&
(lastTarget === listener[3] || keepGoing)
)
if (listener.length === 1) {
// for the ShadowDOMv2
target = listener[0];
} else {
lastTarget = currentTarget = listener[3];
listener[1].call(trueObject, trueObject);
}
}
<button id="1st">Click Here</button>
<button id="2nd">Alternate Button</button>
축소 후이 모든 코드가 gzip 이전에 단일 킬로바이트에 깔끔하게 들어 맞는지 확인하십시오.
var k=new WeakMap;m(document.getElementById("1st"),"click",function q(a){r(document.getElementById("2nd"),a,q)});m(document.getElementById("2nd"),"click",function(a){console.log(a.target.textContent)});function m(a,c,f,b){a.addEventListener(c,f,b);var d=k.get(a);d||k.set(a,d=[]);d.push([""+c,f,"object"==typeof b?!!b.capture:!!b,a])}
function r(a,c,f){var b=[],d=c.type,n=!1,p=!0,g=a,t=!!c.bubbles,l=Object.setPrototypeOf({stopImmediatePropagation:function(){n=!0},stopPropagation:function(){p=!1},get target(){return a},get currentTarget(){return g}},c);do{if(c=k.get(g))for(var h=0;h<(c.length|0)&&!n;h=h+1|0)if(c[h][0]===d&&c[h][1]!==f){var e=c[h];e[2]?e[1].call(l,l):(t||g===a)&&b.push(e)}13===a.nodeType&&(b.push([a]),g=a=g.host)}while(p&&(g=g.parentNode));for(;(e=b.pop())&&!n&&(u===e[3]||p);)if(1===e.length)a=e[0];else{var u=g=
e[3];e[1].call(l,l)}}function z(a,c,f,b){c+="";a.removeEventListener(c,f,b);f="object"==typeof b?!!b.capture:!!b;if(b=k.get(a))for(var d=(b.length|0)-1|0;0<=d;d=d-1|0)b[d][0]===c&&b[d][2]===f&&b.splice(d,1);b.length||k.delete(a)}
<button id="1st">Click Here</button>
<button id="2nd">Alternate Button</button>
참조 URL : https://stackoverflow.com/questions/11974262/how-to-clone-or-re-dispatch-dom-events
'programing' 카테고리의 다른 글
LINQ에서 Union All을 사용하는 방법은 무엇입니까? (0) | 2021.01.14 |
---|---|
Cassandra column family의 모든 데이터를 삭제하려면 어떻게해야합니까? (0) | 2021.01.14 |
MVC 자식 작업이란 무엇입니까? (0) | 2021.01.14 |
Parallel.ForEach에서 반환 값을 어떻게 수집합니까? (0) | 2021.01.14 |
Dropzone.js를 사용하여 서버에 이미 저장된 파일을 어떻게 보여줄 수 있습니까? (0) | 2021.01.14 |