So right now I have a 20 by 20 grid and I want the user to be able to click and select multiple cells in the grid. There is a method I was able to find online but the problem is that mouseover takes over and highlights the cells right when the mouse is over the cells and this is not what I want. I want the user click on a cells then basically drag their mouse and highlight the cells that they want then execute mouseup once they let go.
These are my files.
let graph = document.getElementById("container");
graph.style.display = "flex";
function createGraph() {
let j = 0;
for (let i = 0; i < 20; i++) {
let row = document.createElement("div");
row.id = "row" + i;
row.style.height = "50px";
row.style.width = "50px";
graph.appendChild(row);
let currentRow = document.getElementById("row" + i);
j++;
for (let j = 0; j < 20; j++) {
let cell = document.createElement("div");
cell.classList.add("cells");
///id's are used later in the project
cell.id = "index" + j + i;
cell.style.border = "1px solid black";
cell.style.height = "50px";
cell.style.width = "50px";
currentRow.appendChild(cell);
}
}
}
createGraph();
function main() {
document.querySelectorAll(".cells").forEach(item => {
["mousedown", "mouseover", "mouseup"].forEach(function(e) {
item.addEventListener(e, function() {
item.style.backgroundColor = "red";
})
})
})
}
main();
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
</html>
So in the main function I added an even listener to all the cells and I am trying to change their color to red. The problem is that the mouseover event takes over the mousedown which is what I want to happen first. How can I make it so the user is able to first click down on a cell then drag their mouse and keep highlighting cells and once they let go of the mouse the highlighting stops. Is there away to first execute the mousedown, then mouseover and finally the mouseup?
I refactored your code a little. Here is a simple example how you can use toggle state:
let graph = document.getElementById('container');
function createGraph() {
for (let i = 0; i < 20; i++) {
let row = document.createElement('div');
row.id = 'row' + i;
row.className = 'rows';
for (let j = 0; j < 20; j++) {
let cell = document.createElement('div');
cell.className = 'cells';
cell.id = 'index' + j + i;
row.appendChild(cell);
}
graph.appendChild(row);
}
}
createGraph();
function main() {
let canSelect = false;
document.addEventListener('mousedown', () => canSelect = true);
document.addEventListener('mouseup', () => canSelect = false);
document.querySelectorAll('.cells').forEach(item => {
['mousedown', 'mouseover'].forEach(function(e) {
item.addEventListener(e, () => {
if (!canSelect && e !== 'mousedown') return;
item.style.backgroundColor = 'red';
})
})
})
}
main();
#container {
display: flex;
}
.rows, .cells {
width: 50px;
height: 50px;
}
.cells {
border: 1px solid black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
</html>
The trick with things like this is to only add the mouseover event on mousedown to begin with. mouseover is generally an expensive event to have anyways (because it fires a lot), so you only "turn it on" when you want and remove it when you don't.
Also, if you're hooking the same event to multiple elements in the same parent, it is far better to assign the event to the parent and then check the target and act when it is one of the children you want (usually using the .matches() method).
Then, you don't have to worry about mousemove firing first, because it'll always fire second. Just be aware it'll probably fire MANY times per cell, so you need to write your code to handle that.
let targetElements = [];
const parent = document.querySelector('.parent');
const mouseoverHandler = ({ target }) => {
if (!target.matches('.parent span')
|| targetElements.includes(target)) {
return;
}
targetElements.push(target);
};
parent.addEventListener('mousedown', ({ target }) => {
// use whatever selector makes sense for your children
if (!target.matches('.parent span')) return;
// reset the list here in case they mouseup-ed outside of the parent
targetElements = [];
// turn mouseover "on"
parent.addEventListener('mouseover', mouseoverHandler);
targetElements.push(target);
console.log('mouseover on');
});
parent.addEventListener('mouseup', ({ target }) => {
// use whatever selector makes sense for your children
if (!event.target.matches('.parent span')) return;
// turn mouseover "off"
parent.removeEventListener('mouseover', mouseoverHandler);
// do something with them
targetElements.forEach(el => el.classList.toggle('on'));
console.log('mouseover off');
});
.parent {
border: 2px solid #333;
width: 150px;
display: flex;
flex-wrap: wrap;
}
.parent span {
flex: 0 0 50px;
flex-wrap: wrap;
height: 50px;
border: 1px solid #CCC;
margin: -1px;
height: 50px;
display: -block;
}
.parent span:hover {
/* doesn't seem to work in the demo window */
background: #EEC;
cursor: pointer;
}
.parent span.on {
background: #F00;
}
<div class="parent">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
I'm working on an assignment, where the user can draw inside an n*n grid. The tasks are as following:
Create a 16x16 grid as default grid upon page-load
Implement a mouseover-EventListener for the grid, that changes the background-color of cells to black
Add a reset button, that asks the user how big the new grid should be
Add 2 buttons that set the mouseover-EventListener (default black) to a different color. First button changes the color to yellow, second button to gray.
My problem:
I'm stuck with the last task. The 2 buttons work just fine. But they can be called only once. If I select yellow - it draws yellow. If I then select gray - it draws gray. After that, the button-clicks don't do anything anymore, but I can still draw in gray.
That's what I have done so far:
First, I querySelected the button-type and added an EventListener "click".
Second, in the colourHover function, a mouseover EventListener gets invoked, depending on the button's id.
Third, the EventListener-mouseover gets defined in the respective functions (grayColour(event), yellowColour(event)).
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body id="start">
<div class="container" id="grid">
</div>
<div><button type="button" class="button" id="gray">Gray Colour</button></div>
<div><button type="button" class="button" id="yellow">Yellow Colour</button></div>
<div><button type="button" id="button">Resize your grid manually.</button></div>
<script>
"use strict";
let container = document.getElementById("grid");
let n;
// creating a grid with number-input from user.
let makeGrid = function makeGrid(input) {
let c;
for (c = 0; c < (input * input); c++) {
let cell = document.createElement("div");
container.appendChild(cell).className = "squares";
};
container.style.gridTemplateColumns = `repeat(${input}, auto)`;
container.style.gridTemplateRows = `repeat(${input}, auto)`;
};
// function gets exectuted, only if a number and below 101
let numberCheck = function numberCheck() {
if ((n % n) === 0 && n <= 100) {
makeGrid(n);
};
while ((n % n) !== 0) {
alert("Please enter a number.");
n = prompt("Choose again.");
if ((n % n) === 0 && n <= 100) {
makeGrid(n);
}
};
while ((n % n) === 0 && n > 100) {
alert("The number is too high.");
n = prompt("Choose again.");
if ((n % n) === 0 && n <= 100) {
makeGrid(n);
}
else if ((n % n) !== 0) {
alert("Please enter a number");
n = prompt("Choose again");
if ((n % n) === 0 && n <= 100) {
makeGrid(n);
}
}
};
};
// default grid on first pageload
makeGrid(16);
// this function sets the hovered items colour to black on default / first pageload
let blackColor = function blackColor(event) {
let colour = event.target;
if (colour.className === "container") {
return;
}
else if (colour.className === "squares") {
colour.style.backgroundColor = "black";
};
};
// addEventListener for blackColor function
let hoverItems = document.querySelectorAll(".container");
hoverItems.forEach(element => { element.addEventListener("mouseover", blackColor)
});
// function to manual selecting a grid-size. Beforehand, old grid gets deleted
let removeElements = function removeElements(event) {
let elements = document.getElementsByClassName("squares");
while (elements.length > 0) {
elements[0].parentNode.removeChild(elements[0]);
};
n = prompt("Choose the size of your grid");
numberCheck(n);
};
// button for selecting a grid-size manually
let button = document.querySelector("#button");
button.addEventListener("click", removeElements);
// this function sets the background-color of the cells on mouseover to gray
let grayColour = function grayColour(event) {
let colour = event.target;
if (colour.className === "container") {
return;
}
else if (colour.className === "squares") {
colour.style.backgroundColor = "gray"
}
}
// this function sets the background-color of the cells on mouseover to yellow
let yellowColour = function yellowColour(event) {
let colour = event.target;
if (colour.className === "container") {
return;
}
else if (colour.className === "squares") {
colour.style.backgroundColor = "yellow";
}
}
let colourHover = function colourHover(event) {
let hover = document.querySelectorAll(".container");
switch (event.target.id) {
case "gray":
//hover.forEach(element => { element.removeEventListener("mouseover", yellowColour)
//});
//hover.forEach(element => { element.removeEventListener("mouseover", grayColour)
//});
hover.forEach(element => { element.addEventListener("mouseover", grayColour)
});
break;
case "yellow":
//hover.forEach(element => { element.removeEventListener("mouseover", yellowColour)
//});
//hover.forEach(element => { element.removeEventListener("mouseover", grayColour)
//});
hover.forEach(element => { element.addEventListener("mouseover", yellowColour)
});
break;
};
};
let colourBtn = document.querySelectorAll(".button");
colourBtn.forEach(element => { element.addEventListener("click", colourHover)
});
</script>
</body>
</html>
I appreciate any hint in the right direction. Really stuck right now.
The simplest way is to use CSS classes for styling the cells, and change the class of the table body in a button click handler. The state of the "widget" should be stored in a JS variable, that way you can avoid unnecessary DOM traversing on each click of the buttons. Something like this:
const buttons = document.querySelectorAll('button'),
table = document.querySelector('.hovered-colors');
// The state of the widget
let currentColor = 'black';
buttons.forEach(button => {
button.addEventListener('click', e => {
const newColor = e.target.getAttribute('data-color');
table.classList.remove(currentColor);
table.classList.add(newColor);
currentColor = newColor;
});
});
.black td:hover {
color: white;
background-color: black;
}
.gray td:hover {
color: black;
background-color: gray;
}
.yellow td:hover {
color: black;
background-color: yellow;
}
<table>
<tbody class="hovered-colors black">
<tr><td>R1C1</td><td>R1C2</td></tr>
<tr><td>R2C1</td><td>R2C2</td></tr>
<tr><td>R3C1</td><td>R3C2</td></tr>
</tbody>
</table>
<button data-color="gray">Gray</button>
<button data-color="yellow">Yellow</button>
I use jQuery.click to handle the mouse click event on Raphael graph, meanwhile, I need to handle mouse drag event, mouse drag consists of mousedown, mouseupand mousemove in Raphael.
It is difficult to distinguish click and drag because click also contain mousedown & mouseup, How can I distinguish mouse "click" & mouse "drag" then in Javascript?
I think the difference is that there is a mousemove between mousedown and mouseup in a drag, but not in a click.
You can do something like this:
const element = document.createElement('div')
element.innerHTML = 'test'
document.body.appendChild(element)
let moved
let downListener = () => {
moved = false
}
element.addEventListener('mousedown', downListener)
let moveListener = () => {
moved = true
}
element.addEventListener('mousemove', moveListener)
let upListener = () => {
if (moved) {
console.log('moved')
} else {
console.log('not moved')
}
}
element.addEventListener('mouseup', upListener)
// release memory
element.removeEventListener('mousedown', downListener)
element.removeEventListener('mousemove', moveListener)
element.removeEventListener('mouseup', upListener)
All these solutions either break on tiny mouse movements, or are overcomplicated.
Here is a simple adaptable solution using two event listeners. Delta is the distance in pixels that you must move horizontally or vertically between the up and down events for the code to classify it as a drag rather than a click. This is because sometimes you will move the mouse or your finger a few pixels before lifting it.
const delta = 6;
let startX;
let startY;
element.addEventListener('mousedown', function (event) {
startX = event.pageX;
startY = event.pageY;
});
element.addEventListener('mouseup', function (event) {
const diffX = Math.abs(event.pageX - startX);
const diffY = Math.abs(event.pageY - startY);
if (diffX < delta && diffY < delta) {
// Click!
}
});
Cleaner ES2015
let drag = false;
document.addEventListener('mousedown', () => drag = false);
document.addEventListener('mousemove', () => drag = true);
document.addEventListener('mouseup', () => console.log(drag ? 'drag' : 'click'));
Didn't experience any bugs, as others comment.
In case you are already using jQuery:
var $body = $('body');
$body.on('mousedown', function (evt) {
$body.on('mouseup mousemove', function handler(evt) {
if (evt.type === 'mouseup') {
// click
} else {
// drag
}
$body.off('mouseup mousemove', handler);
});
});
This should work well. Similar to the accepted answer (though using jQuery), but the isDragging flag is only reset if the new mouse position differs from that on mousedown event. Unlike the accepted answer, that works on recent versions of Chrome, where mousemove is fired regardless of whether mouse was moved or not.
var isDragging = false;
var startingPos = [];
$(".selector")
.mousedown(function (evt) {
isDragging = false;
startingPos = [evt.pageX, evt.pageY];
})
.mousemove(function (evt) {
if (!(evt.pageX === startingPos[0] && evt.pageY === startingPos[1])) {
isDragging = true;
}
})
.mouseup(function () {
if (isDragging) {
console.log("Drag");
} else {
console.log("Click");
}
isDragging = false;
startingPos = [];
});
You may also adjust the coordinate check in mousemove if you want to add a little bit of tolerance (i.e. treat tiny movements as clicks, not drags).
If you feel like using Rxjs:
var element = document;
Rx.Observable
.merge(
Rx.Observable.fromEvent(element, 'mousedown').mapTo(0),
Rx.Observable.fromEvent(element, 'mousemove').mapTo(1)
)
.sample(Rx.Observable.fromEvent(element, 'mouseup'))
.subscribe(flag => {
console.clear();
console.log(flag ? "drag" : "click");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/#reactivex/rxjs#5.4.1/dist/global/Rx.js"></script>
This is a direct clone of what #wong2 did in his answer, but converted to RxJs.
Also interesting use of sample. The sample operator will take the latest value from the source (the merge of mousedown and mousemove) and emit it when the inner observable (mouseup) emits.
As mrjrdnthms points out in his comment on the accepted answer, this no longer works on Chrome (it always fires the mousemove), I've adapted Gustavo's answer (since I'm using jQuery) to address the Chrome behavior.
var currentPos = [];
$(document).on('mousedown', function (evt) {
currentPos = [evt.pageX, evt.pageY]
$(document).on('mousemove', function handler(evt) {
currentPos=[evt.pageX, evt.pageY];
$(document).off('mousemove', handler);
});
$(document).on('mouseup', function handler(evt) {
if([evt.pageX, evt.pageY].equals(currentPos))
console.log("Click")
else
console.log("Drag")
$(document).off('mouseup', handler);
});
});
The Array.prototype.equals function comes from this answer
Using jQuery with a 5 pixel x/y theshold to detect the drag:
var dragging = false;
$("body").on("mousedown", function(e) {
var x = e.screenX;
var y = e.screenY;
dragging = false;
$("body").on("mousemove", function(e) {
if (Math.abs(x - e.screenX) > 5 || Math.abs(y - e.screenY) > 5) {
dragging = true;
}
});
});
$("body").on("mouseup", function(e) {
$("body").off("mousemove");
console.log(dragging ? "drag" : "click");
});
You could do this:
var div = document.getElementById("div");
div.addEventListener("mousedown", function() {
window.addEventListener("mousemove", drag);
window.addEventListener("mouseup", lift);
var didDrag = false;
function drag() {
//when the person drags their mouse while holding the mouse button down
didDrag = true;
div.innerHTML = "drag"
}
function lift() {
//when the person lifts mouse
if (!didDrag) {
//if the person didn't drag
div.innerHTML = "click";
} else div.innerHTML = "drag";
//delete event listeners so that it doesn't keep saying drag
window.removeEventListener("mousemove", drag)
window.removeEventListener("mouseup", this)
}
})
body {
outline: none;
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
overflow: hidden;
}
#div {
/* calculating -5px for each side of border in case border-box doesn't work */
width: calc(100vw - 10px);
height: calc(100vh - 10px);
border: 5px solid orange;
background-color: yellow;
font-weight: 700;
display: grid;
place-items: center;
user-select: none;
cursor: pointer;
padding: 0;
margin: 0;
}
<html>
<body>
<div id="div">Click me or drag me.</div>
</body>
</html>
Had the same problem recently with a tree list where the user can either click on the item or drag it, made this small Pointer class and put it in my utils.js
function Pointer(threshold = 10) {
let x = 0;
let y = 0;
return {
start(e) {
x = e.clientX;
y = e.clientY;
},
isClick(e) {
const deltaX = Math.abs(e.clientX - x);
const deltaY = Math.abs(e.clientY - y);
return deltaX < threshold && deltaY < threshold;
}
}
}
Here you can see it at work:
function Pointer(threshold = 10) {
let x = 0;
let y = 0;
return {
start(e) {
x = e.clientX;
y = e.clientY;
},
isClick(e) {
const deltaX = Math.abs(e.clientX - x);
const deltaY = Math.abs(e.clientY - y);
return deltaX < threshold && deltaY < threshold;
}
}
}
const pointer = new Pointer();
window.addEventListener('mousedown', (e) => pointer.start(e))
//window.addEventListener('mousemove', (e) => pointer.last(e))
window.addEventListener('mouseup', (e) => {
const operation = pointer.isClick(e)
? "Click"
: "Drag"
console.log(operation)
})
It's really this simple
var dragged = false
window.addEventListener('mousedown', function () { dragged = false })
window.addEventListener('mousemove', function () { dragged = true })
window.addEventListener('mouseup', function() {
if (dragged == true) { return }
console.log("CLICK!! ")
})
You honestly do not want to add a threshold allowing a small movement. The above is the correct, normal, feel of clicking on all desktop interfaces.
Just try it.
You can easily add an event if you like.
If just to filter out the drag case, do it like this:
var moved = false;
$(selector)
.mousedown(function() {moved = false;})
.mousemove(function() {moved = true;})
.mouseup(function(event) {
if (!moved) {
// clicked without moving mouse
}
});
Another solution for class based vanilla JS using a distance threshold
private initDetectDrag(element) {
let clickOrigin = { x: 0, y: 0 };
const dragDistanceThreshhold = 20;
element.addEventListener('mousedown', (event) => {
this.isDragged = false
clickOrigin = { x: event.clientX, y: event.clientY };
});
element.addEventListener('mousemove', (event) => {
if (Math.sqrt(Math.pow(clickOrigin.y - event.clientY, 2) + Math.pow(clickOrigin.x - event.clientX, 2)) > dragDistanceThreshhold) {
this.isDragged = true
}
});
}
Add inside the class (SOMESLIDER_ELEMENT can also be document to be global):
private isDragged: boolean;
constructor() {
this.initDetectDrag(SOMESLIDER_ELEMENT);
this.doSomeSlideStuff(SOMESLIDER_ELEMENT);
element.addEventListener('click', (event) => {
if (!this.sliderIsDragged) {
console.log('was clicked');
} else {
console.log('was dragged, ignore click or handle this');
}
}, false);
}
Pure JS with DeltaX and DeltaY
This DeltaX and DeltaY as suggested by a comment in the accepted answer to avoid the frustrating experience when trying to click and get a drag operation instead due to a one tick mousemove.
deltaX = deltaY = 2;//px
var element = document.getElementById('divID');
element.addEventListener("mousedown", function(e){
if (typeof InitPageX == 'undefined' && typeof InitPageY == 'undefined') {
InitPageX = e.pageX;
InitPageY = e.pageY;
}
}, false);
element.addEventListener("mousemove", function(e){
if (typeof InitPageX !== 'undefined' && typeof InitPageY !== 'undefined') {
diffX = e.pageX - InitPageX;
diffY = e.pageY - InitPageY;
if ( (diffX > deltaX) || (diffX < -deltaX)
||
(diffY > deltaY) || (diffY < -deltaY)
) {
console.log("dragging");//dragging event or function goes here.
}
else {
console.log("click");//click event or moving back in delta goes here.
}
}
}, false);
element.addEventListener("mouseup", function(){
delete InitPageX;
delete InitPageY;
}, false);
element.addEventListener("click", function(){
console.log("click");
}, false);
For a public action on an OSM map (position a marker on click) the question was: 1) how to determine the duration of mouse down->up (you can't imagine creating a new marker for each click) and 2) did the mouse move during down->up (i.e user is dragging the map).
const map = document.getElementById('map');
map.addEventListener("mousedown", position);
map.addEventListener("mouseup", calculate);
let posX, posY, endX, endY, t1, t2, action;
function position(e) {
posX = e.clientX;
posY = e.clientY;
t1 = Date.now();
}
function calculate(e) {
endX = e.clientX;
endY = e.clientY;
t2 = (Date.now()-t1)/1000;
action = 'inactive';
if( t2 > 0.5 && t2 < 1.5) { // Fixing duration of mouse down->up
if( Math.abs( posX-endX ) < 5 && Math.abs( posY-endY ) < 5 ) { // 5px error on mouse pos while clicking
action = 'active';
// --------> Do something
}
}
console.log('Down = '+posX + ', ' + posY+'\nUp = '+endX + ', ' + endY+ '\nAction = '+ action);
}
Based on this answer, I did this in my React component:
export default React.memo(() => {
const containerRef = React.useRef(null);
React.useEffect(() => {
document.addEventListener('mousedown', handleMouseMove);
return () => document.removeEventListener('mousedown', handleMouseMove);
}, []);
const handleMouseMove = React.useCallback(() => {
const drag = (e) => {
console.log('mouse is moving');
};
const lift = (e) => {
console.log('mouse move ended');
window.removeEventListener('mousemove', drag);
window.removeEventListener('mouseup', this);
};
window.addEventListener('mousemove', drag);
window.addEventListener('mouseup', lift);
}, []);
return (
<div style={{ width: '100vw', height: '100vh' }} ref={containerRef} />
);
})
If you want check the click or drag behavior of a specific element you can do this without having to listen to the body.
$(document).ready(function(){
let click;
$('.owl-carousel').owlCarousel({
items: 1
});
// prevent clicks when sliding
$('.btn')
.on('mousemove', function(){
click = false;
})
.on('mousedown', function(){
click = true;
});
// change mouseup listener to '.content' to listen to a wider area. (mouse drag release could happen out of the '.btn' which we have not listent to). Note that the click will trigger if '.btn' mousedown event is triggered above
$('.btn').on('mouseup', function(){
if(click){
$('.result').text('clicked');
} else {
$('.result').text('dragged');
}
});
});
.content{
position: relative;
width: 500px;
height: 400px;
background: #f2f2f2;
}
.slider, .result{
position: relative;
width: 400px;
}
.slider{
height: 200px;
margin: 0 auto;
top: 30px;
}
.btn{
display: flex;
align-items: center;
justify-content: center;
text-align: center;
height: 100px;
background: #c66;
}
.result{
height: 30px;
top: 10px;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/owl.carousel.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.carousel.min.css" />
<div class="content">
<div class="slider">
<div class="owl-carousel owl-theme">
<div class="item">
click me without moving the mouse
</div>
<div class="item">
click me without moving the mouse
</div>
</div>
<div class="result"></div>
</div>
</div>
from #Przemek 's answer,
function listenClickOnly(element, callback, threshold=10) {
let drag = 0;
element.addEventListener('mousedown', () => drag = 0);
element.addEventListener('mousemove', () => drag++);
element.addEventListener('mouseup', e => {
if (drag<threshold) callback(e);
});
}
listenClickOnly(
document,
() => console.log('click'),
10
);
The following coding is to detect the movement of mouseup and mousedown.
It shall work for most of the cases. It also depends
on how you treat mouseevent as Click.
In JavaScript, the detection is very simple. It does not concern how
long you press or movement between the mousedown and mouseup.
Event.detail would not reset to 1 when your mouse is moved between
the mousedown and mouseup.
If you need to differentiate the click and long press, you need to
check the difference in event.timeStamp too.
// ==== add the code at the begining of your coding ====
let clickStatus = 0;
(() => {
let screenX, screenY;
document.addEventListener('mousedown', (event) => ({screenX, screenY} = event), true);
document.addEventListener('mouseup', (event) => (clickStatus = Math.abs(event.screenX - screenX) + Math.abs(event.screenY - screenY) < 3), true);
})();
// ==== add the code at the begining of your coding ====
$("#draggable").click(function(event) {
if (clickStatus) {
console.log(`click event is valid, click count: ${event.detail}`)
} else {
console.log(`click event is invalid`)
}
})
<!doctype html>
<html lang="en">
<!-- coding example from https://jqueryui.com/draggable/ -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Draggable - Default functionality</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<style>
#draggable { width: 150px; height: 150px; padding: 0.5em; }
</style>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$( function() {
$( "#draggable" ).draggable();
} );
</script>
</head>
<body>
<div id="draggable" class="ui-widget-content">
<p>Drag me around</p>
</div>
</body>
</html>
Is very easy,
el = document.getElementById("your_id");
var isDown = false;
el.addEventListener('mousedown', function () {
isDown = true;
});
el.addEventListener('mouseup', function () {
isDown = false;
});
el.addEventListener('mousemove', function () {
if (isDown) {
// your code goes here
}
});