Draggable editable field - javascript

I want to have an editable field that I can drag and drop. Here is my code (the red div is the drop zone) :
function drag(ev) {
let targetId = ev.target.id;
let rect = document.getElementById(targetId).getBoundingClientRect();
ev.dataTransfer.setData("targetId", targetId);
let offsetX = ev.clientX - rect.left;
let offsetY = ev.clientY - rect.top;
ev.dataTransfer.setData("offsetX", offsetX);
ev.dataTransfer.setData("offsetY", offsetY);
}
function drop(ev) {
let targetId = ev.dataTransfer.getData("targetId");
let offsetX = parseInt(ev.dataTransfer.getData("offsetX"));
let offsetY = parseInt(ev.dataTransfer.getData("offsetY"));
let dropX = ev.clientX - offsetX;
let dropY = ev.clientY - offsetY;
let el = document.getElementById(targetId);
el.style.left = dropX + "px";
el.style.top = dropY + "px";
ev.preventDefault();
}
function allowDrop(ev) {
ev.preventDefault();
}
.item {
min-width: 25px;
position: absolute;
border: solid;
background: white;
}
#item1 {
padding: 3px;
}
#drop-zone {
width: 300px;
height: 200px;
background: red;
border: solid;
}
<div id="drop-zone" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<span class="item" contenteditable="true" draggable="true" ondragstart="drag(event)">Item1</span>
<br><br>
<div id="item1" class="item" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Item2</span>
</div>
I made 2 tests. My first test is Item1, where the <span> itself is draggable. Unfortunately, the browser cannot differenciate between "place the cursor" and "drag the element", so Item1 is not draggable.
Then my idea was to have a border around the field on which we would click to grab the element, so I made Item2 where I put the <span> in a containing <div>. But now the problem is that, as the div is draggable, the span also is draggable, but I want to place the cursor freely in the span, and when I click on the span to write some text, the cursor is always at the beginning. How should I do ?
Note : when I remove the padding: 3px line, Item2 doesn't work.
Thank you for your help.

Related

How to let the coodinates of the cursor follow the cursor when hovering over a rectangle?

The following code always shows the coordinates of the cursor below the cursor:
function showCoords(e) {
var x = event.clientX;
var y = event.clientY;
var coor = "(" + x + ", " + y + ")";
document.getElementById("box").innerHTML = coor;
var bx = document.getElementById("box");
bx.style.left = e.pageX - 50;
bx.style.top = e.pageY + 20;
}
function clearCoords() {
document.getElementById("box").innerHTML = "";
}
div.relative {
position: relative;
width: 400px;
height: 300px;
border: 1px solid black;
}
div.abs {
position: absolute;
top: 100px;
right: 50px;
width: 200px;
height: 100px;
background-color: yellow;
}
<body onmousemove="showCoords(event)">
<div class="relative">
<div class="abs" onmousemove="showCoords(event)" onmouseout="clearCoords()"></div>
</div>
<div id="box" style="width:100px; height:30px; position:absolute"></div>
</body>
I only want the coordinates to be visible when the mouse pointer is hovering over the yellow rectangle.
If I change <body onmousemove="showCoords(event)"> to <body>, the coordinates are never visible.
How do I get the coordinates be visible only when hovering over the yellow rectangle?
Move the onmousemove listener from the body to the element you want to listen on - div.abs in this case.
I'd recommend not using the onmousemove attribute, in favour of using an entirely javascript solution - just to keep javascript-y things together. Something like (untested)
var listenOn = document.querySelector(".abs");
listenOn.addEventListener("mousemove", ShowCoords);

Adjacent div's children needs to be level vertically

