How to make mouseup fire anyehere? - javascript

I have a drag and drop script that is relatively functional. However, I want to be able to trigger mouseup anywhere on the screen. Is there a way to trigger mouseup outside of the window, or outside of the current element? I know this is possible and I've seen other questions like this. I wanted to find a way in vanilla Javascript to detect mouseups like this.
document.onmousemove = mouseCoords;
var x = 0;
var y = 0;
var cl1= false;
var divid;
var offs1;
var offs2;
var topPos;
var leftPos;
function mouseCoords(e) {
x = e.x
y = e.y
if(cl1 === true){
document.getElementById(divid).style.top = topPos + (y-offs1) + 'px';
document.getElementById(divid).style.left = leftPos + (x-offs2) + 'px';
}
}
var drag = function(i, cas) {
divid= i
switch(cas){
case 1:
var rect = document.getElementById(divid).getBoundingClientRect();
leftPos = rect.left;
topPos = rect.top;
offs1 = y;
offs2 = x;
cl1= true;
break;
case 0:
offs1 = 0;
offs2 = 0;
cl1= false;
break;
}
}
#block{
width: 100px; z-index: 20; height: 50px; background-color: blue; position: fixed; user-select: none; -webkit-user-select: none;
}
.drag{
width: 200px; height: 100px; background-color: red; position: fixed;
}
<div id="block">mouseup doesn't trigger over me!</div>
<div id="1" class="drag" onmousedown="drag(1, 1)" onmouseup="drag(1, 0)"></div>

Use
document.addEventListener("mouseup", drag(null, 0));
for mouseup,
and this code for mousedown.
document.addEventListener("mousedown", drag(null, 1));
Basically, document.addEventListener works for the whole window. "mouseup" tells the script that the event is a mouseup, and the final bit is the function to be executed (drag(1, 0))

Related

What causes the glitch in getBoundingClientRect()?

I am struggling with a glitch caused by getBoundingClientRect() method. (see fiddle below). The goal is to make a bar following a cursor inside a container. The aforementioned method does not return valid results. I am a beginner in terms of JS - there is most probably an obvious reason behind this. I just can't find the anwswer.
https://jsfiddle.net/aveoL210/3/
var div_moving = document.getElementById('div_moving');
var parent_div = 'parent_div';
var movingDiv = {
getCoords: function(e) {
var rect = e.target.getBoundingClientRect();
var y_pos = rect.top;
console.log(y_pos);
var y = e.pageY;
y = y - y_pos;
return (y);
}
};
document.getElementById(parent_div).addEventListener('mousemove', function(e){
result = movingDiv.getCoords(e);
div_moving.style.top = result +'px';
div_moving.style.display = "initial";
});
document.getElementById(parent_div).addEventListener('mouseleave', function(){
div_moving.style.display = "none";
});
The target when moving the mouse down will alternate between the moving and parent div
while adding
if(e.target.id !== 'parent_div') return;
guard to the getCoords function fixes it a little, it's still glitchy
The better solution is to get the rect of the parent_div, regardless of the e.target
So .. try this
var div_moving = document.getElementById('div_moving');
var parent_div = document.getElementById('parent_div')
var movingDiv = {
getCoords: function(e) {
var rect = parent_div.getBoundingClientRect();
var y_pos = rect.top;
var y = e.pageY;
y = y - y_pos;
return (y);
}
};
parent_div.addEventListener('mousemove', function(e) {
result = movingDiv.getCoords(e);
div_moving.style.top = result + 'px';
div_moving.style.display = "initial";
});
parent_div.addEventListener('mouseleave', function() {
div_moving.style.display = "none";
});
#parent_div {
position: relative;
width: 50%;
height: 300px;
margin: 1em auto;
border: 1px solid #333;
background: #f0f0f0;
}
#div_moving {
display: none;
position: absolute;
width: 100%;
height: 5px;
margin: 0;
background: blue;
}
<div id="parent_div">
<div id="div_moving"></div>
</div>
In getCoords you want to get parent_div all the time, so you have to use e.currentTarget instead of e.target otherwise, when div_moving is under the cursor e.target return div_moving and all calculation goes wrong, it will move to top and when you move your mouse again all wrong things repeat.
var div_moving = document.getElementById('div_moving');
var parent_div = 'parent_div';
var movingDiv = {
getCoords: function(e) {
console.log(e.target.id)
var rect = e.currentTarget.getBoundingClientRect();
var y_pos = rect.top;
console.log(y_pos);
var y = e.pageY;
y = y - y_pos;
return (y);
}
};
document.getElementById(parent_div).addEventListener('mousemove', function(e){
result = movingDiv.getCoords(e);
div_moving.style.top = result +'px';
div_moving.style.display = "initial";
});
document.getElementById(parent_div).addEventListener('mouseleave', function(){
div_moving.style.display = "none";
});
The, what you called "glitch", is actually what is expected to happen. Let me tell you why:
The line e.target.getBoundingClientRect() is the source of the issue, precisely e.target.
The, so called glitch, happens when the mouse is on top of the blue line element and at this point e.target no longer points to your #parent_div and instead e.target is #div_moving.
A quick fix would be by caching #parent_div in a variable so can use it later on, and on the getCoords() method we simply replace e.target by that new variable.
Here's a live demo:
var parent_div = document.getElementById('parent_div');
var div_moving = document.getElementById('div_moving');
var movingDiv = {
getCoords: function(e) {
var rect = parent_div.getBoundingClientRect();
var y_pos = rect.top;
//console.log(y_pos);
var y = e.pageY;
y = y - y_pos;
return (y);
}
};
parent_div.addEventListener('mousemove', function(e) {
result = movingDiv.getCoords(e);
div_moving.style.top = result + 'px';
div_moving.style.display = "initial";
});
parent_div.addEventListener('mouseleave', function() {
div_moving.style.display = "none";
});
#parent_div {
position: relative;
width: 50%;
height: 300px;
margin: 1em auto;
border: 1px solid #333;
background: #f0f0f0;
}
#div_moving {
display: none;
position: absolute;
width: 100%;
height: 5px;
margin: 0;
background: blue;
}
<div id="parent_div">
<div id="div_moving"></div>
</div>
DISCLAIMAIR: The above demo did not change a lot from the OP's original code which, by the way, can be hugely improved which is out of the scope of my answer.

