Andrew L Andrew L - 1 year ago 117
jQuery Question

jQuery-UI Draggable Containment Acting Strange

When iterating through a

and making all the children draggable, I come to a problem. I want to make the containment work in a way where all the
's are inside the bounds of the
. I've logically done this:

currentHexList.children().draggable({ //currentHexList is a jQuery object in a for loop that has the value of a <ul> list
scroll: false,
containment: 'parent'

All is 'sort of' well as in the containment 'works', but not desirably. Here is what I'm going for and what is happening. Red marks the actual, and the highlighted is the parent in which the bounds should be:

enter image description here

A side note, I am using the 'responsive grid of hexagons' css file from here in which I loop over a list of them to make them draggable. I was wondering if there was any kind of padding in containment or if my CSS was effecting it.

Here is my CSS and the CSS applicable to the list from 'responsive grid of hexagons':

From hexagon css,

#hexGrid {
overflow: hidden;
width: 100%;
margin: 0 auto;
padding:0.866% 0;
font-family: 'Raleway', sans-serif;
font-size: 15px;
#hexGrid:after {
content: "";
display: block;
clear: both;

From my css,

.hexGrid {
position: absolute;
top: 10%;
left: 20%;
padding: 0px;
width: 900px;
height: 800px;

I was suspecting maybe my top and/or left was effecting it, or display block. To sum it all up, there is a huge offset between my desired containment for my draggables versus the real containment. Any help would be appreciated. Thanks!

Answer Source

Containment works by defining coordinates based on the option given and then validating on drag if the element left is higher than containment left and if left + width is lower than containment right. Same thing with top and bottom.

Since part of your element isn't visible and because of the transform, you get this weird result. The left you see isn't actually the left of the element.

What you can do is override calculated containment on start event. This should work for example:

  containment: 'parent',
  start: function(e, ui) {
    // access containment on the instance, which is the 
    // coordinates array calculated based on the element
    // given in containment option. These coordinates
    // are defined on start. The array has this structure:
    // [x1 (left limit), y1 (top limit), x2 (right limit), y2 (bottom limit)]
    var contCoord = $(this).draggable('instance').containment;

    // Adjust the containment array based on the width of the element.
    // This is good for left and right, you'll need
    // to do this for top and bottom.
    contCoord[0] -= ui.helper.width() / 2;
    contCoord[2] -= ui.helper.width() / 2;