Snapping Drag and Drop Items in JavaScript - javascript

I am trying to use drag and drop to move pictures from one <div> to another.
Currently, I can move the pictures anywhere in the destination <div>, but what I really want is that the pictures snap together when dropped. Ideally, they would be able to snap together on any side (not just, for example, on the bottom or on the right).
I've tried a few different things (including using <canvas>) and it didn't work.
This is what I have so far:
var clone;
var offsetx = null;
var offsety = null;
var isClone = false;
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
offsetx = ev.target.offsetLeft - event.clientX;
offsety = ev.target.offsetTop - event.clientY;
ev.dataTransfer.setData("text", ev.target.id);
}
function dropTrash(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var remove = document.getElementById(data);
remove.parentNode.removeChild(remove);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
}
function dropClone(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var num = Math.random() * (1000 - 1) + 1;
isClone = true;
clone = document.getElementById(data).cloneNode(true);
clone.id = "newId" + num.toString();
clone.style.position = "absolute";
clone.style.left = (event.clientX+offsetx)+"px";
clone.style.top = (event.clientY+offsety)+"px";
ev.target.appendChild(clone);
}
html, body {
height: 100%;
padding: 0;
margin: 0;
}
div {
width: 50%;
height: 50%;
float: left;
}
#div1 {
background: #DDD;
}
#div2 {
background: #AAA;
}
#div3 {
background: #777;
}
#div4 {
background: #444;
}
#imgDiv {
width: 611px;
height: 324px;
border: 5px solid #DDD;
}
<div id="div1">
</div>
<div id="div2">
</div>
<div id="div3" ondrop="dropTrash(event)" ondragover="allowDrop(event)">
<img id="drag1" src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Bartagame_fcm.jpg/1200px-Bartagame_fcm.jpg" draggable="true" ondragstart="drag(event)" width="105" height="105">
<img id="drag2" src="http://www.earthtimes.org/newsimage/lizard_Ngo_Van_Tri_big_281.jpg" draggable="true" ondragstart="drag(event)" width="105" height="105">
</div>
<div id="div4">
<div align="center" id="imgDiv" ondrop="dropClone(event)" ondragover="allowDrop(event)"></div>
</div>

When you start dragging an image, you need to store the position of the cursor, relative to that particular image.
There are multiple position properties in the MouseEvent that will help you calculate that, but if browser support is not an issue, I would go for MouseEvent.offsetX and MouseEvent.offsetY. From the docs:
The offsetX/offsetY read-only property of the MouseEvent interface provides the offset in the X/Y coordinate of the mouse pointer between that event and the padding edge of the target node.
So, on dragstart, you will do just:
x = e.offsetX;
y = e.offsetY;
Then, when you drop the image in your, let's call it canvas (note the italics as it is not a <canvas> element, but any other element that you use as your drop zone, a <div> in this particular example), you need to know the position of the cursor relative to that canvas, so you may think you could use offsetX and offsetY again, and your are partially right. That would give you the expected value if you drop the image on the canvas itself, but there may be other images in it already, and you may drop the current one on top of another one, getting the offsetX and offsetY relative to that one instead.
What you can do is use MouseEvent.pageX and MouseEvent.pageY and, from that value, subtract the position of the (upper-left corner) of that canvas element, which you can get from HTMLElement.offsetLeft and HTMLElement.offsetTop:
e.pageX - imageCanvas.offsetLeft;
e.pageY - imageCanvas.offsetTop;
With this you will get the position of the cursor relative to the canvas element.
Now, you need to subtract the x and y values that you stored on dragstart, and that will give you the left and top values of the upper-left corner of the dragged image, relative to the canvas element:
image.style.left = (e.pageX - imagesCanvas.offsetLeft - x) + 'px';
image.style.top = (e.pageY - imagesCanvas.offsetTop - y) + 'px';
All together it will look like this:
let x;
let y;
let currentTarget = null;
let cloneElement = false;
function startDrag(e, clone) {
const target = e.target;
if (target.tagName === 'IMG') {
x = e.offsetX;
y = e.offsetY;
currentTarget = target;
cloneElement = clone;
}
}
function cloneImage(e) {
startDrag(e, true);
}
function moveImage(e) {
startDrag(e, false);
}
function removeImage(e) {
if (!cloneElement) {
currentTarget.remove();
}
}
function stickImage(e) {
const image = cloneElement ? currentTarget.cloneNode(true) : currentTarget;
imagesCanvas.appendChild(image);
// + 1 for the border
image.style.left = (e.pageX - imagesCanvas.offsetLeft - x + 1) + 'px';
image.style.top = (e.pageY - imagesCanvas.offsetTop - y + 1) + 'px';
currentTarget = null;
}
function allowDrag(e) {
e.preventDefault();
}
// Bind event listeners:
const imagesBarElement = document.getElementById('imagesBar');
const imagesCanvasElement = document.getElementById('imagesCanvas');
document.addEventListener('dragenter', allowDrag);
document.addEventListener('dragover', allowDrag);
imagesBarElement.addEventListener('dragstart', cloneImage);
imagesBarElement.addEventListener('drop', removeImage);
imagesCanvasElement.addEventListener('dragstart', moveImage);
imagesCanvasElement.addEventListener('drop', stickImage);
body {
margin: 0;
font-size: 0;
display: flex;
flex-direction: column;
height: 100vh;
user-select: none;
}
img {
width: 100px;
height: 100px;
}
#imagesBar {
height: 100px;
border-bottom: 1px solid #CCC;
padding: 10px 0;
}
#imagesBar > img {
margin: 0 0 0 10px;
}
#imagesCanvas {
position: relative;
background: #EEE;
flex-grow: 1;
overflow: hidden;
}
#imagesCanvas > img {
position: absolute;
}
<div id="imagesBar">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Bartagame_fcm.jpg/1200px-Bartagame_fcm.jpg" draggable="true">
<img src="http://www.earthtimes.org/newsimage/lizard_Ngo_Van_Tri_big_281.jpg" draggable="true">
</div>
<div id="imagesCanvas"></div>