Mouse dragging an element

I've been waiting to ask this question for a long time, but couldn't, because I knew I would get bad reputation. This post was very hard to post, but I REALLY need this code...
Let's say there was a draggable element with the ID of "dragme"... You have to drag and drop the element to a specific spot. I was wondering if there is a code that does this task automatically for me when I execute a function. Lets name that function "dropElement". I am trying to drag "dragme" to my mouse position with a "dragElement" function with jquery or js.
This is what I tried:
(function() {
'use strict';
var mouseX = 0;
var mouseY = 0;
var timer = 0;
//tracks mouse position
document.body.addEventListener("mousemove", function(e) {mouseX = e.clientX; mouseY = e.clientY;});
function dropElement() {
$("#dragme").trigger($.Event("mousedown", {button: 0}));
$("body").trigger($.Event("mouseup", {button: 0, clientX: mouseX, clientY: mouseY}));
timer = setTimeout(drop, 100);
}
dropElement() //executes function and drops "dragme" to mouse position
I found the code in the question a bit complex to follow, especially with a timing function.
Instead I've gone back to basics (and vanilla JS) to think about the sequence of events. The user moves the mouse, we aren't interested unless they have put the mousedown within the element we want to drag. So this snippet sets a variable isDown which is set to true when the user puts the mouse down on the element.
Then it looks for a mousemove event on the whole window and if isDown is set it moves the element.
We also look for the mouseup event on the window and unset isDown.
The reason for looking for some events on the actual element and some on the window is because things are moving - the mouse may get out of the window before it is released for example.
let isDown = false;
const dragMe = document.querySelector('.dragme');
dragMe.addEventListener('mousedown', function() {
isDown = true;
});
window.addEventListener('mouseup', function() {
isDown = false;
});
window.addEventListener('mousemove', function() {
if (isDown) {
dragMe.style.top = event.clientY + 'px';
dragMe.style.left = event.clientX + 'px';
}
});
.dragme {
width: 5em;
height: 5em;
background-color: cyan;
position: relative;
top: 0;
left: 0;
}
<div class="dragme">Drag me</div>
I hope this sample helps you
var drag = {
elem: null,
x: 0,
y: 0,
state: false
};
var delta = {
x: 0,
y: 0
};
function dropElement(e){
var cur_offset = $("#autoDrag").offset();
$("#autoDrag").animate({
left: (e.pageX),
top: (e.pageY )
});
}
$(document).mousedown(function(e) {
dropElement(e);
})
$("#dragMe").mousedown(function(e) {
drag.elem = dragMe;
drag.x = e.pageX;
drag.y = e.pageY;
drag.state = true;
})
$(document).mousemove(function(e) {
if ( drag.state) {
delta.x = e.pageX - drag.x;
delta.y = e.pageY - drag.y;
var cur_offset = $(drag.elem).offset();
$(drag.elem).offset({
left: (cur_offset.left + delta.x),
top: (cur_offset.top + delta.y)
});
drag.x = e.pageX;
drag.y = e.pageY;
}
})
$("#dragMe").mouseup(function() {
drag.state = false;
})
#dragMe {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
width: 80px;
height: 80px;
padding:10px;
background-color: #00a1ff;
color: white;
border-radius: 50px;
}
#autoDrag {
position: absolute;
right:0;
display: flex;
justify-content: center;
align-items: center;
text-align:center;
width: 80px;
height: 80px;
padding:10px;
background-color: #ff00ff;
color: white;
border-radius: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="dragMe">DragMe!</span>
<span id="autoDrag">Click somewhere I will be there!</span>

Style drag ghost element

I am facing an issue, where I am dragging a div.
While the ghost element looks good on MacOs(yes both on Chrome and FireFox),it appears to be too transparent,in Windows (yes both on Chrome and FireFox.
I tried multiple approaches but nothing seems to work.
So is it possible to style the ghost element?
Also, I tried to make an image of that element on the go, and use it as ghost dragging image, but the transparency issue still remains.
You can do this by implementing dragging of the element yourself in JavaScript. That way, you can apply a CSS class to the element while it is being dragged, which styles it in any way you wish.
const d = 'dragging';
const container = document.getElementById('container');
const el = document.getElementById('drag');
var cOffX = 0;
var cOffY = 0;
el.addEventListener('mousedown', dragStart);
function dragStart(e) {
e = e || window.event;
e.preventDefault();
cOffX = e.clientX - el.offsetLeft;
cOffY = e.clientY - el.offsetTop;
document.addEventListener('mousemove', dragMove);
document.addEventListener('mouseup', dragEnd);
el.classList.add(d);
container.style.cursor = 'move';
};
function dragMove(e) {
e = e || window.event;
e.preventDefault();
el.style.top = (e.clientY - cOffY).toString() + 'px';
el.style.left = (e.clientX - cOffX).toString() + 'px';
};
function dragEnd(e) {
e = e || window.event;
e.preventDefault();
document.removeEventListener('mousemove', dragMove);
document.removeEventListener('mouseup', dragEnd);
el.classList.remove(d);
container.style.cursor = null;
};
#container {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
}
#drag {
position: absolute;
height: 100px;
width: 100px;
background-color: lime;
border-radius: 0;
transition: background-color 0.25s, border-radius 0.25s;
cursor: move;
}
#drag.dragging {
background-color: navy;
border-radius: 50%;
}
<div id="container">
<div id="drag"></div>
</div>
As others have said, the ghosting is browser-based and can't be changed, so it seems you need your own solution if you want to get around that.

