calling removeEventListener from within event listener? - javascript

I have some simple code, but currently it does not remove the listener after the first call. How can I achieve this? Or do I really need to add redundant if/else checks on a var set upon notice?
document.addEventListener("contextmenu", function(e){
alert("Please remember this is someone's art! Give credit where it is deserved!");
document.removeEventListener("contextmenu", function(e){
console.log('User has been warned...');
});
}, false);
Updated code Still same message every right click
document.addEventListener("contextmenu", function msg(e){
alert("Please remember this is someone's art! Give credit where it is deserved!");
e.removeEventListener("contextmenu", msg, false);
}, false);

you need to pass the same function to remove as add.
the easy way to do that is to give the function a name and pass the name to removeEventListener():
document.addEventListener("contextmenu", function me(e){
alert("Please remember this is someone's art! Give credit where it is deserved!");
document.removeEventListener("contextmenu", me, false);
}, false);
see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.removeEventListener for a good overview
obligatory fiddle: http://jsfiddle.net/w1kzLkoL/
tested in chrome, firefox, and IE10

You may try this example:
document.addEventListener("contextmenu", (function() {
var done = false;
return function(e) {
if (!done) {
done = true;
alert('Warning !');
}
console.log('done ...', done);
e.preventDefault();
return false;
};
})(), false);
Open console... right click

Easiest way is to just configure the event listener with { once: true }.
document.addEventListener('contextmenu', (e) => {
your code...
}, { once: true });

Related

.click() not getting fired over an anchor tag after modifying its download attribute

