JavaScript how to check drag direction - javascript

I am trying to monitor dragStart and dragEvent javascript, in order to conclude its direction, UP or DOWN.
However i could not get any detail in arguments passed by the event -- that help to conclude.
Is there any better way to check drag direction , up or down?
Note:
my problem is specifically happening at mojo javascript at webos
Thanks,
-iwan

I didn't know about dragStart and dragEvent, but why not use onmousedown, onmousemove and onmouseup?
I made a modified version of http://dunnbypaul.net/js_mouse/. The direction is displayed in #status when you drag the image. Tested and works in IE5.5, IE6, IE7, IE8, Safari 5, Chrome 6 and Navigator 9. Works with Strict Doctype (probably other Doctypes also, didn't test them).
JavaScript:
var dragobj = null;
function getCurY(e) {
if (!e) e = window.event;
if (e.pageX || e.pageY)
return e.pageY;
else if (e.clientX || e.clientY)
return e.clientY + document.body.scrollTop;
}
function drag(context, e) {
dragobj = context;
document.onmousedown = function() { return false };
document.onmouseup = function() {
if (dragobj) dragobj = null;
document.getElementById('status').innerHTML = 'Direction: n/a';
}
var graby = getCurY(e);
var oriy = dragobj.offsetTop;
document.onmousemove = function(e) {
if (dragobj) {
dragobj.style.position = 'absolute';
var newy = oriy + getCurY(e) - graby;
var dir = newy > parseInt(dragobj.style.top, 10) ? 'down' : 'up';
dragobj.style.top = newy + 'px';
document.getElementById('status').innerHTML = 'Direction: ' + dir;
}
return false;
}
}
HTML:
<p onmousedown="drag(this, event)">
<img src="http://1.bp.blogspot.com/-u3FKHnFg8cA/Td56DmfliyI/AAAAAAAAAJ8/fTCFNCTs7iE/s1600/trollface%255B1%255D.jpg" alt="Trollface" />
</p>
<p id="status" style="position:absolute; top:0">Direction: n/a</p>

It won't tell you the direction, but you can get the position of the element you're dragging and figure out which direction it's going.
This might be helpful: http://dunnbypaul.net/js_mouse/.

You want to use dragOver. You could do something like this if you're only interested in vertical position:
Javascript:
<script type="text/javascript">
function getPosY(event) {
console.log(event.clientY);
}
</script>
HTML:
<body ondragover="getPosY(event)">
EDIT: Here's a jsfiddle. Make sure your js console is open.
You could have your function compare the clientY values to determine which direction the mouse is moving.

Related

Changing cursor while dragging HTML element

I know there has been numerous similiar questions on stackoverflow, I've read several of them, but none provided there answers worked in my case. I want to change cursor while dragging HTML element. I tried this:
var startX = null;
var startY = null;
var element = document.getElementById('bla');
element.addEventListener('dragstart', onDragStart, true);
element.addEventListener('dragend', onDragEnd, true);
element.addEventListener('drag', onDrag, true);
function onDragStart(e){
startX = e.screenX;
startY = e.screenY;
e.target.style.cursor = "move";
}
function onDrag(e){
e.target.style.cursor = "move";
}
function onDragEnd(e){
var style = document.defaultView.getComputedStyle(element);
var newLeft = parseInt(style.left) + e.screenX - startX;
var newTop = parseInt(style.top) + e.screenY - startY;
e.target.style.left = newLeft + 'px';
e.target.style.top = newTop + 'px';
e.target.style.cursor = "default";
}
But it doesn't work. I have no idea why on earth e.target.style.cursor = "move" doesn't work. I tried changing it to document.body.style.cursor = "move", but it doesn't work either. Any help with solving this problem with explanation why my code doesn't work will be greatly appreciated.
JS Fiddle link: https://jsfiddle.net/4w20xxvp/59/
Ps. I'm looking for pure JS solution, no JQuery.
Ps2. I couldn't get answers from to work in my case. And I don't want to use custom cursor images, just standard css ones.
Try to preventDefault on the other drag events. Also, you might want to consider adding a drop target that would handle dragover events.
document.addEventListener('dragover', (e) => e.preventDefault(), true)
(Fiddle)

Draggable pop up - scroll issue

