Creating an event that triggers a second event - javascript

I'm trying to create a jQuery event that triggers a second event. The first event is clicking on the emoji id which refers to an image. The second is a mousemove event which moves the image around the page. The third event stops this event when the mouse click happens again anywhere in the body of the page and places the image at that absolute position. I was able to get the second and the third events to work but I can't get the first event to work with the second. Here is what I have so far for my jQuery:
var mouseTracker = function(event) {
console.log(event.pageX, event.pageY, !!event.which)
$('#emoji').css('top', event.pageY);
$('#emoji').css('bottom', event.pageY);
$('#emoji').css('left', event.pageX);
$('#emoji').css('right', event.pageX);
}
var begin = function() {
$('body').on('mousemove', mouseTracker);
$('body').css('cursor', 'none');
}
var stop = function() {
$('body').off('mousemove', mouseTracker);
$('#emoji').css('postion', 'absolute')
$('body').css('cursor', 'default');
}
$('#emoji').on('click', begin);
$('body').on('click', stop);`

Initialize the event from within the first event call.
$('#emoji').on('click', function() {
begin();
$('body').on('click', stop);
});

During the click on #emoji the body click even is also triggered.
That leads to calling stop(). The propagation of that event to body can be blocked by event.stopPropagation() (or equivalent return false from begin()). The propagation should be manually stopped even if body on click handler is attached in begin().
You may want one-time usage of some events. That can be done by binding using .one(). In that case the handler is detached after the first usage without manual .off():
var begin = function (event) {
$('body').on('mousemove', mouseTracker);
$('body').one('click', stop);
$('body').css('cursor', 'none');
return false; // event.stopPropagation();
}
var stop = function () {
$('#emoji').one('click', begin);
$('body').off('mousemove', mouseTracker);
$('#emoji').css('postion', 'absolute')
$('body').css('cursor', 'default');
}
$('#emoji').one('click', begin);

Related

Capture all event targets from mouseover when user clicks, then stop

I'd like to record all event.target that mouse encounters after user clicks anywhere and stop recording after he releases click. So far I've come up with this which doesn't stop recording after mouseup and I don't know why.
document.addEventListener('click', function() {
document.addEventListener('mouseover', record);
document.addEventListener('mouseup', removeListener);
})
function record(e) {
console.log(e.target);
}
function removeListener() {
document.removeEventListener('mouseover', record);
document.removeEventListener('mouseup', removeListener);
}
<div class='toto'>Toto</div>
<div class='toto'>Toto</div>
<div class='toto'>Toto</div>
<div class='toto'>Toto</div>
EDIT : Answer & Explanation
addEventListener('click') triggers on mouseup, therefore the sequence was as follow :
document.addEventListener('click', function() {
//Following would start once mouseup
document.addEventListener('mouseover', record);
//Following never triggers cause mouse is already up
document.addEventListener('mouseup', removeListener);
})
Solution as stated in the answer is to replace 'click' with 'mousedown'. It triggers immediatly after mouse is click is pressed, not released :
document.addEventListener('mousedown', function() {
document.addEventListener('mouseover', record);
document.addEventListener('mouseup', removeListener);
})
Instead of click event, you should use mousedown
I forked your codepen and you can see the result: https://codepen.io/Lazzaro83/pen/EeoxEW
document.addEventListener('mousedown', function() {
document.addEventListener('mouseover', record);
document.addEventListener('mouseup', removeListener);
})
Your problem is because you are putting one listener inside another, this isn't a reliable way to do so because terms of ms of execution, remember JS is not that "sequential" do not worry and let the three listener to live, a better way of do the thing you want to is make a global variable that works like a switch :
let switch = false;
document.addEventListener('click', function(e) {
e.stopPropagation();
switch = true;
});
document.addEventListener('mouseover', function(e){
e.stopPropagation();
if (switch){
console.log(e.target);
}
});
document.addEventListener('mouseup', function(e){
e.stopPropagation();
switch = false;
}) ;
this is a project i did with a blackboard, have many techniques as relegation:
https://codepen.io/LeonAGA/pen/eyWpMV
regards!

Javascript - How can I differentiate a click and a double click on one element

I am trying to add a click function that triggers when a button is clicked. I am also trying to figure out how to add a double click function onto the same element, that triggers a different event.
var click = false;
onEvent("image2", "click", function(event) {
click = true;
});
if (click === true) {
setTimeout(function() {
onEvent("image2", "click", function(event) {
setScreen("safeScreen");
console.log("double click");
});
}, 200);
} else {
onEvent("image2", "dblclick", function(event) {
setScreen("safeScreen");
console.log("click");
});
}
This code is completely wrong, but I don't know where to start/correct. What am I doing wrong?
You should replace click with dblclick
Also check this link

How to restart event mousemove jquery?

I have to move a div by clicking on it, clicking again I must stop the div in that position. Now the problem is: when I want to move again the div, does not activate the mousemove event ... how can I fix it?
$('.move_div').live('click', function() {
$('html').on('mousemove', function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
$('div').css({'top': y, 'left': x});
});
$("html").live('click', function() {
$('html').off('mousemove');
});
});
var ele = '.move_adv';
var moveBool = false;
$(function () {
$('html').on('mousemove', function (e) {
console.log($(this).width());
if (moveBool == true) {
var x = e.pageX - $(ele).width()/2;
var y = e.pageY - $(ele).height()/2;
$(ele).css({
'top': y,
'left': x
});
}
});
});
$(ele).live('click', function () {
moveBool = !moveBool;
});
http://jsfiddle.net/6y24s/2/
The main logic is storing the 'moveability' state of the div in a boolean.
You would also like to refine the code more.
Fiddle here , if you want to keep your code then only thing you need to add is
event.stopPropagation();
When you click on the div the mousemove handler is added to the div. Then an event handler is added to the document that removes any mousemove event handlers.
You then move the mouse and the div follows, you click and the mousemove handler is deleted.
You click on the div again, a mousemove event handler is added, though then the click event handler from the document takes away the mousemove handler.
So whenever you click after the first two clicks the mousemove handler is simultaneously created and destroyed.
Also use .on() instead of .live()
.live() was deprecated in JQuery 1.7

Prevent click event after drag in jQuery

I have a draggable <div> with a click event and without any event for drag,
but after I drag <div> the click event is apply to <div>.
How can prevent of click event after drag?
$(function(){
$('div').bind('click', function(){
$(this).toggleClass('orange');
});
$('div').draggable();
});
http://jsfiddle.net/prince4prodigy/aG72R/
FIRST attach the draggable event, THEN the click event:
$(function(){
$('div').draggable();
$('div').click(function(){
$(this).toggleClass('orange');
});
});
Try it here:
http://jsfiddle.net/aG72R/55/
With an ES6 class (No jQuery)
To achieve this in javascript without the help of jQuery you can add and remove an event handler.
First create functions that will be added and removed form event listeners
flagged () {
this.isScrolled = true;
}
and this to stop all events on an event
preventClick (event) {
event.preventDefault();
event.stopImmediatePropagation();
}
Then add the flag when the mousedown and mousemove events are triggered one after the other.
element.addEventListener('mousedown', () => {
element.addEventListener('mousemove', flagged);
});
Remember to remove this on a mouse up so we don't get a huge stack of events repeated on this element.
element.addEventListener('mouseup', () => {
element.removeEventListener('mousemove', flagged);
});
Finally inside the mouseup event on our element we can use the flag logic to add and remove the click.
element.addEventListener('mouseup', (e) => {
if (this.isScrolled) {
e.target.addEventListener('click', preventClick);
} else {
e.target.removeEventListener('click', preventClick);
}
this.isScrolled = false;
element.removeEventListener('mousemove', flagged);
});
In the above example above I am targeting the real target that is clicked, so if this were a slider I would be targeting the image and not the main gallery element. to target the main element just change the add/remove event listeners like this.
element.addEventListener('mouseup', (e) => {
if (this.isScrolled) {
element.addEventListener('click', preventClick);
} else {
element.removeEventListener('click', preventClick);
}
this.isScrolled = false;
element.removeEventListener('mousemove', flagged);
});
Conclusion
By setting anonymous functions to const we don't have to bind them. Also this way they kind of have a "handle" allowing s to remove the specific function from the event instead of the entire set of functions on the event.
I made a solution with data and setTimeout. Maybe better than helper classes.
<div id="dragbox"></div>
and
$(function(){
$('#dragbox').bind('click', function(){
if($(this).data('dragging')) return;
$(this).toggleClass('orange');
});
$('#dragbox').draggable({
start: function(event, ui){
$(this).data('dragging', true);
},
stop: function(event, ui){
setTimeout(function(){
$(event.target).data('dragging', false);
}, 1);
}
});
});
Check the fiddle.
This should work:
$(function(){
$('div').draggable({
start: function(event, ui) {
$(this).addClass('noclick');
}
});
$('div').click(function(event) {
if ($(this).hasClass('noclick')) {
$(this).removeClass('noclick');
}
else {
$(this).toggleClass('orange');
}
});
});
DEMO
You can do it without jQuery UI draggable. Just using common 'click' and 'dragstart' events:
$('div').on('dragstart', function (e) {
e.preventDefault();
$(this).data('dragging', true);
}).on('click', function (e) {
if ($(this).data('dragging')) {
e.preventDefault();
$(this).data('dragging', false);
}
});
You can just check for jQuery UI's ui-draggable-dragging class on the draggable. If it's there, don't continue the click event, else, do. jQuery UI handles the setting and removal of this class, so you don't have to. :)
Code:
$(function(){
$('div').bind('click', function(){
if( $(this).hasClass('ui-draggable-dragging') ) { return false; }
$(this).toggleClass('orange');
});
$('div').draggable();
});
With React
This code is for React users, checked the draggedRef when mouse up.
I didn`t use click event. The click event checked by the mouse up event.
const draggedRef = useRef(false);
...
<button
type="button"
onMouseDown={() => (draggedRef.current = false)}
onMouseMove={() => (draggedRef.current = true)}
onMouseUp={() => {
if (draggedRef.current) return;
setLayerOpened(!layerOpened);
}}
>
BTN
</button>
I had the same problem (tho with p5.js) and I solved it by having a global lastDraggedAt variable, which was updated when the drag event ran. In the click event, I just checked if the last drag was less than 0.1 seconds ago.
function mouseDragged() {
// other code
lastDraggedAt = Date.now();
}
function mouseClicked() {
if (Date.now() - lastDraggedAt < 100)
return; // its just firing due to a drag so ignore
// other code
}

