Nick Manning
Nick Manning

Reputation: 2989

JQuery Draggable: How do I make a draggable element snap to the inner-top of a div?

The question is pretty self explanatory. I can snap it to all sides of a div with "snapMode:'inner'" but not just the top. Can anyone think of a workaround?

$('.draggableThing').draggable({
    snap:'.row',
    snapMode:'inner',//should say "inner-top" but this is not an available option
    snapTolerance:5
});

http://jsfiddle.net/ZbeJL/2/

Upvotes: 2

Views: 2249

Answers (2)

apaul
apaul

Reputation: 16170

This is a bit of a hack, but if you're only using the snap option on this part of your project you could just comment out the unwanted functionality in your jQuery-ui file.

search for these three lines in your jQuery-ui file:

if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;

and comment them out like so:

//if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
//if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
//if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;

Working Example

Like I said its a bit of a hack, but it works.

Update:

I didn't really like the previous answer, so I figured out how to add some snapMode options to jQuery-ui. You will still need to edit the jQuery-ui file, but I think it may be worth it.

In addition to the standard inner, outer, and both. I added the following options:

  • innerTop
  • innerBottom
  • innerLeft
  • InnerRight
  • outerTop
  • outerBottom
  • outerRight
  • outerLeft

Better Working Example

Here's how:

Search for:

if(o.snapMode != 'inner') {
                var ts = Math.abs(t - y2) <= d;
                var bs = Math.abs(b - y1) <= d;
                var ls = Math.abs(l - x2) <= d;
                var rs = Math.abs(r - x1) <= d;
                if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
                if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
                if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
                if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
            }

            var first = (ts || bs || ls || rs);

            if(o.snapMode != 'outer') {
                var ts = Math.abs(t - y1) <= d;
                var bs = Math.abs(b - y2) <= d;
                var ls = Math.abs(l - x1) <= d;
                var rs = Math.abs(r - x2) <= d;
                if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
                if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
                if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
                if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
            }

and replace it with:

if (o.snapMode != 'inner' && o.snapMode != 'innerTop' && o.snapMode != 'innerBottom' && o.snapMode != 'innerLeft' && o.snapMode != 'innerRight' && o.snapMode != 'outerTop' && o.snapMode != 'outerBottom' && o.snapMode != 'outerLeft' && o.snapMode != 'outerRight') {
    var ts = Math.abs(t - y2) <= d;
    var bs = Math.abs(b - y1) <= d;
    var ls = Math.abs(l - x2) <= d;
    var rs = Math.abs(r - x1) <= d;
    if (ts) ui.position.top = inst._convertPositionTo("relative", {
        top: t - inst.helperProportions.height,
        left: 0
    }).top - inst.margins.top;
    if (bs) ui.position.top = inst._convertPositionTo("relative", {
        top: b,
        left: 0
    }).top - inst.margins.top;
    if (ls) ui.position.left = inst._convertPositionTo("relative", {
        top: 0,
        left: l - inst.helperProportions.width
    }).left - inst.margins.left;
    if (rs) ui.position.left = inst._convertPositionTo("relative", {
        top: 0,
        left: r
    }).left - inst.margins.left;
}

var first = (ts || bs || ls || rs);

if (o.snapMode != 'outer' && o.snapMode != 'innerTop' && o.snapMode != 'innerBottom' && o.snapMode != 'innerLeft' && o.snapMode != 'innerRight' && o.snapMode != 'outerTop' && o.snapMode != 'outerBottom' && o.snapMode != 'outerLeft' && o.snapMode != 'outerRight') {
    var ts = Math.abs(t - y1) <= d;
    var bs = Math.abs(b - y2) <= d;
    var ls = Math.abs(l - x1) <= d;
    var rs = Math.abs(r - x2) <= d;
    if (ts) ui.position.top = inst._convertPositionTo("relative", {
        top: t,
        left: 0
    }).top - inst.margins.top;
    if (bs) ui.position.top = inst._convertPositionTo("relative", {
        top: b - inst.helperProportions.height,
        left: 0
    }).top - inst.margins.top;
    if (ls) ui.position.left = inst._convertPositionTo("relative", {
        top: 0,
        left: l
    }).left - inst.margins.left;
    if (rs) ui.position.left = inst._convertPositionTo("relative", {
        top: 0,
        left: r - inst.helperProportions.width
    }).left - inst.margins.left;
}

if (o.snapMode == 'innerTop') {
    var ts = Math.abs(t - y1) <= d;
    if (ts) ui.position.top = inst._convertPositionTo("relative", {
        top: t,
        left: 0
    }).top - inst.margins.top;
}

if (o.snapMode == 'innerBottom') {
    var bs = Math.abs(b - y2) <= d;
    if (bs) ui.position.top = inst._convertPositionTo("relative", {
        top: b - inst.helperProportions.height,
        left: 0
    }).top - inst.margins.top;
}

if (o.snapMode == 'innerLeft') {
    var ls = Math.abs(l - x1) <= d;
    if (ls) ui.position.left = inst._convertPositionTo("relative", {
        top: 0,
        left: l
    }).left - inst.margins.left;
}

if (o.snapMode == 'innerRight') {
    var rs = Math.abs(r - x2) <= d;
    if (rs) ui.position.left = inst._convertPositionTo("relative", {
        top: 0,
        left: r - inst.helperProportions.width
    }).left - inst.margins.left;
}


if (o.snapMode == 'outerTop') {
    var ts = Math.abs(t - y2) <= d;
    if (ts) ui.position.top = inst._convertPositionTo("relative", {
        top: t - inst.helperProportions.height,
        left: 0
    }).top - inst.margins.top;
}

if (o.snapMode == 'outerBottom') {
    var bs = Math.abs(b - y1) <= d;
    if (bs) ui.position.top = inst._convertPositionTo("relative", {
        top: b,
        left: 0
    }).top - inst.margins.top;
}

if (o.snapMode == 'outerLeft') {
    var ls = Math.abs(l - x2) <= d;
    if (ls) ui.position.left = inst._convertPositionTo("relative", {
        top: 0,
        left: l - inst.helperProportions.width
    }).left - inst.margins.left;
}

if (o.snapMode == 'outerRight') {
    var rs = Math.abs(r - x1) <= d;
    if (rs) ui.position.left = inst._convertPositionTo("relative", {
        top: 0,
        left: r
    }).left - inst.margins.left;
}

Upvotes: 4

Mx.
Mx.

Reputation: 3665

i'm not sure but it seems like jQueryUI doesn't support something like that. You could use this workaround to get the behaviour you need. Simply put another div in your div which is used for the snap.

<div class='row'>
    <div class='innerHack'></div>
</div>

Here's a Fiddle

Upvotes: 2

Related Questions