All I m using the below code snippet to make a pop draggable. the issue im facing is scroll bar is not being detected, the pop up moves instead of scroll. I did see some similar questions, but the implementation seems to be different in their case, Can you help?
$('#Div1').mousedown(function(ev) {
divToMove = document.getElementById('Div1');
var divName = '#Div1';
dragHandler(ev,divName);
});
function dragHandler(e,divName){
var offSet = $(divName).position();
dragOK = true;
dragXoffset = e.clientX - offSet.left;
dragYoffset = e.clientY - offSet.top;
$(divName).mousemove(function(ev){ moveHandler(ev) });
$(divName).mouseup(function(ev){ cleanup(ev, divName) });
return false;
}
function cleanup(e, divName) {
$(divName).mousemove = null;
$(divName).mouseup = null;
dragOK = false;
}
function moveHandler(e) {
if (e == null) { e = window.event }
if (e.button <= 1 && dragOK) {
divToMove.style.left = e.clientX - dragXoffset + 'px';
divToMove.style.top = e.clientY - dragYoffset + 'px';
return false;
}
}
Please see this example in js fiddle. The issue doesnt happen in chrome, happens only in IE and ff.
http://jsfiddle.net/6g6Xr/74/
I was wanting to comment but do not have enough points. I see you have included jQuery UI in the jsfiddle, is it possible to use its draggable component if you are using UI already? If so you could use the handle property shown here in the second part of this answer:
https://stackoverflow.com/a/8793280/2603735
jQuery UI handle reference

vertical scrolling via scrollTo is jittery on mobile devices