setInterval cannot clear with mouseup

I am using mousedown and mouseup to trigger a setInterval function like so:
$("#rotateRight").mousedown(function() {
intervalIRight = setInterval(rotateRight, 0);
}).mouseup(function() {
clearInterval(intervalIRight);
});
This works great, however, if I release the mouse (mouseup) when I am not hovering over $("#rotateRight") then there is technically no 'mouseup' so the interval goes on forever and is never cleared.
I cannot use hover because I want the even to be when a user clicks and holds a mouse. But at the same time, I need to fix this 'mouseup bug.' Any ideas?
UPDATE: New code is as follows, but still does not clear interval because mouseup happens on an iframe, not the DOM.
var intervalIRight;
var intervalILeft;
$("#rotateRight").on('mousedown', function() {
intervalIRight = setInterval(rotateRight, 0);
});
$("#rotateLeft").on('mousedown', function() {
intervalILeft = setInterval(rotateLeft, 0);
});
$(document).on('mouseup', function() {
clearInterval(intervalIRight);
clearInterval(intervalILeft);
});
clear the interval on any mouseup by attaching the event handler to the document.
var intervalIRight;
$("#rotateRight").on('mousedown', function() {
intervalIRight = setInterval(rotateRight, 0);
});
$(document).on('mouseup', function() {
clearInterval(intervalIRight);
});
FIDDLE

Categories