My case is that "System needs to ask to the user that 'are you going to open the image or to download it.?' by using a confirm box.. If user presses okay we should not prevent the default action of that anchor tag, let it go, but if user presses cancel the particular image should get downloaded...
HTML:
test
JS:
$('a').click(function (e) {
if (!$(this).is('[download]')) {
var cond = confirm('Press ok to view, cancel to save..');
if (!cond) {
e.preventDefault();
$(this).attr('download', 'download').click().removeAttr('download');
}
}
});
DEMO
Can anybody tell how to achieve this..?
You need to use this.click(); as HTMLElement.click() method simulates a mouse click on an element.
Whereas $(this).click(); will only trigger jquery click handler and onclick handler bounded to element nothing else.
$('a').click(function (e) {
if (!$(this).is('[download]')) {
var cond = confirm('Press ok to view, cancel to save..');
if (!cond) {
e.preventDefault();
$(this).attr('download', 'download');
this.click()
$(this).removeAttr('download');
}
}
});
DEMO
Try with this, $("a")[0].click() will do the trick
$('a').click(function (e) {
if (!$(this).is('[download]')) {
var cond = confirm('Press ok to view, cancel to save..');
if (!cond) {
e.preventDefault();
$(this).attr('download', 'download');
$("a")[0].click().removeAttr('download');
}
}
});
Demo
$('a').click(function (e) {
if (!$(this).is('[download]')) {
var resp = confirm("Press ok to view, cancel to save..!");
if (resp == true) {
// You pressed OK
e.preventDefault();
} else {
// Pressed Cancel!";
$(this).attr('download', 'download').click().removeAttr('download');
}
}
});
here you go working fiddle
http://jsfiddle.net/sajrashid/94Hra/18/
There is no need to mess with event bubbling with this one. Let the browser's default behavior take care of everything. Calling events manually always creates a mess. Control behavior with the download attribute. Add it or remove it based on your condition and pass the ball to browser.
Demo
Code:
$('a').click(function (e) {
var cond = confirm('Press ok to view, cancel to save..');
if (!cond) {
$(this).attr('download', 'download');
} else {
$(this).removeAttr('download');
}
});
I checked your code and got a solution
So you have to change your code a bit
you have add a name tag in your anchor tag like
test
Now replace your code
$('a').click(function (e) {
With this one
$(document).on("click","a[name='myevent']", function (e) {

Jquery long press, stop short press action not working

I am trying to implement one event for a short press and a different for a long press. The short press is just doing the default action. The long press works, but also does the default action still. What am I missing?
HTML
<"Label for my Link"
Javascript
$(document).ready(function(){
$('.recordlongpress').each(function() {
var timeout, longtouch;
$(this).mousedown(function() {
timeout = setTimeout(function() {
longtouch = true;
}, 1000);
}).mouseup(function(e) {
if (longtouch) {
e.preventDefault();
$('#popupPanel').popup("open");
return false;
} else {
return;
}
longtouch = false;
clearTimeout(timeout);
});
});
});
I followed the jQuery documentation and was under the impress "preventDefault" should stop the short press default action. Any examples I have found online do not seem to be exactly my situation. I appreciate you taking the time to read this. Thank you for any input.
You're returning from your "mouseup" handler before clearing the timeout and setting "longtouch" to false.
Try:
}).mouseup(function(e) {
var returnval;
if (longtouch) {
e.preventDefault();
$('#popupPanel').popup("open");
returnval = false;
}
longtouch = false;
clearTimeout(timeout);
return returnVal;
});
I'd also clear "longtouch" in the "mousedown" handler. That said, I wouldn't do this with mouse events. I'd use "touchstart" and "touchend". On touch screen devices, "mouse" events are simulated from touch events, and there's a distinct delay involved. (You may also want to detect whether the finger moved during the touch period.)
jsFiddle Demo
In your code these lines are unreachable
longtouch = false;
clearTimeout(timeout);
JS:
$('.recordlongpress').each(function () {
var timeout, longtouch = false;
$(this).mousedown(function () {
timeout = setTimeout(function () {
longtouch = true;
}, 1000);
e.preventDefault();
}).mouseup(function (e) {
clearTimeout(timeout);
if (longtouch == true) {
longtouch = false;
$('body').append("long press" + longtouch);
return false;
} else {
return;
}
});
});
#Pointy lead me towards a working solution for clicking events.
$(document).ready(function(){
$('.recordlongpress').bind('tap', function(event) {
return;
});
$('.recordlongpress').bind('taphold', function(event) {
$('#popupPanel').popup("open");
});
});
Something still needs to be added because upon a long press on my mobile device, the default options screen with the four options; open, save link, copy link URL and select text still pops up as well. I will add on the fix for that once I find it.

How to continue event propagation after cancelling?

When a user clicks a certain link I would like to present them with a confirmation dialog. If they click "Yes" I would like to continue the original navigation. One catch: my confirmation dialog is implemented by returning a jQuery.Deferred object which is resolved only when/if the user clicks the Yes button. So basically the confirmation dialog is asynchronous.
So basically I want something like this:
$('a.my-link').click(function(e) {
e.preventDefault(); e.stopPropogation();
MyApp.confirm("Are you sure you want to navigate away?")
.done(function() {
//continue propogation of e
})
})
Of course I could set a flag and re-trigger click but that is messy as heck. Any natural way of doing this?
Below are the bits from the code that actually worked in Chrome 13, to my surprise.
function handler (evt ) {
var t = evt.target;
...
setTimeout( function() {
t.dispatchEvent( evt )
}, 1000);
return false;
}
This is not very cross-browser, and maybe will be fixed in future, because it feels like security risk, imho.
And i don't know what happens, if you cancel event propagation.
It could be risky but seems to work at the time of writing at least, we're using it in production.
This is ES6 and React, I have tested and found it working for the below browsers. One bonus is if there is an exception (had a couple during the way making this), it goes to the link like a normal <a> link, but it won't be SPA then ofc.
Desktop:
Chrome v.76.0.3809.132
Safari v.12.1.2
Firefox Quantum v.69.0.1
Edge 18
Edge 17
IE11
Mobile/Tablet:
Android v.8 Samsung Internet
Android v.8 Chrome
Android v.9 Chrome
iOs11.4 Safari
iOs12.1 Safari
.
import 'mdn-polyfills/MouseEvent'; // for IE11
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class ProductListLink extends Component {
constructor(props) {
super(props);
this.realClick = true;
this.onProductClick = this.onProductClick.bind(this);
}
onProductClick = (e) => {
const { target, nativeEvent } = e;
const clonedNativeEvent = new MouseEvent('click', nativeEvent);
if (!this.realClick) {
this.realClick = true;
return;
}
e.preventDefault();
e.stopPropagation();
// #todo what you want before the link is acted on here
this.realClick = false;
target.dispatchEvent(clonedNativeEvent);
};
render() {
<Link
onClick={(e => this.onProductClick(e))}
>
Lorem
</Link>
}
}
I solved problem by this way on one of my projects. This example works with some basic event handling like clicks etc. Handler for confirmation must be first handler bound.
// This example assumes clickFunction is first event handled.
//
// you have to preserve called function handler to ignore it
// when you continue calling.
//
// store it in object to preserve function reference
var ignoredHandler = {
fn: false
};
// function which will continues processing
var go = function(e, el){
// process href
var href = $(el).attr('href');
if (href) {
window.location = href;
}
// process events
var events = $(el).data('events');
for (prop in events) {
if (events.hasOwnProperty(prop)) {
var event = events[prop];
$.each(event, function(idx, handler){
// do not run for clickFunction
if (ignoredHandler.fn != handler.handler) {
handler.handler.call(el, e);
}
});
}
}
}
// click handler
var clickFunction = function(e){
e.preventDefault();
e.stopImmediatePropagation();
MyApp.confirm("Are you sure you want to navigate away?")
.done(go.apply(this, e));
};
// preserve ignored handler
ignoredHandler.fn = clickFunction;
$('.confirmable').click(clickFunction);
// a little bit longer but it works :)
If I am understanding the problem correctly, I think you can just update the event to be the original event in that closure you have there. So just set e = e.originalEvent in the .done function.
https://jsfiddle.net/oyetxu54/
MyApp.confirm("confirmation?")
.done(function(){ e = e.originalEvent;})
here is a fiddle with a different example (keep the console open so you can see the messages):
this worked for me in chrome and firefox
I solved this by:
placing a event listener on a parent element
removing the class from the link ONLY when the user confirms
reclicking the link after I have removed the class.
function async() {
var dfd = $.Deferred();
// simulate async
setTimeout(function () {
if (confirm('Stackoverflow FTW')) {
dfd.resolve();
} else {
dfd.reject();
}
}, 0);
return dfd.promise();
};
$('.container').on('click', '.another-page', function (e) {
e.stopPropagation();
e.preventDefault();
async().done(function () {
$(e.currentTarget).removeClass('another-page').click();
});
});
$('body').on('click', function (e) {
alert('navigating somewhere else woot!')
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
Somewhere else
</div>
The reason I added the event listener to the parent and not the link itself is because the jQuery's on event will bind to the element until told otherwise. So even though the element does not have the class another-page it still has the event listener attached thus you have to take advantage of event delegation to solve this problem.
GOTCHAS this is very state based. i.e. if you need to ask the user EVERYTIME they click on a link you'll have to add a 2nd listener to readd the another-page class back on to the link. i.e.:
$('body').on('click', function (e) {
$(e.currentTarget).addClass('another-page');
});
side note you could also remove the event listener on container if the user accepts, if you do this make sure you use namespace events because there might be other listeners on container you might inadvertently remove. see https://api.jquery.com/event.namespace/ for more details.
We have a similar requirement in our project and this works for me. Tested in chrome and IE11.
$('a.my-link').click(function(e) {
e.preventDefault();
if (do_something === true) {
e.stopPropogation();
MyApp.confirm("Are you sure you want to navigate away?")
.done(function() {
do_something = false;
// this allows user to navigate
$(e.target).click();
})
}
})
I edited your code. New features that I added:
Added namespace to event;
After click on element event will be removed by namespace;
Finally, after finish needed actions in "MyApp" section continue propagation by triggering others element "click" events.
Code:
$('a.my-link').on("click.myEvent", function(e) {
var $that = $(this);
$that.off("click.myEvent");
e.preventDefault();
e.stopImmediatePropagation();
MyApp.confirm("Are you sure you want to navigate away?")
.done(function() {
//continue propogation of e
$that.trigger("click");
});
});
This is untested but might serve as a workaround for you
$('a.my-link').click(function(e) {
e.preventDefault(); e.stopPropogation();
MyApp.confirm("Are you sure you want to navigate away?")
.done(function() {
//continue propogation of e
$(this).unbind('click').click()
})
})

Catch only keypresses that change input?

I want to do something when a keypress changes the input of a textbox. I figure the keypress event would be best for this, but how do I know if it caused a change? I need to filter out things like pressing the arrow keys, or modifiers... I don't think hardcoding all the values is the best approach.
So how should I do it?
In most browsers, you can use the HTML5 input event for text-type <input> elements:
$("#testbox").on("input", function() {
alert("Value changed!");
});
This doesn't work in IE < 9, but there is a workaround: the propertychange event.
$("#testbox").on("propertychange", function(e) {
if (e.originalEvent.propertyName == "value") {
alert("Value changed!");
}
});
IE 9 supports both, so in that browser it's better to prefer the standards-based input event. This conveniently fires first, so we can remove the handler for propertychange the first time input fires.
Putting it all together (jsFiddle):
var propertyChangeUnbound = false;
$("#testbox").on("propertychange", function(e) {
if (e.originalEvent.propertyName == "value") {
alert("Value changed!");
}
});
$("#testbox").on("input", function() {
if (!propertyChangeUnbound) {
$("#testbox").unbind("propertychange");
propertyChangeUnbound = true;
}
alert("Value changed!");
});
.change() is what you're after
$("#testbox").keyup(function() {
$(this).blur();
$(this).focus();
$(this).val($(this).val()); // fix for IE putting cursor at beginning of input on focus
}).change(function() {
alert("change fired");
});
This is how I would do it: http://jsfiddle.net/JesseAldridge/Pggpt/1/
$('#input1').keyup(function(){
if($('#input1').val() != $('#input1').attr('prev_val'))
$('#input2').val('change')
else
$('#input2').val('no change')
$('#input1').attr('prev_val', $('#input1').val())
})
I came up with this for autosaving a textarea. It uses a combination of the .keyUp() jQuery method to see if the content has changed. And then I update every 5 seconds because I don't want the form getting submitted every time it's changed!!!!
var savePost = false;
jQuery(document).ready(function() {
setInterval('autoSave()', 5000)
$('input, textarea').keyup(function(){
if (!savePost) {
savePost = true;
}
})
})
function autoSave() {
if (savePost) {
savePost = false;
$('#post_submit, #task_submit').click();
}
}
I know it will fire even if the content hasn't changed but it was easier that hardcoding which keys I didn't want it to work for.

How to hook into the page wide click event?

Just like the question states. I want to fire off an event that calls a method everytime the user clicks on the web page.
How do I do that without use of jQuery?
Without using jQuery, I think you could do it like this:
if (document.addEventListener) {
document.addEventListener('click',
function (event) {
// handle event here
},
false
);
} else if (document.attachEvent) {
document.attachEvent('onclick',
function (event) {
// handle event here
}
);
}
Here's one way to do it..
if (window.addEventListener)
{
window.addEventListener('click', function (evt)
{
//do something
}, false);
}
else if(window.attachEvent)
{
window.attachEvent('onclick', function (evt)
{
// do something (for IE)
});
}
$(document).click(function(){});
document.onclick = function() { alert("hello"); };
note that this will only allow for one such function though.

Categories