I have 2 seperate event listeners, the first one is a click event, second one is a window beforeunload listener:
This is the click event listener:
document.body.addEventListener('click',function(event){
if (event.defaultPrevented) return;
console.log('click EL');
})
and this is the beforeunload listener:
window.addEventListener("beforeunload", function (e) {
e.preventDefault();
console.log('beforeunload EL');
})
Can I stop the click event from firing if the beforeunload is fired? I've tried doing it with event.preventDefault(); still it didn't work.
Try this, This is working code:
var beforeunload = function (e) {
e.preventDefault();
console.log('beforeunload EL');
}
window.addEventListener("beforeunload", beforeunload);
document.body.addEventListener('click',function(event){
if (event.defaultPrevented) return;
console.log('click EL');
window.removeEventListener("beforeunload", beforeunload);
});
Just remove the listener if your click happened
Related
Since dispatchEvent, as per the docs, will apply the:
normal event processing rules (including the capturing and optional
bubbling phase)
I'm looking for something similar but with a way to skip this process and trigger the event directly on the element. To trigger the default element event behavior while bypassing the processing stage.
As in, to capture the event at window level (before it reaches the other capture triggers) and pass it straight to the component (text area) invoking it directly.
(For example to trigger the default keydown of a text area without going through the hierarchy)
I've been trying to do it like this but if there is another event at window level this will not work:
window.addEventListener("keydown", this.keyDown, true);
keyDown = (event) => {
event.preventDefault();
event.nativeEvent && event.nativeEvent.stopImmediatePropagation();
event.stopImmediatePropagation && event.stopImmediatePropagation();
event.stopPropagation();
// Pass event straight to the element
return false;
};
I'm looking to trigger the default element event behavior while bypassing the processing
There may well be a more elegant way to do this, but one option is to remove the element from the DOM first, dispatch the event to it, then put it back into the DOM:
document.body.addEventListener('keydown', () => {
console.log('body keydown capturing');
}, true);
document.body.addEventListener('keydown', () => {
console.log('body keydown bubbling');
});
const input = document.querySelector('input');
input.addEventListener('keydown', () => {
console.log('input keydown');
});
const node = document.createTextNode('');
input.replaceWith(node);
input.dispatchEvent(new Event('keydown'));
node.replaceWith(input);
<input>
Since the element isn't in the DOM when the event is dispatched, the elements which used to be its ancestors won't see the event.
Note that events dispatched to detached elements do not capture/bubble regardless, not even to parents or children of element the event was dispatched to.
Without removing the element from the DOM entirely beforehand, if the input can exist in a shadow DOM, you can also dispatch an event to it there, and the event won't capture down or bubble up (though user input, not being custom events, will propagate through):
document.body.addEventListener('keydown', () => {
console.log('body keydown capturing');
}, true);
document.body.addEventListener('keydown', () => {
console.log('body keydown bubbling');
});
outer.attachShadow({mode: 'open'});
const input = document.createElement('input');
outer.shadowRoot.append(input);
input.addEventListener('keydown', () => {
console.log('input keydown');
});
input.dispatchEvent(new Event('keydown'));
<div id="outer"></div>
Another approach would be to call stopPropagation and stopImmediatePropagation in the capturing phase, at the very beginning, when the event is at the window, and then manually call the listener function you want. Make sure to attach your window listener before any other scripts on the page run, to make sure none of the page's listeners can see the event first:
// Your script:
const input = document.body.appendChild(document.createElement('input'));
input.className = 'custom-extension-element';
const handler = (e) => {
setTimeout(() => {
console.log(e.target.value);
});
};
window.addEventListener(
'keydown',
(e) => {
if (e.target.closest('.custom-extension-element')) {
e.stopImmediatePropagation(); // Stop other capturing listeners on window from seeing event
e.stopPropagation(); // Stop all other listeners
handler(e);
}
},
true // add listener in capturing phase
);
// Example page script
// which tries to attach listener to window in capturing phase:
window.addEventListener(
'keydown',
(e) => {
console.log('page sees keydown');
},
true
);
document.body.addEventListener('keydown', () => {
console.log('body keydown capturing');
}, true);
document.body.addEventListener('keydown', () => {
console.log('body keydown bubbling');
});
The best way around propagation issues is to just execute the function:
function tester(){
console.log("Just fire the function! Don't dispatchEvent!");
}
tester();
document.getElementById('test').onkeyup = function(e){
e.stopPropagation();
console.log(this.id); console.log(e.target); tester();
}
document.body.onkeyup = ()=>{
console.log("This shouldn't fire when on #test");
}
<input id='test' type='text' value='' />
Scenario :
I use this code for a page and apply it on click event, now I have trouble to remove it from page (same way, on click).
How do I do that?
document.addEventListener('touchmove', function(e) {
e.preventDefault();
}, {
passive: false
});
Use a named callback function touchMove when binding/unbinding the event listener to addEventListener and removeEventListener methods.
The event listener to be removed is identified using a combination of
the event type, the event listener function itself, and various
optional options that may affect the matching process;
var touchMove = function(e){
e.preventDefault();
};
document.addEventListener('touchmove', touchMove, { passive: false });
document.removeEventListener('touchmove', touchMove);
So initialize your button to add the event listener on click to the touchmove area, then remove the click function from the button and set it up so the next cick adds the remove event listener for removing the click and touch event. Basically toggle the event listener on the button and the div.
//Touchmove action
function preDef(e) {
e.preventDefault();
}
//Add the touchmove action and toggle the button to remove the action
function addE(e) {
e.target.removeEventListener('click', addE, {passive: false});
e.target.addEventListener('click', removeE, {passive: false});
document.addEventListener('touchmove', preDef, {passive: false});
}
//Remove the touchmove action and toggle the button to add the action
function removeE(e) {
e.target.removeEventListener('click', removeE, {passive: false});
e.target.addEventListener('click', addE, {passive: false});
document.removeEventListener('touchmove', preDef, {passive: false});
}
//Initialize the add action
document.getElementById('somebutton').addEventListener('click', addE, {passive: false});
My blur event fires but not my click event. If I remove the blur event code the click event works fine.
How do I change the order these events fire?
$.fn.autoComplete = function () {
$(document).on('click', '#' + settings.resultsDivId + ' tr', function () {
console.log('click fired');
$('#' + settings.resultsDivId).hide();
});
this.on('blur', function () {
console.log('blur fired');
$('#' + settings.resultsDivId).hide();
});
function AutoComplete(term) {
// ajax call stuff
}
};
Changing click to mousedown solved it. Apparently click fires after blur.
Blur event stops click event from working?
This is my html code
< button class="send-report" name="submit" id="submit" type="submit" onclick="reportfeed()">Send Report< /button>
On the first click the keyboard disappeared, the 'reportfeed' function works only in the second click (in ipad)
function reportfeed()
{
alert(1);
}
I can use the code below, Please help me if you know any other method
jQuery(".send-report").bind("click touchstart", function(){
reportfeed();
});
Define a clickhandler that you can use later on:
var clickHandler = ('ontouchstart' in document.documentElement ? "touchstart" : "click");
$(".send-report").bind(clickHandler, function(e) {
alert("clicked or tapped. This button used: " + clickHandler);
});
This will trigger click on non-touch devices and touchstart on touch devices.
Use .on() because .bind() will be removed from future scripts,I think.
Try this
$(".send-report").on('touchstart click', function(){
reportfeed();
});
You could use .stopPropagation() to stop multiple events being fired. Also, if you want to do specific stuff for different event types use e.type
$('.send-report').on('touchstart click', function(e) {
e.stopPropagation(); //stops propagation
if(e.type == "touchstart") {
// Handle touchstart event.
} else if(e.type == "click") {
// Handle click event.
}
});
I want to trigger click event on a element when mousedown occurs. Also, I want to enable this feature for all elements in a html page.
Is it possible with jQuery on Chrome ?
Here's my first attempt;
$.fn.mousedown = function (onclick) {
this.bind("click", function (e) { onclick.call(this, e); });
return this;
};
But this mousedown elements fired after click occurs.
$(document).on('mousedown', function (e) { $(e.target).trigger('click') })
I'm not sure though for what this should be useful.
To prevent the second click (which is the normal click) you have to do some extra work
$(document).on('mousedown', function (e) {
$(e.target).trigger('click').once('click', function (e) {
e.preventDefault();
e.stopPropagation();
});
})