-
Notifications
You must be signed in to change notification settings - Fork 22
/
jquery.ui.resizable.snap.ext.js
161 lines (142 loc) · 5.01 KB
/
jquery.ui.resizable.snap.ext.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/**
* "jQuery UI Resizable Snap" - Extension to the jQuery UI Resizable plugin for snapping while resizing.
*
* @copyright Copyright 2011, Alexander Polomoshnov
* @license MIT license (https://raw.github.com/polomoshnov/jQuery-UI-Resizable-Snap-extension/master/LICENSE.txt)
* @link https://github.com/polomoshnov/jQuery-UI-Resizable-Snap-extension
* @version 1.9.1
*/
(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.position.left + inst.lm, _l = l - st,
t = inst.position.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 - coords.b, st));
}
});
});
if (hs.length) inst.size.height += getN(hs);
if (ws.length) inst.size.width += getN(ws);
if (ls.length) {
var n = getN(ls);
inst.position.left += n;
inst.size.width -= n;
}
if (ts.length) {
var n = getN(ts);
inst.position.top += n;
inst.size.height -= n;
}
}
});
function getC(lt, rb, st) {
return Math.abs(lt) < st ? -lt : Math.abs(rb) < st ? -rb : 0;
}
function getN(ar) {
return ar.sort(function (a, b) { return !a ? 1 : !b ? -1 : Math.abs(a) - Math.abs(b) })[0];
}
function getLm($el) {
return parseInt($el.css('margin-left'), 10) || 0;
}
function getTm($el) {
return parseInt($el.css('margin-top'), 10) || 0;
}
// These are patches to the jQuery resizable plugin.
// They are needed in order for the snapping to work properly when the ghost or helper option is used.
function patch(func, afterFunc, beforeFunc) {
var fn = $.ui.resizable.prototype[func];
$.ui.resizable.prototype[func] = function () {
if (beforeFunc) beforeFunc.apply(this, arguments);
fn.apply(this, arguments);
if (afterFunc) afterFunc.apply(this, arguments);
}
}
patch('_mouseStop', null, function () {
if (this._helper) {
// 0.1 is a dirty hack to not end up with null if 0 is provided (when snapped to the left or top side of the browser window).
this.position = { left: parseInt(this.helper.css('left'), 10) || 0.1, top: parseInt(this.helper.css('top'), 10) || 0.1 };
this.size = { width: this.helper.outerWidth(), height: this.helper.outerHeight() };
}
});
patch('_mouseStart', function () {
if (this._helper) {
this.size = {
width: this.size.width - (this.helper.outerWidth() - this.helper.width()),
height: this.size.height - (this.helper.outerHeight() - this.helper.height())
};
this.originalSize = { width: this.size.width, height: this.size.height };
}
});
patch('_renderProxy', function () {
if (this._helper) {
this.helper.css({
left: this.elementOffset.left,
top: this.elementOffset.top,
width: this.element.outerWidth(),
height: this.element.outerHeight()
});
}
});
var p = $.ui.resizable.prototype.plugins.resize;
$.each(p, function (k, v) {
if (v[0] == 'ghost') {
p.splice(k, 1);
return false;
}
});
$.each($.ui.resizable.prototype.plugins.start, function (k, v) {
if (v[0] == 'ghost') {
var fn = v[1];
v[1] = function () {
fn.apply(this, arguments);
$(this).data('ui-resizable').ghost.css({ width: '100%', height: '100%' });
}
return false;
}
});
})(jQuery);