Related

Javascript (vanilla) drag and drop does not work the second time an element is dragged and dropped

I am trying to implement a drag and drop functionality using vanilla Javascript on my web app, where element gets moved to a new position within a div, once it's dragged and dropped.
But I am having an issue where I can drop the element fine the first time, but I can no longer do it the second time onwards.
After debugging, I have noticed that the first time I drop an element, it does not have any inline style (see Appendix A). But when I try and do it the second time, it now has an inline style (see Appendix B) and for some reason, I cannot chnage the values of it. That was also the case after I manually added inline style to my draggable element- I could not drop the item even the first time when I did it.
I am completely out of ideas as to what I could be doing wrong and no similar questions yielded a solution.
Thank you very much in advance for your time.
Code (Unnecessary parts ommitted)
const list = document.querySelector("#list");
const rect = list.getBoundingClientRect();
let oldLeft, oldTop, mouseXStart, mouseYStart;
function dragStart(event) {
event.dataTransfer.setData("plain/text", event.target.id);
const item = document.querySelector("#" + event.target.id);
mouseXStart = event.clientX - rect.left;
mouseYStart = event.clientY - rect.top;
oldLeft = item.style.left;
oldTop = item.style.top;
console.log(item);
}
function dragOver(event) {
event.preventDefault();
event.dataTransfer.dropEffect = "move";
}
function dropItem(event) {
event.preventDefault();
const mouseXEnd = event.clientX - rect.left;
const mouseYEnd = event.clientY - rect.top;
//Calculate by how much mouse has been moved
const newLeft = mouseXEnd - mouseXStart;
const newTop = mouseYEnd - mouseYStart;
const item = document.querySelector('#' + event.dataTransfer.getData("plain/text"));
item.style.left = oldLeft + newLeft + "px";
item.style.top = oldTop + newTop + "px";
}
#list {
position: relative;
top: 60px;
height: 600px;
width: 100%;
border: 2px solid rgb(107, 14, 14);
display: block;
}
#list>div {
position: absolute;
height: 200px;
width: 200px;
background-color: blue;
margin: 10px;
overflow: hidden;
text-align: left;
}
<div id="list" ondrop="dropItem(event)" ondragover="dragOver(event)">
<div id="test" draggable="true" ondragstart="dragStart(event)">
<button type="button"></button>
<div>
<p>Test</p>
</div>
</div>
</div>
Appendix A
console.log() output on the first dragStart() call:
<div id="test" draggable="true" ondragstart="dragStart(event)">
Appendix B
console.log() output on the second dragStart() call:
<div id="test" draggable="true" ondragstart="dragStart(event)" style="left: 853px; top: 147px;">
Problem
This code
oldLeft + newLeft + "px"
evaluated to something like
123px40px
because
oldLeft = item.style.left
returned string with px at the end
Solution
Parse the value to float
oldLeft = item.style.left ? parseFloat(item.style.left) : 0;
oldTop = item.style.top ? parseFloat(item.style.top) : 0;
const list = document.querySelector("#list");
const rect = list.getBoundingClientRect();
let oldLeft, oldTop, mouseXStart, mouseYStart;
function dragStart(event) {
event.dataTransfer.setData("plain/text", event.target.id);
const item = document.querySelector("#" + event.target.id);
mouseXStart = event.clientX - rect.left;
mouseYStart = event.clientY - rect.top;
oldLeft = item.style.left ? parseFloat(item.style.left) : 0;
oldTop = item.style.top ? parseFloat(item.style.top) : 0;
}
function dragOver(event) {
event.preventDefault();
event.dataTransfer.dropEffect = "move";
}
function dropItem(event) {
event.preventDefault();
const mouseXEnd = event.clientX - rect.left;
const mouseYEnd = event.clientY - rect.top;
//Calculate by how much mouse has been moved
const newLeft = mouseXEnd - mouseXStart;
const newTop = mouseYEnd - mouseYStart;
const item = document.querySelector('#' + event.dataTransfer.getData("plain/text"));
item.style.left = oldLeft + newLeft + "px";
item.style.top = oldTop + newTop + "px";
}
#list {
position: relative;
top: 60px;
height: 600px;
width: 100%;
border: 2px solid rgb(107, 14, 14);
display: block;
}
#list>div {
position: absolute;
height: 200px;
width: 200px;
background-color: blue;
margin: 10px;
overflow: hidden;
text-align: left;
}
<div id="list" ondrop="dropItem(event)" ondragover="dragOver(event)">
<div id="test" draggable="true" ondragstart="dragStart(event)">
<button type="button"></button>
<div>
<p>Test</p>
</div>
</div>
</div>

