drag&drop of div element - javascript

I have a rectangular div element on a page with image and text span inside.
Div has 2px border to make it actually visible.
Then I add dragstart event listener to my div element.
dragstart event fires always if I start dragging the image inside div but it is very problematic if I start dragging by clicking on text span or blank place:
In Google Chrome dragging is very unstable. It can work a few times then stops firing, then work again and so on.
In Mozilla Firefox it doesn't work at all.
How to fix it and allow drag by clicking on any point inside bound rect of my div?
<div class="item">
<img src="https://www.wigwam3d.com/previews/1f/1ffbf8da-a4d0-4e40-b9e1-0329220969dc.jpg">
<div>Element</div>
</div>
Plunker: http://plnkr.co/edit/673ytif50cViE5dTv3df?p=preview

Use this code , you can drag div anywhere on the window. Also fix width and height of the div.
$(function(){
$("#animation").css({"cursor":"move"})
// mousedown:fn(){dragging = true;}
var dragging = false;
var iX, iY;
$("#animation").mousedown(function(e) {
dragging = true;
iX = e.clientX - this.offsetLeft;
iY = e.clientY - this.offsetTop;
this.setCapture && this.setCapture();
return false;
});
// mouseover:fn(){dragging = tru;}
document.onmousemove = function(e) {
if (dragging) {
var e = e || window.event;
var oX = e.clientX - iX;
var oY = e.clientY - iY;
$("#animation").css({"left":oX + "px", "top":oY + "px"});
return false;
}
};
// mouseup:fn(){dragging = false;}
$('#animation').mouseup(function(e) {
dragging = false;
this.releaseCapture && this.releaseCapture();
e.cancelBubble = true;
})
})

Just found a simple solution: add attribute draggable=true on div element! That's all!

Related

Drag div content by grabbing its background

When the content goes outside the div, we use scrollbars to see it. How can I scroll the div content by grabbing and dragging its background? I've searched the solution but did not find what I need. Here is my fiddle:
https://jsfiddle.net/vaxobasilidze/xhn49e1j/
Drag any item to the right div and move it outside the container to the right or bottom. scrollbars appear to help you to scroll. Here is an example of what I want to achieve. See the first diagram on the link and drag it:
https://jsplumbtoolkit.com/
Any tips on how to do this?
You should just need to detect when the mouse is down and then when the mouse is moving afterwards you can store the previous mouse coordinates and reference the current coordinates. Finally you can scroll the div in question by an amount based on the difference in drag since the last mousemove call.
var mouseDown = false;
var prevCoords = { x: 0, y: 0 };
$("#mainDiv").mousedown(function() {
mouseDown = true;
}).mousemove(function(e) {
var currentScrollX = $('#mainDiv').scrollLeft();
var currentScrollY = $('#mainDiv').scrollTop();
if(mouseDown) {
$('#mainDiv').scrollLeft(currentScrollX + prevCoords.x - (e.clientX + currentScrollX))
$('#mainDiv').scrollTop(currentScrollY + prevCoords.y - e.clientY)
};
prevCoords.x = e.clientX + currentScrollX;
prevCoords.y = e.clientY;
}).mouseup(function() {
mouseDown = false;
});
https://jsfiddle.net/6rx30muh/
EDIT: Fixed bug with wiggling tables when dragging:
var mouseDown = false;
var prevCoords = { x: 0, y: 0 };
$("#mainDiv").mousedown(function() {
mouseDown = true;
}).mousemove(function(e) {
var currentScrollX = $('#mainDiv').scrollLeft();
var currentScrollY = $('#mainDiv').scrollTop();
if(mouseDown) {
$('#mainDiv').scrollLeft(currentScrollX + prevCoords.x - e.clientX)
$('#mainDiv').scrollTop(currentScrollY + prevCoords.y - e.clientY)
};
prevCoords.x = e.clientX;
prevCoords.y = e.clientY;
}).mouseup(function() {
mouseDown = false;
});
Check for mousemove between mousedown and mouseup on the body element is a good place to start.
element = $('body');
element.addEventListener("mousedown", function(){
flag = 0;
}, false);
element.addEventListener("mousemove", function(){
flag = 1;
}, false);
element.addEventListener("mouseup", function(){
if(flag === 0){
console.log("click");
}
else if(flag === 1){
console.log("drag");
}
}, false);

How to detect mouseleave when mouse button is being held and cursor is out the viewport?

