I've got issue with the not-allowed cursor. While dragging the "drag" element, not-allowed cursor appears and I can't drag it anymore. How can i prevent that? I want to make my "drag" element always be "absolute" while mouse is down.
Note: I know that it can happens becouse "pointer-events" but I need it to be contained into this code.
Some code:
$("#drag").bind({
mousedown : function (e) {
var dragged = $(this);
dragged.css({
left : e.pageX - (50 / 2),
top : e.pageY - (50 / 2)
});
dragged.addClass("absolute");
dragged.css({
'pointer-events' : 'none'
})
var upHandler = function () {
dragged.removeClass("absolute");
dragged.css({
'pointer-events' : 'all'
})
$("body").off('mouseup', upHandler);
$("body").off('mousemove', moveHandler);
}
var moveHandler = function (e) {
dragged.css({
left : e.pageX - (50 / 2),
top : e.pageY - (50 / 2)
});
}
$("body").bind({
mouseup : upHandler,
mousemove : moveHandler
})
}
});
$("body").mousemove(function (event) {
$("#log").text("pageX: " + event.pageX + ", pageY: " + event.pageY);
});
https://jsfiddle.net/38zecoL1/1/
Thanks for any help.
Before handling your mouse events, make a call to
e.preventDefault();
It cancels the event which prevents the browser from performing the default behavior. Normally it would show a "not allowed" cursor on elements that typically are not draggable.
$("box").mouseover(function() {
$(this).addClass("green");
var box = $(this).attr("id");
$("#result").html(box);
});
/*
Solution
*/
$("box").mousedown(function(e) {
// Booooom! This should stop the undesired default beahvior.
e.preventDefault();
});
$("box").mouseleave(function() {
$(this).removeClass("green");
});
$("#drag").bind({
mousedown: function() {
$(this).addClass("absolute");
},
mouseup: function() {
$(this).removeClass("absolute");
},
mousemove: function(e) {
$(this).css({
left: e.pageX - (50 / 2),
top: e.pageY - (50 / 2)
});
}
});
$("body").mousemove(function(event) {
$("#log").text("pageX: " + event.pageX + ", pageY: " + event.pageY);
});
box {
float: left;
width: 100px;
height: 100px;
background-color: red;
margin: 20px;
}
#log {
position: absolute;
top: 150px;
}
.green {
background-color: green;
}
#drag {
width: 50px;
height: 50px;
float: left;
background-color: blue;
}
#drag.absolute {
position: absolute;
}
html,
body {
width: 100%;
height: 100%;
}
* {
margin: 0;
padding: 0;
}
<box id="box1">
<div id="drag"></div>
</box>
<box id="box2"></box>
<div id="result"></div>
<div id="log"></div>
Original fiddle: https://jsfiddle.net/38zecoL1/4/
Related
I am trying to have this circle follow the cursor. However I need the cursor to fade in after the user clicks a button, when this happens though the circle won't be centered on the cursor.
The first code snippet shows the desired result in terms of the circle following the cursor correctly and being centered.The second snippet shows the desired fade in on button click but as you can see the circle won't be centered on the cursor
First code snippet:
const cursor = document.querySelector('.test');
const {
width,
height
} = cursor.getBoundingClientRect();
document.addEventListener('mousemove', e => {
cursor.style.top = e.y - height / 2 + 'px';
cursor.style.left = e.x - width / 2 + 'px';
});
.test {
position: absolute;
width: 25rem;
height: 25rem;
border-radius: 50%;
background-color: red;
z-index: 200;
}
<div class="test"></div>
Second code snippet:
$("#myBtn").click(function(){
$('.test').fadeIn();
});
const cursor = document.querySelector('.test');
const {
width,
height
} = cursor.getBoundingClientRect();
document.addEventListener('mousemove', e => {
cursor.style.top = e.y - height / 2 + 'px';
cursor.style.left = e.x - width / 2 + 'px';
});
.test {
position: absolute;
width: 25rem;
height: 25rem;
border-radius: 50%;
background-color: blue;
z-index: 200;
display: none;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<button id="myBtn">show</button>
<div class="test"></div>
In the second example, on page init the .test div has display: none, so its height and width are 0. You must calculate them after the fadeIn to get the correct result.
You can also add the mousemove listener after fadeIn:
$("#myBtn").click(function() {
$('.test').fadeIn('slow', function() {
const cursor = document.querySelector('.test')
, { width, height } = cursor.getBoundingClientRect();
document.addEventListener('mousemove', e => {
cursor.style.top = e.y - height / 2 + 'px';
cursor.style.left = e.x - width / 2 + 'px';
});
});
});
.test {
position: absolute;
width: 25rem;
height: 25rem;
border-radius: 50%;
background-color: blue;
z-index: 200;
display: none;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<button id="myBtn">show</button>
<div class="test"></div>
Another, perhaps simpler, alternative is just to call fadeOut() (with a duration of 0) on the .test div on page load, instead of using display:none
$("#myBtn").click(function(){
$('.test').fadeIn();
});
const cursor = document.querySelector('.test');
const {
width,
height
} = cursor.getBoundingClientRect();
$('.test').fadeOut(0);
document.addEventListener('mousemove', e => {
cursor.style.top = e.y - height / 2 + 'px';
cursor.style.left = e.x - width / 2 + 'px';
});
.test {
position: absolute;
width: 25rem;
height: 25rem;
border-radius: 50%;
background-color: blue;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<button id="myBtn">show</button>
<div class="test"></div>
How to move or drag the span into the Div element. My element structure is the Div -> Span. Here I need to drag the Span inside the div element without drag beyond that div. I have tried this by calculating pixels but didn't give a solution. I don't need a native onDrag method.
I need to calculate pixels and drag the Span inside the Div. Here is my code.
var handleClick = false;
window.dragging = function(event) {
if (handleClick) {
var bar = document.getElementsByClassName('bar')[0],
handle = document.getElementsByClassName('handle')[0];
var left = bar.offsetWidth - handle.offsetWidth;
tops = (bar.offsetWidth - handle.offsetWidth);
pixel = left < ((pixel - 0) / 1.233445) ? left : ((pixel - 0) / 1.233445);
handle.style.left = pixel + "px";
}
}
document.addEventListener('mouseup', function() {
handleClick = false;
});
window.handlersDown = function() {
handleClick = true;
}
.bar {
width: 100px;
height: 30px;
border: 1px solid;
position: relative;
}
.handle {
width: 20px;
height: 20px;
left: 2px;
top: 5px;
background-color: rgba(255, 0, 0, 0.5);
position: absolute;
}
<div class="bar">
<span class="handle" onmousedown="handlersDown()" onmousemove="dragging(event)"></span>
</div>
I have modified your code a bit and changed the selectors from class to ID. I also would advice you to use external libraries to make it more easy for you. Besides that I also removed the event listeners inside your HTML and translate them to Javascript. Is this what you want?
window.onload = addListeners();
function addListeners(){
document.getElementById('handle').addEventListener('mousedown', mouseDown, false);
window.addEventListener('mouseup', mouseUp, false);
}
function mouseUp()
{
window.removeEventListener('mousemove', spanMove, true);
}
function mouseDown(e){
window.addEventListener('mousemove', spanMove, true);
}
function spanMove(e){
var bar = document.getElementById('bar')
var span = document.getElementById('handle');
// variables
var bar_width = bar.offsetWidth;
var handle_width = span.offsetWidth;
// stop scroll left if the minimum and maximum is reached
if(e.clientX < bar_width - handle_width - 1 && e.clientX > 1){
span.style.left = e.clientX + 'px';
}
}
#bar {
width: 100px;
height: 30px;
border: 1px solid;
position: relative;
}
#handle {
width: 20px;
height: 20px;
left: 2px;
top: 5px;
background-color: rgba(255, 0, 0, 0.5);
position: absolute;
}
<div id="bar">
<span id="handle"></span>
</div>
In 2020, following solution works perfectly on last version of Chrome, Opera, Firefox and Edge Chromium.
window.onload = addListeners();
function addListeners()
{
var div = document.getElementById('div');
var span = document.getElementById('span');
span.addEventListener('mousedown', onMouseDown, false);
window.addEventListener('mouseup', onMouseUp, false);
//compute space between left border of <div> and left border of <span>
// this value is also used to compute space at right
iMinLeft = span.offsetLeft;
// compute max left value allowed so that span remains in <div>
iMaxLeft = div.clientWidth - span.offsetWidth - iMinLeft;
}
function onMouseDown(e)
{
if (e.which === 1) // left button is pressed
{
e.preventDefault();
window.addEventListener('mousemove', onMouseMove, true);
// save mouse X position to compute deplacement
posMouseX = e.clientX;
span.style.background = "yellow";
}
}
function onMouseMove(e)
{
e.preventDefault();
//compute mouse deplacement
deltaX = posMouseX - e.clientX;
//compute new left position of <span> element
iNewLeft = span.offsetLeft - deltaX;
if (iNewLeft < iMinLeft)
{
iNewLeft = iMinLeft;
}
else
{
if (iNewLeft > iMaxLeft)
{
iNewLeft = iMaxLeft;
}
}
span.style.left = iNewLeft + 'px';
// save mouse X position to compute NEXT deplacement
posMouseX = e.clientX;
}
function onMouseUp(e)
{
if (e.which === 1) // left button is pressed
{
e.preventDefault();
span.style.background = "white";
window.removeEventListener('mousemove', onMouseMove, true);
}
}
#div
{
width: 200px;
height: 50px;
border: 1px solid;
position: relative;
left: 50px;
}
#span
{
cursor: pointer;
font-size: 30px;
width: auto;
height: 40px;
left: 2px;
top: 5px;
position: absolute;
}
<div id="div">
<span id="span">😃</span>
</div>
JavaScript line e.preventDefault(); is necessary to avoid <span> to become 'blue' when dragging.
CSS code cursor: pointer; is only to see that unicode is clickable.
Javascript line if (e.which === 1) has been added to prevent emoticon to move when RIGHT mouse button is clicked.
The rectangle around emoticon when <span> is dragged move without being shifted (see previous solution) and space remaining in left or in right are equal.
Thanks to w3schools-exemple
I have two divs that I want my users to be able to hit a button and arrange these two divs top/down or left/right. I have implemented it but whenever I arrange them left/right, the right div often overflows to the bottom of the left div.
I have seen another similar example that talks about resizing left/right divs, but I still don't know what exactly caused my right div to overflow. Any help is appreciated!
Here is my example:
var d = $('#divider'); // divider between top and bottom divs
var t = $('#tl'); // top/left div
var b = $('#br'); // bottom/right div
var h = $('body').height();
var w = $('body').width();
var isDragging = false;
var isLandscape = false;
d.mousedown(function(e) {
isDragging = true;
});
$(document).mouseup(function() {
isDragging = false;
}).mousemove(function(e) {
if (isDragging) {
if (!isLandscape) {
t.css('height', e.pageY);
b.css('height', h - e.pageY - d.height());
d.css('height', h - t.height() - b.height());
} else {
t.css('width', e.pageX);
b.css('width', w - e.pageX - d.width());
d.css('width', w - t.width() - b.width());
}
}
});
var rotateBtn = document.getElementById('rotateScreen');
if (rotateBtn) {
rotateBtn.addEventListener('click', rotateDisplay, false);
} else {
throw error;
}
function rotateDisplay() {
if (!isLandscape) {
isLandscape = true;
t.css('height', h);
t.css('width', Math.round(0.75 * w));
b.css('height', h);
b.css('width', Math.round(0.24 * w));
d.css('height', h);
d.css('width', w - t.width() - b.width());
d.css('cursor', 'w-resize');
} else {
isLandscape = false;
t.css('height', Math.round(0.75 * h));
t.css('width', w);
t.css('float', 'left');
b.css('height', Math.round(0.24 * h));
b.css('width', w);
b.css('float', 'left');
d.css('height', h - t.height() - b.height());
d.css('width', w);
d.css('cursor', 'n-resize');
d.css('float', 'left');
}
}
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#br {
width: 100%;
height: 24%;
float: left;
background: gold;
}
#tl {
width: 100%;
height: 75%;
float: left;
background: navy;
}
#divider {
height: 1%;
background: #fff;
float: left;
width: 100%;
cursor: ns-resize;
}
#control {
position: absolute;
z-index: 5;
background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="control">
<button id="rotateScreen">🔁</button>
</div>
<div id="tl">This is the top/left div</div>
<div id="divider"></div>
<div id="br">This is the bottom/right div</div>
I'm trying to drag a div when I click on it but when I do it the div blinks and moves to the left, if I remove offset and put position instead it works but the cursor goes to the left top of the div.
var selected = 0,
x = 0,
y = 0;
$.fn.isDraggable = function() {
$(this).on('mousedown', function(e) {
selected = $(this);
$(selected).css({
position: 'absolute',
left: e.pageX - $(selected).position().left,
top: e.pageY - $(selected).position().top
});
});
$(document).on('mouseup', function() {
if (selected !== 0) {
selected = 0;
}
});
$(document).bind('mousemove', function(e) {
$(selected).css({
position: 'absolute',
left: e.pageX - $(selected).offset().left,
top: e.pageY - $(selected).offset().top
});
});
return true;
};
$('#card').isDraggable();
#card {
position: fixed;
width: 100px;
height: 150px;
top: calc(50% - 75px);
left: calc(50% - 50px);
border: 1px solid #D3D3D3;
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<title>freeMarketRocks</title>
</head>
<body>
<div>
<div id="card">
</div>
</div>
</body>
</html>
You have 2 problems here. First your event handler logic might result in a performance waste as you are asking your browser to constantly check for mouse movement, even if its not necessary.
Second, the calculation of the box coordiante is wrong, it must take the initial position in account. That's the purpose of my deltaX and deltaY variables in the fiddle
Here's a working fiddle https://jsfiddle.net/TCHdevlp/t2bapq5y/
Or Here:
var selected = 0,
x = 0,
y = 0,
boxX = 0,
boxY = 0;
$.fn.isDraggable = function() {
$(this).on('mousedown', function(e) {
selected = $(this);
//get initial positions
x = e.pageX;
y = e.pageY;
BoxX = $(selected).offset().left;
BoxY = $(selected).offset().top;
//bind mousemove
$(document).bind('mousemove', function(e) {
//compute new coordinate
deltaX = e.pageX - x;
deltaY = e.pageY - y;
$(selected).css({
position: 'absolute',
left: (BoxX + deltaX),
top: (BoxY + deltaY)
});
});
});
//unbind when finished
$(document).on('mouseup', function() {
if (selected !== 0) {
$(document).unbind("mousemove");
selected = 0;
}
});
return true;
};
$('#card').isDraggable();
#card {
position: fixed;
width: 100px;
height: 150px;
top: 10x;
left: 10px;
border: 1px solid #D3D3D3;
}
<div>
<div id="card">
</div>
</div>
var selected = 0,
x = 0,
y = 0;
$.fn.isDraggable = function() {
var moveFrame, comStartX, comStartY, startMousePosX, startMousePosY;
$(this).on('mousedown', function(e) {
selected = $(this);
moveFrame = true;
comStartX = $(this).position().left;
comStartY = $(this).position().top;
startMousePosX = e.pageX;
startMousePosY = e.pageY;
});
$(document).on('mouseup', function() {
moveFrame = false;
});
$(document).bind('mousemove', function(e) {
if (moveFrame){
currPosX = comStartX + (e.pageX - startMousePosX);
currPosY = comStartY + (e.pageY - startMousePosY);
$(selected).css({position: 'absolute', 'left': currPosX + 'px', 'top': currPosY + 'px'});
}
});
return true;
};
$('#card').isDraggable();
#card {
position: fixed;
width: 100px;
height: 150px;
top: calc(50% - 75px);
left: calc(50% - 50px);
border: 1px solid #D3D3D3;
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<title>freeMarketRocks</title>
</head>
<body>
<div>
<div id="card">
</div>
</div>
</body>
</html>
I have this HTML code:
<div class="inner">
<div class="nhood">
<div class="image"></div>
</div>
</div>
And this CSS:
.image {
width: 4000px;
height: 4000px;
background: beige;
margin: 150px;
position: absolute;
}
.nhood {
overflow: hidden;
width: 100%;
height: 100%;
box-sizing: border-box;
position: relative;
background: black;
}
The .image div is filled with 400 divs, all floating left, creating a huge 'chess'-pattern, the code is the following:
.image > div {
border: 1px dotted;
width: 5%;
height: 5%;
float: left;
box-sizing:border-box;
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
position: relative;
user-select: none;
}
You are able to click on any cell to show its info, and the whole .image div is draggable. Now if you have selected a cell and you ZOOM (which basically only shrinks/extends the 4000x4000 div to 2000x2000 or the other way round) it zooms in ANYWHERE but I want to keep focus on the cell that was selected earlier.
I have made an image of this:
http://smimoo.lima-city.de/zoom.png
I hope this was any clear...
EDIT:
JS
function zoomIn() {
$(draggable).animate({
height: '4000',
width: '4000',
borderWidth: 0
}, 600, function() {
$divs.animate({
borderWidth: 0
});
});
}
function zoomOut() {
$(draggable).animate({
height: '2000',
width: '2000',
borderWidth: 0
}, 600, function() {
$divs.animate({
borderWidth: 1
});
});
EDIT2:
This is my js to center the function (written before Mario helped me out):
function centerField() {
var myObject = $(draggable).find('.selected');
var docWidth = ($(viewport).width() / 2) - (myObject.outerWidth()/2);
var docHeight = ($(viewport).height() / 2) - (myObject.outerWidth()/4);
var myOff = myObject.offset();
var distanceTop = myOff.top - docHeight;
var distanceLeft = myOff.left - docWidth;
var position = $(draggable).position();
var left = position.left;
var top = position.top;
var right = left - $(viewport).width() + draggable.outerWidth(true);
var bottom = top - $(viewport).height() + draggable.outerHeight(true);
if(left - distanceLeft > 0) {
distanceLeft = left;
}
if(right - distanceLeft < 0) {
distanceLeft = right;
}
if(top - distanceTop > 0) {
distanceTop = top;
}
if(bottom - distanceTop < 0) {
distanceTop = bottom;
}
$(draggable).animate({
left: '-=' + distanceLeft,
top: '-=' + distanceTop
}, { duration: 200, queue: false });
}
Assume that the selected div has the class .selected, this function will center the div:
function centerSelected() {
var selectedElement = $('.image .selected');
var p = selectedElement.position();
var w = $('.nhood').width();
var h = $('.nhood').height();
var offsetX = (w/2)-p.left - (selectedElement.width() / 2);
var offsetY = (h/2)-p.top - (selectedElement.height() / 2);
if(offsetX > 0) offsetX = 0;
if(offsetY > 0) offsetY = 0;
$('.image').css('left', offsetX + 'px');
$('.image').css('top', offsetY + 'px');
}
Just call centerSelected after every zoom operation.
Here is a jsfiddle with slightly modified css to get the presentation work:
http://jsfiddle.net/q1r95w3g/3/
Edit
If you want the div to get centered during jQuery animation, you can call centerSelected in the step callback of the animate method, e.g.:
function zoomIn() {
$(draggable).animate({
height: '4000',
width: '4000',
borderWidth: 0
},{
duration: 600,
complete: function() {
$divs.animate({
borderWidth: 0
});
},
step: function(now, fx) {
centerSelected();
}
});
}