How to put symbol or text into an image's clicked position

I am trying to implement something like this, a predefined symbol or text should be putted on a image where clicked. Suppose there is an image and I had clicked on the top right corner of that image. Now I want to show something on that clicked position.
I can get the coordinate of the clicked position. But I am not getting how I can put something on that place using this coordinate.
This is what I had tried.
HTML code :
<img src="result.png" alt="" id="image">
JS code:
$('#image').click(function (e) {
var posX = $(this).position().left,
posY = $(this).position().top,
positionX = e.pageX - posX,
positionY = e.pageY - posY;
$("#image").html('<p id="clicked">Clicked here</p>');
});
You are trying to set the html of an image element that is clicked. You do nothing with the x and y position of the element.
You need to append an element and set the position.
$('#myDiv').on("click", "img", function (e) {
var wrapper = $(this).parent(),
position = wrapper.offset(),
posX = position.left,
posY = position.top,
positionX = Math.floor(e.pageX - posX),
positionY = Math.floor(e.pageY - posY),
marker = $('<p class="clicked">Clicked here</p>');
marker.css({top: positionY + "px", left: positionX + "px"})
wrapper.append(marker);
});
#myDiv {
position: relative;
border: 1px solid green;
}
#myDiv p {
position: absolute;
color: rgb(0, 255, 255);
mix-blend-mode: difference;
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Example</h1>
<div id="myDiv">
<img src="http://placekitten.com/g/400/300" alt="">
</div>
Consider an alternative solution.
$(function() {
$.fn.setMarker = function(e, o) {
if (o == undefined) {
o = $("<p>", {
class: "clicked"
}).html("Clicked Here");
}
var self = $(this);
var marker = o.appendTo(self.parent()).css({
top: (e.pageY - self.offset().top) + "px",
left: (e.pageX - self.offset().left) + "px"
});
}
$('#myDiv-1').on("click", "img", function(e) {
$(this).setMarker(e);
});
});
#myDiv-1 {
position: relative;
border: 1px solid green;
}
#myDiv-1 p {
position: absolute;
color: rgb(0, 255, 255);
mix-blend-mode: difference;
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Example</h1>
<div id="myDiv-1">
<img src="http://placekitten.com/g/400/300" alt="">
</div>
This adds the function as a jQuery extension basically. If you like, you can modify the function to pass in an jQuery Object or Element to add as the marker.