I have seen this question but it wasn't answered.
I have a object on a webpage that I want you to be able to drag and scroll the page. Reason behind this is that I set it up to be a swipe'able window but on some mobile devices the window takes up most of the screen. So in addition to horizontal "swiping" I want you to be able to vertically scroll the page as well.
This works great on a PC with a mouse. Everything is smooth and as expected. However, once you go to a mobile device (I have tried on Safari on an iPhone and the native browser on an Android 4 and both have the same issue) vertical scrolling is very "jittery".
At first I thought that it had to do with the fact that after you scroll the page, the next touchmove / MSPointerMove event will return a Ycord that different even though your finger might not have moved (due to the scrolling). But trying to accomidate for this didn't help.
Anyway, a demo of the whole thing can be found at http://www.leecolpi.com/NEW/m/
The full javascript can be found at http://www.leecolpi.com/NEW/m/JAVASCRIPT/slide_window.js
The relivant javascript is (might be easier to read via the link above):
function mouseMoveTrigger(evt)
{
if (!isDragging) return;
if (!touchEvents && !pointerEvents)
if (window.event) evt=window.event;
if (evt.preventDefault)
evt.preventDefault();
else
evt.returnValue = false;
var newX;
var newY;
if (touchEvents)
{
newX = offsetX - evt.changedTouches[0].pageX;
offsetX = evt.changedTouches[0].pageX;
newY = offsetY - evt.changedTouches[0].pageY;
offsetY = evt.changedTouches[0].pageY;
}
else
{
newX = offsetX - evt.clientX;
offsetX = evt.clientX;
newY = offsetY - evt.clientY;
offsetY = evt.clientY;
}
var thingsToSlide = document.getElementById("pictureFrame").getElementsByTagName("li");
newX = parseInt(thingsToSlide[0].style.right.replace(/px/g,'')) + newX;
if (newX < 0)
newX = 0;
if (newX > ((thingsToSlide[0].offsetWidth * (thingsToSlide.length - 1))) + 30)
newX = (thingsToSlide[0].offsetWidth * (thingsToSlide.length - 1)) + 30;
window.scrollBy(0, newY);
for (var i=0; i<thingsToSlide.length; i++)
thingsToSlide[i].style.right = newX + "px";
return false;
}
As you can see, all I am doing is a scrollBy of the difference of the Yvalue for the current and previous "move" events. Again, this works like a champ on a computer which is exactly where I don't care if it works or not. Only problem is every mobile device I have tried it on.
I am using preventDefault() (or setting the return value = false if I can't do that), but could I be triggering another event and not knowing it? I tried with my init to only listen for certian events. Here is my init function (might be easier to read via the link above):
function initSlider()
{
var pageBody = document.getElementsByTagName("body")[0];
var thingsToSlide = document.getElementById("pictureFrame");
if (thingsToSlide)
{
var thingsToSlideList = document.getElementById("pictureFrame").getElementsByTagName("li");
for (var i=0; i<thingsToSlideList.length; i++)
thingsToSlideList[i].style.right = "0px";
if (touchEvents)
{
thingsToSlide.addEventListener("touchstart", onTouchStart, false);
}
else if (pointerEvents)
{
thingsToSlide.addEventListener("MSPointerDown", onTouchStart, false);
}
else
{
thingsToSlide.ondrag=function() { return false; };
thingsToSlide.onselectstart=function() { return false; };
thingsToSlide.onmousedown=function(event) { mouseDownTrigger(this,event); };
}
if (touchEvents)
{
pageBody.addEventListener("touchmove", mouseMoveTrigger, false);
pageBody.addEventListener("touchend", mouseUpTrigger, false);
pageBody.addEventListener("touchcancle", mouseUpTrigger, false);
}
else if (pointerEvents)
{
pageBody.addEventListener("MSPointerMove", mouseMoveTrigger, false);
pageBody.addEventListener("MSPointerUp", mouseUpTrigger, false);
pageBody.addEventListener("MSPointerCancel", mouseUpTrigger, false);
}
else
{
document.onmousemove = mouseMoveTrigger;
document.onmouseup = mouseUpTrigger;
}
}
}
Any help would be greatly appreciated. Thanks in advance

Create a draggable div in native javascript [duplicate]

This question already has answers here:
Moveable/draggable <div>
(9 answers)
Closed 5 years ago.
I want to create a movable/draggable div in native javascript without using jquery and libraries. Is there a tutorial or anythign?
OK, here's my personal code that I use for lightweight deployments (projects where using a library is either not allowed or overkill for some reason). First thing first, I always use this convenience function so that I can pass either an id or the actual dom element:
function get (el) {
if (typeof el == 'string') return document.getElementById(el);
return el;
}
As a bonus, get() is shorter to type than document.getElementById() and my code ends up shorter.
Second realize that what most libraries are doing is cross-browser compatibility. If all browsers behave the same the code is fairly trivial. So lets write some cross-browser functions to get mouse position:
function mouseX (e) {
if (e.pageX) {
return e.pageX;
}
if (e.clientX) {
return e.clientX + (document.documentElement.scrollLeft ?
document.documentElement.scrollLeft :
document.body.scrollLeft);
}
return null;
}
function mouseY (e) {
if (e.pageY) {
return e.pageY;
}
if (e.clientY) {
return e.clientY + (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
}
return null;
}
OK, the two functions above are identical. There're certainly better ways to write them but I'm keeping it (relatively) simple for now.
Now we can write the drag and drop code. The thing I like about this code is that everything's captured in a single closure so there are no global variables or helper functions littering the browser. Also, the code separates the drag handle from the object being dragged. This is useful for creating dialog boxes etc. But if not needed, you can always assign them the same object. Anyway, here's the code:
function dragable (clickEl,dragEl) {
var p = get(clickEl);
var t = get(dragEl);
var drag = false;
offsetX = 0;
offsetY = 0;
var mousemoveTemp = null;
if (t) {
var move = function (x,y) {
t.style.left = (parseInt(t.style.left)+x) + "px";
t.style.top = (parseInt(t.style.top) +y) + "px";
}
var mouseMoveHandler = function (e) {
e = e || window.event;
if(!drag){return true};
var x = mouseX(e);
var y = mouseY(e);
if (x != offsetX || y != offsetY) {
move(x-offsetX,y-offsetY);
offsetX = x;
offsetY = y;
}
return false;
}
var start_drag = function (e) {
e = e || window.event;
offsetX=mouseX(e);
offsetY=mouseY(e);
drag=true; // basically we're using this to detect dragging
// save any previous mousemove event handler:
if (document.body.onmousemove) {
mousemoveTemp = document.body.onmousemove;
}
document.body.onmousemove = mouseMoveHandler;
return false;
}
var stop_drag = function () {
drag=false;
// restore previous mousemove event handler if necessary:
if (mousemoveTemp) {
document.body.onmousemove = mousemoveTemp;
mousemoveTemp = null;
}
return false;
}
p.onmousedown = start_drag;
p.onmouseup = stop_drag;
}
}
There is a reason for the slightly convoluted offsetX/offsetY calculations. If you notice, it's just taking the difference between mouse positions and adding them back to the position of the div being dragged. Why not just use the mouse positions? Well, if you do that the div will jump to the mouse pointer when you click on it. Which is a behavior I did not want.
You can try this
HTML
<div id="one" style="height:50px; width:50px; border:1px solid #ccc; background:red;">
</div>
Js Script for draggable div
window.onload = function(){
draggable('one');
};
var dragObj = null;
function draggable(id)
{
var obj = document.getElementById(id);
obj.style.position = "absolute";
obj.onmousedown = function(){
dragObj = obj;
}
}
document.onmouseup = function(e){
dragObj = null;
};
document.onmousemove = function(e){
var x = e.pageX;
var y = e.pageY;
if(dragObj == null)
return;
dragObj.style.left = x +"px";
dragObj.style.top= y +"px";
};
Check this Demo
This code corrects the position of the mouse (so the dragged object doesn't jump when you start dragging) and works with touch screens/phones as well
var dragObj = null; //object to be moved
var xOffset = 0; //used to prevent dragged object jumping to mouse location
var yOffset = 0;
window.onload = function()
{
document.getElementById("menuBar").addEventListener("mousedown", startDrag, true);
document.getElementById("menuBar").addEventListener("touchstart", startDrag, true);
document.onmouseup = stopDrag;
document.ontouchend = stopDrag;
}
function startDrag(e)
/*sets offset parameters and starts listening for mouse-move*/
{
e.preventDefault();
e.stopPropagation();
dragObj = e.target;
dragObj.style.position = "absolute";
var rect = dragObj.getBoundingClientRect();
if(e.type=="mousedown")
{
xOffset = e.clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.clientY - rect.top;
window.addEventListener('mousemove', dragObject, true);
}
else if(e.type=="touchstart")
{
xOffset = e.targetTouches[0].clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.targetTouches[0].clientY - rect.top;
window.addEventListener('touchmove', dragObject, true);
}
}
function dragObject(e)
/*Drag object*/
{
e.preventDefault();
e.stopPropagation();
if(dragObj == null) return; // if there is no object being dragged then do nothing
else if(e.type=="mousemove")
{
dragObj.style.left = e.clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.clientY-yOffset +"px";
}
else if(e.type=="touchmove")
{
dragObj.style.left = e.targetTouches[0].clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.targetTouches[0].clientY-yOffset +"px";
}
}
function stopDrag(e)
/*End dragging*/
{
if(dragObj)
{
dragObj = null;
window.removeEventListener('mousemove', dragObject, true);
window.removeEventListener('touchmove', dragObject, true);
}
}
div{height:400px; width:400px; border:1px solid #ccc; background:blue; cursor: pointer;}
<div id="menuBar" >A</div>
<div draggable=true ondragstart="event.dataTransfer.setData('text/plain', '12345')">
drag me
</div>
<div ondragover="return false;" ondrop="this.innerHTML=event.dataTransfer.getData('text/plain')">
drop on me
</div>

JavaScript cannot get onmousemove script to work as intended

I have a function to follow the object after the mouse,
and I want to be able to stop and start following at will, without hiding the object.
It almost works as I wanted, and is following the mouse indeed, but I cannot make it move initial position without actually moving the mouse.
E.G. When I trigger the function, the object is still somewhere in another place, until I move the mouse, but what I'm trying to do is to move it the initial position first, before attaching the mousemove event.
Here is how I want to trigger the function:
showtrail();
function showtrail(shit){
//this is how I tried to set the initial position first, but this get me an error:..
//followmouse();
document.onmousemove=followmouse; //and this is how I attach the event.
}
This is a part of the actual function to move the object,
but, I can't get the coordinates if I try to initilize/imitate the first movement.
function followmouse(e){
var xcoord=offsetfrommouse[0]
var ycoord=offsetfrommouse[1]
if (typeof e != "undefined"){ //This- if triggered by mousemove, and it works
xcoord+=e.pageX
ycoord+=e.pageY
}
else { //this was meant for the initial call, but... for some reason
xcoord+=document.body.scrollLeft+event.clientX // it triggers an error,
ycoord+=document.body.scrollTop+event.clientY // saying event.clientX undefined.
}
}
So the event.clientX never seems to work, and I cannot figure out how to get the actual mouse position otherwise..
Please guide..
event.clientX and event.clientY are wrong. They should be e.clientX and e.clientY
A more elegant cross browser way to get xcoord and ycoord in followmouse(e) is:
xcoord = e.pageX||(e.clientX+(document.body.scrollLeft||document.documentElement.scrollLeft));
ycoord = e.pageY||(e.clientY+(document.body.scrollTop||document.documentElement.scrollTop));
Now if I'm getting it right, the object that follows is expected to have an initial absolute position and displayed as a block, meaning that you have initial x and y (left and top). Therefore by using a global bool var for currently following or not you're done.
<style>
...
#trail {position:absolute;left:0;top:0;display:none}
...
</style>
<script>
var following = false;
...
function followmouse(e){
if (!following){
document.getElementById('trail').style.display='none';
return;
}
...
document.getElementById('trail').style.display='block';
}
</script>
By changing display you have the option to move your #trail to its initial position and then follow the mouse, and the option to avoid the move and let it follow the mouse from its latest following position.
EDIT 1:
For this very purpose, I recommend using of requestAnimationFrame API, not classic DOM events. said API is more efficient for creating animations and pausing them.
take a look at this too: requestAnimationFrame for smart animating
This is sad, but true that you can not get mouse's initial position before moving mouse on a webpage. I mean you can't calibrate your object before mousemove event. this is what I will do in a similar project:
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<script type="text/javascript">
var targetID = 'mydiv'; // div that is to follow the mouse
var pauseFollowing = false;
// (must be position:absolute)
var offX = 15; // X offset from mouse position
var offY = 15; // Y offset from mouse position
function mouseX(evt) {if (!evt) evt = window.event; if (evt.pageX) return evt.pageX; else if (evt.clientX)return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); else return 0;}
function mouseY(evt) {if (!evt) evt = window.event; if (evt.pageY) return evt.pageY; else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); else return 0;}
function follow(evt) {
if(pauseFollowing) {
//or do something else at pause
return false;
}
var obj = document.getElementById(targetID).style;
obj.visibility = 'visible';
obj.left = (parseInt(mouseX(evt))+offX) + 'px';
obj.top = (parseInt(mouseY(evt))+offY) + 'px';
}
function toggleFollow() {
pauseFollowing = !pauseFollowing;
}
window.onload = function() {
window.onclick = toggleFollow;
document.onmousemove = follow;
}
</script>
</head>
<body>
<div id="mydiv" style="visibility: hidden; top:0; left:0 ;width: 100px; height: 100px; background: #ff0; position: absolute;"></div>
</body>
</html>
Alright that's how I done it.
The best Idea was to always capture a move to set position in a global var.
Now I have an option to display it fixed at any specific place (if I pass coords to showtrail)
or to actually follow the mouse;
I also added an event listener, so if the mouse gets outside the window while following- it will be hidden.
So far it works exactly as I wanted:
var trailimage=["scripts/loading_mouse.gif", 24, 24] //image path, plus width and height
var offsetfrommouse=[2,10] //image x,y offsets from cursor position in pixels. Enter 0,0 for no offset
var global_coord=[0,0]
var follow=false;
if (document.getElementById || document.all)
document.write('<div id="trailimageid" style="z-index: 10;position:absolute;display:none;left:0px;top:0px;width:1px;height:1px"><img src="'+trailimage[0]+'" border="0" width="'+trailimage[1]+'px" height="'+trailimage[2]+'px"></div>')
function gettrailobj(){
if (document.getElementById)
return document.getElementById("trailimageid").style
else if (document.all)
return document.all.trailimagid.style
}
function hidett(){ gettrailobj().display="none"; }
function showtt(){ gettrailobj().display="block"; }
function truebody(){ return (document.body||document.documentElement); }
function showtrail(shit){
if (typeof shit == "undefined"){ //Follow Mouse
follow=true;
setmousepos(global_coord[0],global_coord[1]);
}
else { //Set fixed in specific place
follow=false;
showtt()
gettrailobj().left=shit.left+6+"px"
gettrailobj().top=shit.top-5+"px"
}
}
function hidetrail(){
hidett()
follow=false;
}
function setcoord(e){
var xcoord=offsetfrommouse[0]
var ycoord=offsetfrommouse[1]
var xxcoord = e.pageX||(e.clientX+truebody().scrollLeft);
var yycoord = e.pageY||(e.clientY+truebody().scrollTop);
if (typeof xxcoord != "undefined"&&typeof yycoord != "undefined"){
xcoord+=xxcoord;
ycoord+=yycoord;
global_coord=[xcoord,ycoord];
if (follow) setmousepos(xcoord,ycoord);
}}
function setmousepos(xcoord,ycoord){
var docwidth=truebody().scrollLeft+truebody().clientWidth
var docheight=Math.max(truebody().scrollHeight, truebody().clientHeight)
if ((xcoord+trailimage[1]+3>docwidth || ycoord+trailimage[2]> docheight ||!follow)){
hidett()
}
else{
showtt();
gettrailobj().left=xcoord+"px"
gettrailobj().top=ycoord+"px"
}
}
window.addEventListener("mouseout",
function(e){
mouseX = e.pageX;
mouseY = e.pageY;
if ((mouseY >= 0 && mouseY <= window.innerHeight)
&& (mouseX >= 0 && mouseX <= window.innerWidth)){
return false;
}else{
if (follow) hidett()
}
},
false);
document.onmousemove=setcoord;

Categories