There are 3 Vertical divs, as shown in the picture. There are some child divs inside each div that are shown by blue rectangles. I need the children divs to be level vertically. How can I do it?
As they said, in pure css/html is not possible if they are in separated containers.
Using javascript you can first create the 'base' element (in this case, the inner divs of the center column), save its coord and then create the side ones and pos them with the saved coords.
This is a rough example, but can give the idea
for (let i = 1; i < 10; i++) {
//Create the center column element first, from where to get the Y pos
let elem2 = document.createElement('div');
elem2.style.width = 'calc(100% - 10px)';
elem2.style.height = '50px';
elem2.style.margin = '5px';
elem2.style.background = 'lightblue';
document.querySelector('.col2').append(elem2);
let coords = elem2.getBoundingClientRect(); //Getting coords data
//creating first column elem
let elem1 = document.createElement('div');
elem1.style.position = 'absolute';
elem1.style.top = coords.top + 'px'; //use de y pos from above
elem1.style.width = 'calc(100% - 10px)';
elem1.style.height = '25px';
elem1.style.margin = '0 5px';
elem1.style.background = 'pink';
document.querySelector('.col1').append(elem1);
//creating third column elem
let elem3 = document.createElement('div');
elem3.style.position = 'absolute';
elem3.style.top = coords.top + 'px'; //use de y pos from above
elem3.style.width = 'calc(100% - 10px)';
elem3.style.height = '25px';
elem3.style.margin = '0 5px';
elem3.style.background = 'lightgreen';
document.querySelector('.col3').append(elem3);
}
body,
html {
margin: 0;
padding: 0;
background: lightyellow
}
.container {
display: flex;
}
.col1 {
position: relative;
width: 75px;
border: 2px solid red
}
.col2 {
position: relative;
flex-grow: 1;
border: 2px solid blue
}
.col3 {
position: relative;
width: 150px;
border: 2px solid green
}
<div class="container">
<div class="col1">
</div>
<div class="col2">
</div>
<div class="col3">
</div>
</div>

Javascript moving element to mouse click position, element not responding

I'm trying to get my png to move to the mouse click position when the user clicks within the container but I cant get the png to respond. I'm following this tutorial (https://www.youtube.com/watch?v=b4GwvdhrEQg), and stuck on the first test. my target doesnt respond to clicks at all.
Please help
var theGirl = document.querySelector("#girl");
var container = document.querySelector("#floor");
container.addEventListener("click", getClickPosition, false);
function getClickPosition(e) {
var xPosition = e.clientX - (theGirl.offsetWidth / 2);
var yPosition = e.clientY; - (theGirl.offsetHeight / 2)
var translate3dValue = "translate3d(" + xPosition + "px" + yPosition + "px, 0)";
theGirl.style.transform = translate3dValue;
}
#floor {
width: 700px;
height: 600px;
cursor: pointer;
overflow: visible;
border: 10px #EDEDED solid;
}
#girl {
height: 450px;
width: 200px;
border: 15px red solid;
transform: translate3d(50px, 50px, 0);
}
<body>
<div id="floor">
<div>
<img src="girl.png" id="girl"> </div>
</div>
Change #girl's position to absolute. I think it works after that.

When I try to create two slider boxes on the same page, it doesn't work

Source
I tried creating table and copying the html over and it didn't work. I'm trying to create some before and afters. I'm not 100% on Javascript, but I'm thinking there is something in there preventing it.
Sorry I have to link to the code. It would not let me post with so much copypasta'd code.
Example of sliders working using the same HTML except for the images. Added table and removed CSS that was sizing 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";
}
}
}
/*Execute a function that will execute an image compare function for each element with the img-comp-overlay class:*/
initComparisons();
div[class^="img-comp-container"] {
position: relative;
}
* {
box-sizing: border-box;
}
.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%;
}
<table class="cool" cellpadding="10">
<tr>
<td width="500">
<div class="img-comp-container1">
<div class="img-comp-img">
<img src="http://placekitten.com/500/400" width="500" height="400">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="http://placebear.com/500/400" width="500" height="400">
</div>
</div>
</td>
<td>
<div class="img-comp-container2">
<div class="img-comp-img">
<img src="http://placekitten.com/500/300" width="500" height="300">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="http://baconmockup.com/500/300/" width="500" height="300">
</div>
</div>
</td>
</tr>
</table>

move a large div opposite to mouse movement