get jquery touch position every x milliseconds

is there a way to get the touch position in a touchmove event every x milliseconds and then execute a function, when the x-coordinate at the moment and the one at the start are differing e.g. 50px?
Thanks
Try the below ;
$('document').ready(function() {
var touch,
action,
diffX,
diffY,
endX,
endY,
startX,
startY,
timer,
timerXseconds = 500, // Change to the Time(milliseconds) to check for touch position
xDifferenceX = 50, // Change to difference (px) for x-coordinates from starting point to run your function
xDifferenceY = 50; // Change to difference (px) for y-coordinates from starting point
function getCoord(e, c) {
return /touch/.test(e.type) ? (e.originalEvent || e).changedTouches[0]['page' + c] : e['page' + c];
}
function testTouch(e) {
if (e.type == 'touchstart') {
touch = true;
} else if (touch) {
touch = false;
return false;
}
return true;
}
function onStart(ev) {
if (testTouch(ev) && !action) {
action = true;
startX = getCoord(ev, 'X');
startY = getCoord(ev, 'Y');
diffX = 0;
diffY = 0;
timer = window.setInterval(checkPosition(ev), timerXseconds); // get coordinaties ever X time
if (ev.type == 'mousedown') {
$(document).on('mousemove', onMove).on('mouseup', onEnd);
}
}
}
function onMove(ev) {
if (action) {
checkPosition(ev)
}
}
function checkPosition(ev) {
endX = getCoord(ev, 'X');
endY = getCoord(ev, 'Y');
diffX = endX - startX;
diffY = endY - startY;
// Check if coordinates on Move are Different than Starting point by X pixels
if (Math.abs(diffX) > xDifferenceX || Math.abs(diffY) > xDifferenceY) {
// console.log('Start is :' + startX + ' End is : ' + endX + 'Difference is : ' + diffX);
$(this).trigger('touchend');
// here Add your function to run...
}
}
function onEnd(ev) {
window.clearInterval(timer);
if (action) {
action = false;
if (ev.type == 'mouseup') {
$(document).off('mousemove', onMove).off('mouseup', onEnd);
}
}
}
$('#monitor')
.bind('touchstart mousedown', onStart)
.bind('touchmove', onMove)
.bind('touchend touchcancel', onEnd);
});
body {
margin: 0;
padding: 0;
}
#monitor {
height: 500px;
width: 500px;
position: relative;
display: block;
left: 50px;
top: 50px;
background: green;
}
.box {
position: absolute;
top: 0;
left: 0;
right: 0;
text-align: center;
font-weight: bold;
bottom: 0;
background: white;
width: 50px;
height: 50px;
margin: auto;
font-size: 16px;
line-height: 23px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='monitor'>
<div class='box'>start here</div>
</div>
Read this post for a more detailed answer
This can be done in a few functions.
The first function is called when there is a movement of the touch event, this event stores the x and y of the touch in a separate variable.
Then we have a function that runs every X miliseconds, this function gets the x and y from the move event and dispatches then to your code.
Functions 3, 4 and 5 are used to handle the start, stop and cancel dragevents, and start/stop the second function:
var timerid;
var x;
var y;
var tick = 0;
function handleStart(evt) {
console.log("handleStart");
evt.preventDefault();
timerid = window.setInterval(timer, 50); // Replace 50 here with X
}
function handleEnd(evt) {
console.log("handleEnd");
evt.preventDefault();
window.clearInterval(timerid);
}
function handleCancel(evt) {
console.log("handleCancel");
evt.preventDefault();
window.clearInterval(timerid);
}
function handleMove(evt) {
console.log("handleMove");
evt.preventDefault();
// Select last point:
var point = evt.changedTouches[evt.changedTouches.length - 1];
x = point.pageX;
y = point.pageY;
}
function timer() {
console.log("timer");
tick++;
document.getElementById("output").innerHTML = "tick: " + tick + " x: " + x + " y:" + y;
}
var el = document.getElementById("canvas");
el.addEventListener("touchstart", handleStart, false);
el.addEventListener("touchend", handleEnd, false);
el.addEventListener("touchcancel", handleCancel, false);
el.addEventListener("touchmove", handleMove, false);
<canvas id="canvas" width="300" height="300" style="border:solid black 1px;"></canvas>
<p id=output></p>
As long as the user is pressing the screen, the code will print out the x and the y coordinate to the screen. You can also integrate the reading of the x and y into your existing game loop instead of having a separate function if that is needed for your project.
Take a look at hammer.js, it has exactly what you need. It supports "touchmove" called pan, that is being called every few milliseconds when you pan. Also there is a threshold property which determine a length in pixels you have to pan before recognizing it as a pan.

Moving a image in jQuery (image crop)

My code is working fine, but Im getting a few problems. The first problem regards to the browsers ability to drag images around, when it happens a "stop signal" appears, and it breaks the code. Sometimes the signal appears (firefox), sometimes not. I dont know why. The second problem regards to the text outside the div. When the user drag the image, the text outside gets selected. Who can I solve it?
If you run the code, you need a 140px width image.
The code:
<div style="position: relative; height: 100px; width: 100px; overflow: hidden;" class="img-profile">
<div id="crop" style="position: absolute; width: 140px; left: -20px; height: 140px; top: 0px; background: url(/image/user/teste.jpg) no-repeat; cursor: move;"></div>
</div>
var x = 0;
var y = 0;
$(document).ready(function () {
$("#crop").mousedown(function () {
var crop = $(this);
$(document).mousemove(function (e) {
var x_movement = 0;
var y_movement = 0;
if (x == e.pageX || x == 0) {
x = e.pageX;
} else {
x_movement = e.pageX - x;
x = e.pageX;
}
if (y == e.pageY || y == 0) {
y = e.pageY;
} else {
y_movement = e.pageY - y;
y = e.pageY;
}
var left = parseFloat(crop.css("left")) + x_movement;
var min_left = 0;
var max_left = -40;
if (left >= min_left) left = min_left;
if (left <= max_left) left = max_left;
crop.css("left", left);
var top = parseFloat(crop.css("top")) + y_movement;
var min_top = 0;
var max_top = (parseFloat(crop.css("height")) - 100) * -1;
if (top >= min_top) top = min_top;
if (top <= max_top) top = max_top;
crop.css("top", top);
});
});
$(document).mouseup(function () {
x = 0;
y = 0;
$(document).unbind("mousemove");
});
});
Just noted that changing the crop div to a input solved both problems.
<input type="button" id="crop" style="position: absolute; width: 140px; left: -20px; height: 140px; top: 0px; background: url(/image/user/teste.jpg) no-repeat; cursor: move; border: 0px;" />

Categories

Resources