Create a Draggable Element in JavaScript


#22

You can just store the transform X and Y values on each element to get the same result. I don’t recommend using the the top and left properties for performance reasons.


#23

Thank you for your response, now it is much easier to drag :slight_smile: But now I have a new problem - I can’t get the file to scale. The settings I had before I placed the url(filehere) in css, was that the element should be 60% of the windows width, but not bigger than 363px (width: 60%;, max-width: 363px;). That worked when I had the img src in html, but not now when I need the image file to be in css. I tried to place the img src in between the div in html, but then my original problem occurs (you have to click once more to let the item go). I tried making a container around the div as well, but it still doesn’t work. Now it looks like this:

#containerElement1 {
position: relative;
max-width: 363px;
max-height: 139px;
width: 60%;
height: auto;
}

#element1 {
background-image: url(illustrasjon/nase1.png);
display: block;
width: 100%;
height: auto;
}


#24

Correction, this is how it looks like in the css file:

#containerElement1 {

position: relative;

max-width: 363px;

max-height: 139px;

width: 60%;

height: auto;

}

#element1 {

background-image: url(illustrasjon/nase1.png);

display: block;

width: 263px;

height: 139px;

}


#25

Do you have the example hosted anywhere that we can take a look at? :slight_smile:


#26

Here is the webpage: http://folk.ntnu.no/manordt/wu1/Heimeside/framside.html

The code is a bit messy now because I have been trying out different things :slight_smile: But the first element is the one I can’t get to scale properly (id=“element1”). The other elements on the page is how it looks when the file is in the html document.
Then it doesn’t drag properly.


#27

That helps greatly! The issue is that the drag code doesn’t like any child elements like our image to be placed inside the div. The trick is to disable mouse/touch events on the image. Here is an example: https://www.kirupa.com/html5/examples/drag_multiple_images.htm

The main change is the following style rule that I added:

.item img {
  pointer-events: none;
}

You may need to modify your style rule to be .element img, but that will fix it for you as well. I set it on all images via your existing img style rule, and it worked.

Cheers,
Kirupa


#28

Thank you so much! It worked :smiley: Buuuut… Every time something works, it affects something else :joy: Now all my elements get to small, I figured out it is because the javascript I have that randomly places the objects inside the browser window. Maybe it doesn’t like that I use element img in css, and then only refers to element in the script? Do you have any idea how I can fix this? I should send you a medal soon for helping me so much out :sweat_smile:
Webpage: folk.ntnu.no/manordt/wu1/Heimeside/framside.html


#29

Haha. Welcome to web development :stuck_out_tongue:

The reason for the sizes doesn’t seem to have anything to do with the JavaScript or how you are placing them on the page. All of your images are respecting the size you have specified:

.element img {
    max-width: 363px;
    width: 60%;
    pointer-events: none;
}

If you increase the width and max-width values, you’ll find that your images grow to match your new size. Try that and let us know if that solves it for you.

Cheers,
Kirupa


#30

Figured it out, thank you! Again! I figured out it was because I was using the .element img {} to scale it within the browser window, but I guess it then scaled within the div instead? So I moved the max-width and width: 60% to .element {}, and in .element img {width: 100%;}. Now it works! I also added some code that prevent the images from being highlighted when dragged. Now it looks like this in the CSS file:
.element {
max-width: 363px;
width: 60%;
user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
}

.element img {
pointer-events: none;
width: 100%;
}

.element:active {
opacity: .75;
}

.element:hover {
cursor: pointer;
}

Thanks again, you’re a real life saver! Now my webpage is finally ready to be launched :smiley:


#31

That is awesome! Glad to hear you are unblocked :slight_smile:


#32

Hi there, I’m trying your code and for some reason it doesn’t get past the condition for the if statement in dragStart.

if(e.target === detailPanel) {
active = true;
}

detailPanel being my dragItem.

I’m trying to drag an element (toggled on the draggable in the html attributes) which has a few things inside. It’s basically a card, or as the name implies, a detail panel with lots of info in it.

If I console log out my detailPanel variable it does select the right element so I’m not sure why the script can’t get into the if statement.

var detailPanel = document.getElementsByClassName('detailTabWrappper');
console.log(detailPanel);
var panelContainer = document.body;
console.log(panelContainer);
var active = false;

var currentX;
var currentY;
var initialX;
var initialY;
var xOffset = 0;
var yOffset = 0;

panelContainer.addEventListener('mousedown', dragStart);
panelContainer.addEventListener('mouseup', dragEnd);
panelContainer.addEventListener('mousemove', drag);

function dragStart(e) {
  if(e.type === 'mousedown') {
    initialX = e.clientX - xOffset;
    initialY = e.clientY - yOffset;
  }

  // this here is not working
  if(e.target === detailPanel) {
    active = true;
  }
}

<article class="detailTabWrappper" draggable="true"></article>

Any ideas why?


#33

One thing is that getElementsByClassName returns an array. Try this:

var detailPanel = document.getElementsByClassName('detailTabWrappper')[0];

That will ensure detailPanel points to an element instead of the array. Does that fix it?

Cheers,
Kirupa :stuck_out_tongue:


#34

It works.

I can’t believe I got owned by that a second time. That the getEByClass returns an array.

Thanks!