I need to detect when an user move out the mouse outside the view-port (example mouse is on browser address bar) even when the mouse button is being held.
As you can see from the code below, I am able to detect it using mouseout and mouseleave but when keeping the mouse button hold and moving out of the view-port these events are not fired.
Any idea how to solve this issue?
I target FF and Chrome latest version.
http://jsbin.com/gesehoneri/edit?html,output
document.addEventListener('mouseout', function () {
console.log('mouseout');
})
document.addEventListener('mouseleave', function () {
console.log('mouseleave');
})
Try this:
document.addEventListener('mousemove', function(e) {
var top = e.pageY;
var right = document.body.clientWidth - e.pageX;
var bottom = document.body.clientHeight - e.pageY;
var left = e.pageX;
if (top < 10 || right < 10 || bottom < 10 || left < 10) {
console.log('Mouse is out the viewport!');
}
});
body,
html {
height: 100%;
}
With this code, if you press the button inside the window, hold it and move the mouse outside the window, it logs the text. Does this help you?
function myFunctioName(e){
if(e.pageY < 0 || e.pageY > window.innerHeight) {
console.log("outside window vertical");
};
if(e.pageX < 0 || e.pageX > window.innerWidth) {
console.log("outside window horizontal");
};
}
window.addEventListener("mousemove", myFunctioName);
window.addEventListener("mousedown", myFunctioName);
Updated for use without JQuery and included both directions.

Creating a Windows 8 Explorer simulation - mouse selection issue

As a little practice I decided to recreate the Windows 8 Explorer file list panel, and all went well, until I wanted to add the mouse selection. It's basically the feature that allows you to select multiple files by dragging your mouse along the window, drawing a square, which should select all "files" that fall under it.
The only problem I have is that I can't seem to find a way to add the selected class to the elements under the selection
Here's the related code: (full code available in a working fiddle)
<ul class="files">
<li>
<span class="icon folder"></span>
<span class="name">Folder</span>
</li>
</ul>
.selection {
position: absolute;
border: 1px solid #39F;
background-color: rgba(51,153,255,.4);
display: none;
}
$(function(){
var $body = $(document.body);
var selecting = false,
$selectionDiv = $(document.createElement('div')).addClass('selection').appendTo($body),
startX, startY;
$body.on({
mousedown: function(e){
if (e.target === document.body){
e.stopPropagation();
startX = e.clientX;
startY = e.clientY;
selecting = true;
$selectionDiv.show().css({top:startY+'px',left:startX+'px',width:'0px',height:'0px'});
}
},
mousemove: function(e){
if (selecting){
var currentX = e.clientX,
currentY = e.clientY;
var subX = currentX - startX,
subY = currentY - startY;
if (subX < 0){
subX *= -1;
$selectionDiv.css('left',startX+(currentX-startX));
}
else $selectionDiv.css('left',startX+'px');
if (subY < 0){
subY *= -1;
$selectionDiv.css('top',startY+(currentY-startY));
}
else $selectionDiv.css('top',startY+'px');
$selectionDiv.css({
width: subX,
height: subY,
});
}
}
}).on('mouseup blur mouseleave',function(){
if (selecting){
$selectionDiv.hide();
selecting = false;
}
});
});
If I understand you correctly, you need to determine which elements are contained inside the selection box. Here's the code which seems to do the job (it's supposed to go into your mousemove event handler):
var topLeftX = Math.min(startX, currentX),
topLeftY = Math.min(startY, currentY),
bottomRightX = Math.max(startX, currentX),
bottomRightY = Math.max(startY, currentY);
$('.files li').each(function() {
var offset = $(this).offset(),
width = $(this).outerWidth(),
height = $(this).outerHeight();
if (offset.left < bottomRightX
&& offset.left + width > topLeftX
&& offset.top < bottomRightY
&& offset.top + height > topLeftY) {
$(this).addClass('selected');
}
else {
$(this).removeClass('selected');
}
});
This code goes through all the elements of your file list and runs rectangle overlap test (the algorithm for which I got from this answer) for the selection box and the list element. Usage of outerWidth() and outerHeight() makes sure that the border is also taken into consideration.
I also noticed that when you release the mouse your handler which resets the selection gets called:
$(window).click(function(){
$('.files li').removeClass('selected');
})
As a possible solution, you can move this into your mousedown handler.
Here's JSFIddle which works for me in Chrome 35: http://jsfiddle.net/5Hzm4/2/

Make a div follow the mouse just when the mouse is on mousedown