How to center the whole image comparison slider

When I manage to move the image comparison slider, the actual 'slider' left behind. The slider JS code is from https://www.w3schools.com/howto/howto_js_image_comparison.asp
and can be easily inspect there but I will paste the code in here too.
I have tried to move the slider with Css grid but the as mentioned before the slider icon won't move with the images.
function initComparisons() {
var x, i;
/* Find all elements with an "overlay" class: */
x = document.getElementsByClassName("img-comp-overlay");
for (i = 0; i < x.length; i++) {
/* Once for each "overlay" element:
pass the "overlay" element as a parameter when executing the compareImages function: */
compareImages(x[i]);
}
function compareImages(img) {
var slider, img, clicked = 0, w, h;
/* Get the width and height of the img element */
w = img.offsetWidth;
h = img.offsetHeight;
/* Set the width of the img element to 50%: */
img.style.width = (w / 2) + "px";
/* Create slider: */
slider = document.createElement("DIV");
slider.setAttribute("class", "img-comp-slider");
/* Insert slider */
img.parentElement.insertBefore(slider, img);
/* Position the slider in the middle: */
slider.style.top = (h / 2) - (slider.offsetHeight / 2) + "px";
slider.style.left = (w / 2) - (slider.offsetWidth / 2) + "px";
/* Execute a function when the mouse button is pressed: */
slider.addEventListener("mousedown", slideReady);
/* And another function when the mouse button is released: */
window.addEventListener("mouseup", slideFinish);
/* Or touched (for touch screens: */
slider.addEventListener("touchstart", slideReady);
/* And released (for touch screens: */
window.addEventListener("touchstop", slideFinish);
function slideReady(e) {
/* Prevent any other actions that may occur when moving over the image: */
e.preventDefault();
/* The slider is now clicked and ready to move: */
clicked = 1;
/* Execute a function when the slider is moved: */
window.addEventListener("mousemove", slideMove);
window.addEventListener("touchmove", slideMove);
}
function slideFinish() {
/* The slider is no longer clicked: */
clicked = 0;
}
function slideMove(e) {
var pos;
/* If the slider is no longer clicked, exit this function: */
if (clicked == 0) return false;
/* Get the cursor's x position: */
pos = getCursorPos(e)
/* Prevent the slider from being positioned outside the image: */
if (pos < 0) pos = 0;
if (pos > w) pos = w;
/* Execute a function that will resize the overlay image according to the cursor: */
slide(pos);
}
function getCursorPos(e) {
var a, x = 0;
e = e || window.event;
/* Get the x positions of the image: */
a = img.getBoundingClientRect();
/* Calculate the cursor's x coordinate, relative to the image: */
x = e.pageX - a.left;
/* Consider any page scrolling: */
x = x - window.pageXOffset;
return x;
}
function slide(x) {
/* Resize the image: */
img.style.width = x + "px";
/* Position the slider: */
slider.style.left = img.offsetWidth - (slider.offsetWidth / 2) + "px";
}
}
}
initComparisons();
.img-comp-container {
margin:auto;
position: relative;
height: 100vh;
width: 100vw
}
.img-comp-img {
position: absolute;
width: auto;
height: auto;
overflow:hidden;
}
.img-comp-img img {
display: block;
vertical-align: middle;
}
.img-comp-slider {
position: absolute;
z-index: 9;
cursor: ew-resize;
width: 0;
height: 0;
border-style: solid;
border-width: 9px 0 9px 14px;
border-color: transparent transparent transparent #ffffff;
}
<div class="img-comp-container">
<div class="img-comp-img">
<img src="img/ysl_before.jpg" width="650" height="450">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="img/ysl_after.jpg" width="650" height="450">
</div>
</div>
I believe this fixes what you are looking for:
Wrap the existing container in another div (img-comp-outer-container), remove margin from img-comp-container and set height/width of img-comp-container to auto.
You can then style the outer container to align the component how you like
<div class="img-comp-outer-container"> <!--new div -->
<div class="img-comp-container">
<div class="img-comp-img">
<img src="img_snow.jpg" width="650" height="450">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="img_forest.jpg" width="650" height="450">
</div>
</div>
</div> <!--new div end -->
.img-comp-outer-container {
/* add your styles to move around component */
}
.img-comp-container {
/* margin: auto; */
position: relative;
height: auto; /* was 100vh */
width: auto; /* was 100vw */
}
I wanted to bring the two images, that I'm comparing using image compare slider to the center of the page. The code available on W3Schools to compare images using slider but there was not suggestion about centering it. So what I did was I placed div id box and added all other classes into it and styled the box as white with height and width and added float-right to the img-comp-container. You can change the width and height of box accordingly to center the slider.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {box-sizing: border-box;}
.img-comp-container {
float: right; /*new change*/
position: relative;
height: 200px; /*should be the same height as the images*/
}
.img-comp-img {
position: absolute;
width: auto;
height: auto;
overflow:hidden;
}
.img-comp-img img {
display:block;
vertical-align:middle;
}
.img-comp-slider {
position: absolute;
z-index:9;
cursor: ew-resize;
/*set the appearance of the slider:*/
width: 40px;
height: 40px;
background-color: #2196F3;
opacity: 0.7;
border-radius: 50%;
}
/*new change*/
#box{
background: white;
width: 150px;
height: 200px;
}
</style>
<script>
function initComparisons() {
var x, i;
/*find all elements with an "overlay" class:*/
x = document.getElementsByClassName("img-comp-overlay");
for (i = 0; i < x.length; i++) {
/*once for each "overlay" element:
pass the "overlay" element as a parameter when executing the compareImages function:*/
compareImages(x[i]);
}
function compareImages(img) {
var slider, img, clicked = 0, w, h;
/*get the width and height of the img element*/
w = img.offsetWidth;
h = img.offsetHeight;
/*set the width of the img element to 50%:*/
img.style.width = (w / 2) + "px";
/*create slider:*/
slider = document.createElement("DIV");
slider.setAttribute("class", "img-comp-slider");
/*insert slider*/
img.parentElement.insertBefore(slider, img);
/*position the slider in the middle:*/
slider.style.top = (h / 2) - (slider.offsetHeight / 2) + "px";
slider.style.left = (w / 2) - (slider.offsetWidth / 2) + "px";
/*execute a function when the mouse button is pressed:*/
slider.addEventListener("mousedown", slideReady);
/*and another function when the mouse button is released:*/
window.addEventListener("mouseup", slideFinish);
/*or touched (for touch screens:*/
slider.addEventListener("touchstart", slideReady);
/*and released (for touch screens:*/
window.addEventListener("touchend", slideFinish);
function slideReady(e) {
/*prevent any other actions that may occur when moving over the image:*/
e.preventDefault();
/*the slider is now clicked and ready to move:*/
clicked = 1;
/*execute a function when the slider is moved:*/
window.addEventListener("mousemove", slideMove);
window.addEventListener("touchmove", slideMove);
}
function slideFinish() {
/*the slider is no longer clicked:*/
clicked = 0;
}
function slideMove(e) {
var pos;
/*if the slider is no longer clicked, exit this function:*/
if (clicked == 0) return false;
/*get the cursor's x position:*/
pos = getCursorPos(e)
/*prevent the slider from being positioned outside the image:*/
if (pos < 0) pos = 0;
if (pos > w) pos = w;
/*execute a function that will resize the overlay image according to the cursor:*/
slide(pos);
}
function getCursorPos(e) {
var a, x = 0;
e = e || window.event;
/*get the x positions of the image:*/
a = img.getBoundingClientRect();
/*calculate the cursor's x coordinate, relative to the image:*/
x = e.pageX - a.left;
/*consider any page scrolling:*/
x = x - window.pageXOffset;
return x;
}
function slide(x) {
/*resize the image:*/
img.style.width = x + "px";
/*position the slider:*/
slider.style.left = img.offsetWidth - (slider.offsetWidth / 2) + "px";
}
}
}
</script>
</head>
<body>
<h1>Compare Two Images</h1>
<p>Click and slide the blue slider to compare two images:</p>
<div id="box">/*new change*/
<div class="img-comp-container">
<div class="img-comp-img">
<img src="img_snow.jpg" width="300" height="200">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="img_forest.jpg" width="300" height="200">
</div>
</div>
</div>
<script>
/*Execute a function that will execute an image compare function for each element with the img-comp-overlay class:*/
initComparisons();
</script>
</body>
</html>

