I have the following working code (also see this fiddle):
<!DOCTYPE HTML>
<html>
<head>
<style>
#div1 {width:350px;height:170px;padding:10px;border:1px solid #aaaaaa;}
#drag1 {width:50px;height:50px;padding:10px;border:1px solid #000;background-color: #f00; position: absolute;}
</style>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text/html", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text/html");
ev.target.appendChild(document.getElementById(data));
//window.alert( ev.clientX + ',' + ev.clientY);
document.getElementById("drag1").style.left = ev.clientX + 'px';
document.getElementById("drag1").style.top = ev.clientY + 'px';
return false;
}
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<div id="drag1" draggable="true" ondragstart="drag(event)"></div>
</div>
</body>
</html>
Here you can drag and drop a colored div only inside the main div. The problem is that this red div jumps a bit from his dropped position. I think this is because I use the mouse ev.clientX and Y. So how can I fix this so the DIV stays at the dropped position?
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text/html", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text/html");
ev.target.appendChild(document.getElementById(data));
//window.alert( ev.clientX + ',' + ev.clientY);
document.getElementById("drag1").style.left = ev.clientX + 'px';
document.getElementById("drag1").style.top = ev.clientY + 'px';
return false;
}
#div1 {width:350px;height:170px;padding:10px;border:1px solid #aaaaaa;}
#drag1 {width:50px;height:50px;padding:10px;border:1px solid #000;background-color: #f00; position: absolute;}
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<div id="drag1" draggable="true" ondragstart="drag(event)"></div>
</div>
You're dropping the div's top left corner to the mouse's location, you have to find the offset from inside the div where the mouse is actually dragging. By checking the event object(in chrome), offsetX and offsetY and layerX and layerY seem to have the offset from the origin of the div to the mouse.
Here is a question with alot of discussion on offsetXY and layerXY and associated properties event.offsetX in Firefox, note: don't just read the accepted answer.
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("application/json",
JSON.stringify([ev.target.id,
(ev.offsetX || ev.clientX - $(ev.target).offset().left),
(ev.offsetY || ev.clientY - $(ev.target).offset().top)]
));
}
function drop(ev) {
ev.preventDefault();
var data = JSON.parse(ev.dataTransfer.getData("application/json"));
ev.target.appendChild(document.getElementById(data[0]));
//window.alert( ev.clientX + ',' + ev.clientY);
document.getElementById("drag1")
.style.left = ev.clientX - data[1] + 'px';
document.getElementById("drag1").style.top = ev.clientY - data[2] + 'px';
return false;
}
#div1 { width:350px; height:170px; padding:10px; border:1px solid #aaaaaa; }
#drag1 { width:50px; height:50px; padding:10px; border:1px solid #000; background-color: #f00; position: absolute; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<div id="drag1" draggable="true" ondragstart="drag(event)"></div>
</div>
Related
I have created a drag and drop application which contains left and right panel. When I drag the ball from left panel to right panel the ball is dragged. But the problem is here when I drag the ball the ball should not be removed from left panel while dragging it.Again it only should be dragged/move to right panel,and should not go back to left panel.Here is the code below
let currentDroppable = null;
ball.onmousedown = function(event) {
let shiftX = event.clientX - ball.getBoundingClientRect().left;
let shiftY = event.clientY - ball.getBoundingClientRect().top;
ball.style.position = 'absolute';
ball.style.zIndex = 1000;
document.body.append(ball);
moveAt(event.pageX, event.pageY);
function moveAt(pageX, pageY) {
ball.style.left = pageX - shiftX + 'px';
ball.style.top = pageY - shiftY + 'px';
}
function onMouseMove(event) {
moveAt(event.pageX, event.pageY);
ball.hidden = true;
let elemBelow = document.elementFromPoint(event.clientX, event.clientY);
ball.hidden = false;
if (!elemBelow) return;
let droppableBelow = elemBelow.closest('.droppable');
if (currentDroppable != droppableBelow) {
if (currentDroppable) { // null when we were not over a droppable before this event
leaveDroppable(currentDroppable);
}
currentDroppable = droppableBelow;
if (currentDroppable) { // null if we're not coming over a droppable now
// (maybe just left the droppable)
enterDroppable(currentDroppable);
}
}
}
document.addEventListener('mousemove', onMouseMove);
ball.onmouseup = function() {
document.removeEventListener('mousemove', onMouseMove);
ball.onmouseup = null;
};
};
function enterDroppable(elem) {
elem.style.background = 'pink';
}
function leaveDroppable(elem) {
elem.style.background = '';
}
ball.ondragstart = function() {
return false;
};
#gate {
cursor: pointer;
margin-bottom: 100px;
width: 83px;
height: 46px;
border: 1px solid;
}
#ball {
cursor: pointer;
width: 40px;
height: 40px;
}
<div style="float:left;border: 1px solid;width: 15%;">Left Pannel<img src="https://en.js.cx/clipart/ball.svg" id="ball"></div>
<div style="float: left;border: 1px solid;width: 80%;height: 1000px;">Right Panel</div>
<head>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>
<div style="float:left;border: 1px solid;width: 15%;" id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
Left Pannel
<img id="ball" src="https://en.js.cx/clipart/ball.svg" draggable="true" ondragstart="drag(event)">
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"
style="float: left;border: 1px solid;width: 80%;height: 1000px;">Right Panel</div>
</body>
i am working on my game but i have some problems...
1. if the image is in the class .room it has a another src but if you drop it in the class .items it should change to a icon. And if you drag it again to .room it will turn back.
2. There are many different image so i want to have a switch. if the draged objekt is dragging to .items the image should change. so the id of the image should go to the switch and check if the id and case is the same. the scr should be from the icon.
3. if it is possible i want to safe the id of the image in local.storage so i can use the objekt in the next page
<html>
<head>
<style>
.room {
width: 500px;
height: 150px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
.items {
width: 500px;
height: 150px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
</style>
<script>
function allowDrop(ev) {
if (ev.target.className === "items") {
ev.target.style.border = "3px dashed black";
}
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("img", ev.target.id);
}
function dragleave(ev) {
if (ev.target.className === "items") {
ev.target.style.border = "0px dashed transparent";
}
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("img");
ev.target.style.border = "0px dashed transparent";
if (ev.target=="[object HTMLImageElement]"){
ev.target = ev.target.parentNode;
}
else {
ev.target.appendChild(document.getElementById(data));
}
if (ev.target.id === ev.dataTransfer.getData("ori")) {
return;
}
var image = document.createElement("img");
image.id =
image.draggable = true;
image.addEventListener('dragstart', drag);
if (ev.target.className === 'items') {
icon();
} else if (ev.target.className === 'room') {
room();
}
var originEle = document.getElementById(ev.dataTransfer.getData("ori"));
originEle.outerHTML = '';
delete originEle;
ev.target.appendChild(image);
}
function icon(){
switch(image.id) {
case "teddy": image.src="pic/Icons/teddy.png";break;
case "book": image.src="pic/Icons/Buch.png";break;
}
}
function room(){
switch(image.id) {
case "teddy": image.src= "pic/Home/HomeRoom_booksL.png";break;
case "booksR": image.src= "pic/Home/HomeRoom_buch.png";break;}
}
function reset(){
var container = document.getElementById("field");
container.innerHTML= html;
}
var html;
window.onload = function(){
html = document.getElementById('field').innerHTML;
};
</script>
</head>
<body>
<h2>Drag and Drop</h2>
<div>
<div class="room" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>
<h2>items</h2>
<div class="items" ondrop="drop(event)" ondragover="allowDrop(event)">
<img id="book" src="pic/Icons/Buch.png" draggable="true" ondragstart="drag(event)" id="drag1">
<img id="teddy" alt="booksL"src="pic/Home/HomeRoom_teddy.png" id="drag2" draggable="true" ondragstart="drag(event)" >
</div>
</div>
</body>
</html>
About the 3rd question - saving to localStorage:
add the code below to your drop function.
localStorage.setItem("name", data);
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.
I have three buttons for instance. On hover each I calculate the x and y axis of the mouse using jQuery and show a border to the hovered element. For individual elements, the hovering works fine. But for child elements, only the parent element shows border. The code used for the sample.
$(document).ready(function(){
$(document).mousemove(function(event){
$(".button").removeClass('active')
$('.button').each(function(){
var position = $(this).position();
var width = $(this).width()
var height = $(this).height()
var x1 = position.left
var y1 = position.top
var x2 = x1+width
var y2 = y1+height
if (event.pageX > x1 && event.pageX < x2 && event.pageY > y1 && event.pageY < y2){
$("span").text(event.pageX + ", " + event.pageY);
$(this).addClass('active')
}
});
});
});
.button{
width:150px;
height:35px;
display:block;
position:absolute;
pointer-events: none;
border:1px solid transparent;
}
.button.x{ top:10%; left;35%;}
.button.y{top:40%; left;35%;}
.button.z{top:20%; left;35%;}
.button.active{
border-color:blue;
pointer-events: auto;
border:1px solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="button x">
Hello
<div class="button y">
Hello
</div>
</div>
<div class="button z">
Hello
</div>
<span></span>
It's a common mistake, due in part to the naming of the jQuery methods involved (IMHO). You're using position ("Get the current coordinates...relative to the offset parent.") where you want to use offset ("Get the current coordinates...relative to the document."):
var position = $(this).offset();
Updated Example (easiest to see if you hit the Full Page link) (I've also added backgrounds to the nested elements and tweaked the border that gets added, to make it clearer when the mouse is over them):
$(document).ready(function(){
$(document).mousemove(function(event){
$(".button").removeClass('active')
$('.button').each(function(){
var position = $(this).offset();
var width = $(this).width()
var height = $(this).height()
var x1 = position.left
var y1 = position.top
var x2 = x1+width
var y2 = y1+height
if (event.pageX > x1 && event.pageX < x2 && event.pageY > y1 && event.pageY < y2){
$("span").text(event.pageX + ", " + event.pageY);
$(this).addClass('active')
}
});
});
});
.button{
width:150px;
height:35px;
display:block;
position:absolute;
pointer-events: none;
border:1px solid transparent;
}
.button.x{ top:10%; left;35%;}
.button.y{top:40%; left;35%;}
.button.z{top:20%; left;35%;}
.button.active{
pointer-events: auto;
border:2px solid red;
}
.button.x {
background-color: #00d;
}
.button.y {
background-color: #0d0;
}
<div class="button x">
Hello
<div class="button y">
Hello
</div>
</div>
<div class="button z">
Hello
</div>
<span></span>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
Or do it with CSS:
.button:hover {
border-color:blue;
pointer-events: auto;
border:1px solid;
}
(And remove pointer-events: none; from .button.)
Live Example (with the same visibility tweaks):
.button{
width:150px;
height:35px;
display:block;
position:absolute;
/*pointer-events: none;*/
border:1px solid transparent;
}
.button.x{ top:10%; left;35%;}
.button.y{top:40%; left;35%;}
.button.z{top:20%; left;35%;}
.button:hover {
pointer-events: auto;
border:2px solid red;
}
.button.x {
background-color: #00d;
}
.button.y {
background-color: #0d0;
}
<div class="button x">
Hello
<div class="button y">
Hello
</div>
</div>
<div class="button z">
Hello
</div>
<span></span>
Im not even sure if this is possible. Im trying to change this background image:
CSS
#topnav ul li
{
height:4em;
list-style:none;
display:table-cell;
text-align:center;
background-image: url(images/libg2.png);
border: 1px solid black;
}
HTML
<div id="topnav">
<ul>
<li>blahblah</li>
<li>blahblah1</li>
<li>blahblah2</li>
<li>blahblah3</li>
<li>blahblah4</li>
</ul>
</div>
So that when you mouse over it the image changes.
I know it can be done in CSS with hover but I am trying to do it with JavaScript.
Any help would be awesome, even if its someone saying "Stop what you're trying, it wont work".
You're looking for a on.mouseover and on.mouseleave
$(document).ready(function() {
$('img').on('mouseover', function() {
$(this).attr('src', 'http://www.adventureswithwords.com/wp-content/uploads/2014/11/unhappy_face_sticker-p217427116611791537qjcl_400.jpg');
});
$('img').on('mouseleave', function() {
$(this).attr('src', 'http://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Smiley.svg/2000px-Smiley.svg.png');
});
});
img {
height: 50px;
width:50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Smiley.svg/2000px-Smiley.svg.png"/>
This gave me some idea to display Mac-alike menu:
var SCALE = 0.3;
var SIZE = 60;
$(document).ready(function() {
$('img').hover(function() {
var width = parseInt($(this).css('width'));
var widthNew = (width * (1 + SCALE)) + "px";
var height = parseInt($(this).css('height'));
var heightNew = (height * (1 + SCALE)) + "px";
$(this).animate({'width':widthNew,
'height': heightNew,
'top':'0px',
'left':'0px'},{duration:300});
},
function() {
var width = SIZE + "px";
var height = width;
$(this).animate({'width':width,
'height':height,
'top':'0px',
'left':'0px'},{duration:300});
});
});
img {
height: 60px;
width: 60px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<img src='https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xpa1/v/t1.0-1/p50x50/1456606_1460821830821643_7486511918744151887_n.jpg?oh=f9b2785989fd8b5588b7ca9e5511827b&oe=555E6440&__gda__=1429015900_851e7cb473ef706fd143e9e27aa1a800' />
<img src='https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xpf1/v/t1.0-1/p50x50/10699_10153535875314202_163449416445002093_n.jpg?oh=0f175d991b4e40cddd2f93989290cea1&oe=556C8A6E&__gda__=1431860513_23cc2847318db85ff0a1be57f83bcc29' />
<img src='https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xpa1/v/t1.0-1/p50x50/10898122_10153484934294867_4849101525532515761_n.jpg?oh=a207f82cf3758b6749227926eda74089&oe=556DCDC7&__gda__=1433284218_f10e5359128204efd38483d3618b7243' />
<img src='https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xap1/v/t1.0-1/p50x50/1520677_10151904372747017_2089516271_n.jpg?oh=b2d8efeb0c0fc7798e64a47a8a29df90&oe=556398E3&__gda__=1428469569_accebeff7a22c0b49f042ec832c6e99d' />
<img src='https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xfp1/v/t1.0-1/c10.0.50.50/p50x50/10678820_10204778094155474_8940868813772127523_n.jpg?oh=d4dad7a7433e5b4c18482b884b3977dc&oe=552A9784&__gda__=1428368107_2b280d1b6e04c0ad273794113b2b0825' />
<img src='https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xap1/v/t1.0-1/p50x50/10897996_10152971325863698_4809774063415800215_n.jpg?oh=4bffdcdc93d7d67cec3bebd2e610373a&oe=55570368&__gda__=1433040493_dc870d4688164c2d82e7b6807441abb7' />