I have a table full of data that tends to be larger than the screen.
I put the table in a DIV and set the "overflow" to "auto" in CSS
div.scrolling-comps {
width : 970px;
height : 800px;
overflow : auto;
}
So the DIV can be scrolled up/down, left right using the browser's built-in scroll bars.
Problem is, the table can be WAAY bigger than the screen. And while the mousewheel will scroll it up/down, scrolling left/right is a pain in the hooch.
So, looking for a javascript/jquery or CSS way to scroll the div NATURALLY.
In other words, when someone viewing the huuuge table moves their mouse to the right, the DIV goes to the left (thus scrolling without using the scroll bars).
Something similar to this, but instead of following the mouse, the div would move opposite the mouse...
window.onload = function() {
var bsDiv = document.getElementById("box-shadow-div");
var x, y;
// On mousemove use event.clientX and event.clientY to set the location of the div to the location of the cursor:
window.addEventListener('mousemove', function(event) {
x = event.clientX;
y = event.clientY;
if (typeof x !== 'undefined') {
bsDiv.style.left = x + "px";
bsDiv.style.top = y + "px";
}
}, false);
}
#box-shadow-div {
position: fixed;
width: 1000px;
height: 800px;
border-radius: 0%;
background-color: black;
box-shadow: 0 0 10px 10px black;
top: 49%;
left: 48.85%;
}
<div id="box-shadow-div"></div>
The example you have about using the mouse position is interesting... But it is not what you need to achieve what you described.
In fact... What you need to know is the "ratio" between the div wrapping the table and its scrollWidth
Then, using the X position of the mouse, you can apply a scroll to the div in order to make it "move".
I used jQuery to do it using very few lines.
// Just to fake a big table
var fakeCell = $("<td>Some data</td>");
for(i=0;i<100;i++){
var fakeRow = $("<tr>");
for(k=0;k<50;k++){
fakeRow.append(fakeCell.clone().append(" "+k));
}
$("#test").append(fakeRow.clone());
}
// ---------------------------------------------------
// Calculate the "ratio" of the box-div width versus its scrollable width
var ratio = $("#box-div")[0].scrollWidth / $("#box-div").width();
console.log("Ratio: "+ratio);
// Scroll left/rigth based on mouse movement
$(window).on("mousemove", function(e){
var X = ratio * e.pageX;
// Scroll the div using the mouse position multiplyed by the ratio
$("#box-div").scrollLeft(X);
});
td{
white-space: nowrap;
border: 1px solid black;
}
#box-div{
overflow:auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="box-div">
<table id="test">
</table>
</div>
</body>
So while the user moves the mouse over the div's width, you apply a scroll multiplied by the ratio... The effect is the user can scroll it all from the most left to most right ends easilly.
How about this?
wrap a table in div (i.e. parent-div) which is relatively positioned
Give position absolute to the target div.
And change left & top position of target div on mousemove event.
window.onload = function() {
var bsDiv = document.getElementById("box-shadow-div");
var x, y;
// On mousemove use event.clientX and event.clientY to set the location of the div to the location of the cursor:
window.addEventListener('mousemove', function(event) {
x = event.clientX;
y = event.clientY;
if (typeof x !== 'undefined') {
bsDiv.style.left = -x + "px";
bsDiv.style.top = -y + "px";
}
}, false);
}
.parent-div {
position: relative;
}
#box-shadow-div {
position: absolute;
width: 1000px;
height: 800px;
border-radius: 0%;
background-color: black;
box-shadow: 0 0 10px 10px black;
top: 0;
left: 0;
}
<div class="parent-div">
<div id="box-shadow-div"></div>
</div>
Have you tried changing x to -x? this will technically "invert" the effect.
window.onload = function() {
var bsDiv = document.getElementById("box-shadow-div");
var x, y;
// On mousemove use event.clientX and event.clientY to set the location of the div to the location of the cursor:
window.addEventListener('mousemove', function(event) {
x = event.clientX;
y = event.clientY;
if (typeof x !== 'undefined') {
bsDiv.style.left = -x + "px";
bsDiv.style.top = -y + "px";
}
}, false);
}
#box-shadow-div {
position: fixed;
width: 1000px;
height: 800px;
border-radius: 0%;
background-color: black;
box-shadow: 0 0 10px 10px black;
top: 49%;
left: 48.85%;
}
<div id="box-shadow-div"></div>

Categories