How to drag or move a span into the Div by using javascript

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">&#x1F603</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

How to get the start value and end value of a div after dragging

Hi i have a div which is draggable .My requirement is
1. I want the start value and end value of the div after dragging in a text box
2.Now its is only drag in right side only i want it drag also from left side of the div
i tried some steps but it is not perfect because the value is not displaying and the dragging from left is not working middle table is my parent div
$(function () {
var container = $('.middletablediv'),
base = null,
handle = $('.handle'),
isResizing = false,
screenarea = screen.width;
handle.on('mousedown', function (e) {
base = $(this).closest(".scalebar");
isResizing = true;
lastDownX = e.clientX;
offset = $(this).offset();
xPos = offset.left;
});
$(document).on('mousemove', function (e) {
// we don't want to do anything if we aren't resizing.
if (!isResizing)
return;
p = parseInt(e.clientX - base.offset().left),
// l = parseInt(p * (3 / 11));
base.css('width', p);
k = parseInt(xPos - base.offset().left);
$("#startvalue").value(k)
$("#stopvalue").value(p)
}).on('mouseup', function (e) {
// stop resizing
isResizing = false;
});
});
.handle{
position: absolute;
top:1px;
right: 0;
width: 10px;
height: 5px;
cursor: w-resize;
}
.middletablediv{
float:left;
width:35%;
}
.scalebar{
margin-top: 13px;
height: 7px;
position: relative;
width:20px;
background-color: green; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="middletablediv">
<div id="newvalue1" class="scalebar">
<div class="handle" style="left:0"></div> <div class="handle"></div>
</div>
</div>
<input id="startvalue" type="text">startvalue</input>
<input id="stopvalue" type="text" />stopvalue</input>
how i solve this issue
You should use val() instead of value(). Also, the way dragging works the end value can be smaller than the start value, so I added a couple of things to handle that problem in a simple way (just switch values). Finally, to drag from the left, you should handle the left dragging differently, so I gave the left handle a unique id and also padded the whole parent div a bit to make it more apparent.
$(function () {
var container = $('.middletablediv'),
base = null,
handle = $('.handle'),
isResizing = false,
isLeftDrag = false;
screenarea = screen.width;
handle.on('mousedown', function (e) {
base = $(this).closest(".scalebar");
isResizing = true;
if($(this).attr('id')=='lefthandle')isLeftDrag=true;
else isLeftDrag=false;
lastDownX = e.clientX;
offset = $(this).offset();
xPos = offset.left;
});
$(document).on('mousemove', function (e) {
// we don't want to do anything if we aren't resizing.
if (!isResizing)
return;
if(isLeftDrag){
p = parseInt(base.offset().left - e.clientX);
k = parseInt(base.offset().left - xPos);
base.css('margin-left',-p);
base.css('width',p);
}
else{
p = parseInt(e.clientX - base.offset().left),
// l = parseInt(p * (3 / 11));
base.css('width', p);
k = parseInt(xPos - base.offset().left);
}
//if(k>p){var temp = k; k = p; p = temp;}
$("#startvalue").val(k)
$("#stopvalue").val(p)
}).on('mouseup', function (e) {
// stop resizing
isResizing = false;
});
});
.handle{
position: absolute;
top:1px;
right: 0;
width: 10px;
height: 5px;
cursor: w-resize;
}
.middletablediv{
float:left;
width:35%;
}
.scalebar{
margin-top: 13px;
height: 7px;
position: relative;
width:20px;
background-color: green; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="middletablediv" style="padding-left:100px; overflow:visible;">
<div id="newvalue1" class="scalebar">
<div class="handle"id="lefthandle" style="left:0"></div> <div class="handle"></div>
</div>
</div><br><br>
<input id="startvalue" type="text">startvalue</input>
<input id="stopvalue" type="text" />stopvalue</input>

Categories

Resources