I'm trying to make a jquery function to follow the mouse coursor with a div, when it is on mousedown and when it is on mouseup it stay in the last position it was.
any sugestion.
Why not simply use drag and drop by jquery:
<script>
$(function() {
$( "#draggable" ).draggable();
});
</script>
Jquery draggable
I've put together a simple working example that defines a Draggable object. You specify the drag item (the element that you're moving around), as well as a drag boundary (the space—or element—that you are moving the item inside of). The concept of a boundary is important if you ever want to restrict a draggable item to a certain space on the page (such as a container), or define a relative coordinate system on which to base your math.
My solution isn't the fastest, but it demonstrates the concept:
$(function() {
window.mousedown = 0;
$(window).on('mousedown mouseup', function(e) {
if(e.type == 'mousedown') { this.mousedown++; }
else { this.mousedown--; }
});
var Draggable = function(dragItem, dragBoundary) {
this.item = $(dragItem).css('position', 'absolute');
this.item.on('mousemove', $.proxy(this.handleDragEvent, this));
this.boundary = $(dragBoundary).css('position', 'relative');
};
Draggable.prototype.handleDragEvent = function(e) {
if(window.mousedown) {
var mousePosition = this.mapToBoundary([e.clientX, e.clientY]);
var mouseX = mousePosition[0],
mouseY = mousePosition[1];
if(typeof this.prevMouseX == "undefined") this.prevMouseX = mouseX;
if(typeof this.prevMouseY == "undefined") this.prevMouseY = mouseY;
this.itemX = this.item.offset().left - this.boundary.offset().left;
this.itemY = this.item.offset().top - this.boundary.offset().top;
var deltaX = mouseX - this.prevMouseX,
deltaY = mouseY - this.prevMouseY;
this.item.css({
'left': this.itemX + deltaX,
'top': this.itemY + deltaY
});
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
};
Draggable.prototype.mapToBoundary = function(coord) {
var x = coord[0] - this.boundary.offset().left;
var y = coord[1] - this.boundary.offset().top;
return [x,y];
};
var draggable = new Draggable($('.draggable'), $('.container'));
});
Notice that we are maintaining a mousedown value on global, allowing us to determine when it would be appropriate to drag around our element (we only add a mousemove listener to the drag item itself). I've also included a spacer div above the boundary div to demonstrate how you can move the boundary anywhere around the page and the coordinate system is still accurate. The code to actually restrict a draggable item within its assigned boundary could be written using simple math.
Here is the fiddle: http://jsfiddle.net/bTh9s/3/
EDIT:
Here is the start to some code for restricting a Draggable item within its container.
Draggable.prototype.restrictItemToBoundary = function() {
var position = this.item.position();
position.right = position.left + this.item.outerWidth();
position.bottom = position.top + this.item.outerHeight();
if(position.left <= 0) {
this.item.css('left', 1);
} else if(position.right >= this.boundary.outerWidth()) {
this.item.css('left', this.boundary.outerWidth() - this.item.outerWidth());
}
if(position.top <= 0) {
this.item.css('top', 1);
} else if(position.bottom >= this.boundary.outerHeight()) {
this.item.css('top', this.boundary.outerHeight() - this.item.outerHeight());
}
};
This method should be called inside of Draggable.handleDragEvent just after you update the CSS positioning of the drag item. It seems this solution is glitchy, but it's a start.

mousemove strange behavior

i am trying to change images of a slideshow using mousemove. but its not working correctly. It only works correctly first time and after that even the mouse is not clicked it assumed that mouse is clicked.
You can check demo here
http://unirazz.com/kb/html/movie.html
here is the code for mousemove
var clicking = false;
var pageX = 0;
$('#movieShow').mousedown(function(e){
clicking = true;
pageX = e.pageX;
});
$(document).mouseup(function(e){
clicking = false;
pageX = 0;
//alert('h');
})
$('#movieShow').mousemove(function(e){
if(clicking == false) return;
// Mouse click + moving logic here
//$('.movestatus').text('mouse moving');
if(pageX == 0) return;
if((e.pageX - pageX) > 0){
var t = e.pageX - pageX;
if(t%10 == 0){
pageX = e.pageX;
//console.log('right');
rightClick();
}
}
else{
var t = pageX - e.pageX;
if(t%10 == 0){
pageX = e.pageX;
//console.log('left');
leftClick();
}
}
});
It seems to be getting confused when you click and hold and drag your mouse outside the 'movieShow'. Your document.mouseup isn't working so it never sets clicking to false;
I think you need to define a mouseout for 'movieShow' that does the same thing as mouseup
$('#movieShow').mouseout(function(e){
clicking = false;
pageX = 0;
})

Categories

Resources