Resizable Snap

by Larry Cole

HTML

<div class="box"></div>
<div class="box"></div>
<div class="box"></div>

CSS

.box {
    position: absolute;
    width: 200px;
    height: 200px;
    background: silver;
}

.box:nth-of-type(1) {
    left: 50px;
    top: 170px;
    background: red;
}

.box:nth-of-type(2) {
    left: 150px;
    top: 270px;
    background: green;
}

.box:nth-of-type(3) {
    left: 250px;
    top: 370px;
    background: blue;
}

JavaScript

$('.box').draggable({snap:true}).resizable({ 
            handles: 'all',
            snap: true
        });

(function ($) {
$.extend($.ui.resizable.prototype.options, { snapTolerance: 20, snapMode: 'both' });

$.ui.plugin.add('resizable', 'snap', {
start: function () {
var $this = $(this), inst = $this.data('ui-resizable'), snap = inst.options.snap;
inst.ow = inst.helper.outerWidth() - inst.size.width;
inst.oh = inst.helper.outerHeight() - inst.size.height;
inst.lm = getLm($this);
inst.tm = getTm($this);
inst.coords = [];

$(typeof snap == 'string' ? snap : ':data(ui-resizable)').each(function () {
if (this == inst.element[0] || this == inst.helper[0]) return;

var $el = $(this), p = $el.position(),
l = p.left + getLm($el), t = p.top + getTm($el);

inst.coords.push({
l: l, t: t,
r: l + $el.outerWidth(), b: t + $el.outerHeight() });
});
},
resize: function () {
var ls = [], ts = [], ws = [], hs = [],
inst = $(this).data('ui-resizable'),
axes = inst.axis.split(''),
st = inst.options.snapTolerance,
md = inst.options.snapMode,
l = inst.elementOffset.left + inst.lm, _l = l - st,
t = inst.elementOffset.top + inst.tm, _t = t - st,
r = l + inst.size.width + inst.ow, _r = r + st,
b = t + inst.size.height + inst.oh, _b = b + st;

$.each(inst.coords, function () {
var coords = this,
w = Math.min(_r, coords.r) - Math.max(_l, coords.l),
h = Math.min(_b, coords.b) - Math.max(_t, coords.t);

if (w < 0 || h < 0) return;

$.each(axes, function (k, axis) {
if (md == 'outer') {
switch (axis) {
case 'w': case 'e': if (w > st * 2) return; break;
case 'n': case 's': if (h > st * 2) return;
}
} else if (md == 'inner') {
switch (axis) {
case 'w': case 'e': if (w < st * 2) return; break;
case 'n': case 's': if (h < st * 2) return;
}
}

switch (axis) {
case 'w': ls.push(getC(l - coords.l, l - coords.r, st)); break;
case 'n': ts.push(getC(t - coords.t, t - coords.b, st)); break;
case 'e': ws.push(getC(r - coords.l, r - coords.r, st)); break;
case 's': hs.push(getC(b - coords.t, b -...