Skip to content

Commit f6144fb

Browse files
committed
Added mutationobserver to detect DOM movements and reset sensor accordingly.
fixed a bug in Safari where dragdrop doesn't work with huge sensors dimensions.
1 parent b4f79b3 commit f6144fb

File tree

6 files changed

+248
-8
lines changed

6 files changed

+248
-8
lines changed

src/ResizeSensor.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
declare class ResizeSensor {
22
constructor(element: (Element | Element[]), callback: Function);
33
detach(callback: Function): void;
4+
reset(element: Element | Element[]): void;
45
}
56

67
export default ResizeSensor;

src/ResizeSensor.js

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@
131131
element.resizeSensor = document.createElement('div');
132132
element.resizeSensor.dir = 'ltr';
133133
element.resizeSensor.className = 'resize-sensor';
134-
var style = 'position: absolute; left: -10px; top: -10px; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden; max-width: 100%';
134+
var style = 'pointer-events: none; position: absolute; left: 0px; top: 0px; right: 0; bottom: 0; ' +
135+
'overflow: hidden; z-index: -1; visibility: hidden; max-width: 100%;';
135136
var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;';
136137

137138
element.resizeSensor.style.cssText = style;
@@ -161,14 +162,17 @@
161162
var lastAnimationFrame = 0;
162163

163164
var resetExpandShrink = function () {
164-
expandChild.style.width = '100000px';
165-
expandChild.style.height = '100000px';
165+
var width = element.offsetWidth;
166+
var height = element.offsetHeight;
166167

167-
expand.scrollLeft = 100000;
168-
expand.scrollTop = 100000;
168+
expandChild.style.width = (width + 10) + 'px';
169+
expandChild.style.height = (height + 10) + 'px';
169170

170-
shrink.scrollLeft = 100000;
171-
shrink.scrollTop = 100000;
171+
expand.scrollLeft = width + 10;
172+
expand.scrollTop = height + 10;
173+
174+
shrink.scrollLeft = width + 10;
175+
shrink.scrollTop = height + 10;
172176
};
173177

174178
var reset = function() {
@@ -248,7 +252,7 @@
248252
};
249253
};
250254

251-
ResizeSensor.reset = function(element, ev) {
255+
ResizeSensor.reset = function(element) {
252256
forEachElement(element, function(elem){
253257
elem.resizeSensor.resetSensor();
254258
});
@@ -271,6 +275,27 @@
271275
});
272276
};
273277

278+
if (typeof MutationObserver !== "undefined") {
279+
var observer = new MutationObserver(function (mutations) {
280+
for (var i in mutations) {
281+
var items = mutations[i].addedNodes;
282+
for (var j = 0; j < items.length; j++) {
283+
if (items[j].resizeSensor) {
284+
ResizeSensor.reset(items[j]);
285+
}
286+
}
287+
288+
}
289+
});
290+
291+
document.addEventListener("DOMContentLoaded", function (event) {
292+
observer.observe(document.body, {
293+
childList: true,
294+
subtree: true,
295+
});
296+
});
297+
}
298+
274299
return ResizeSensor;
275300

276301
}));

tests/mutation/app.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
var __values = (this && this.__values) || function (o) {
2+
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
3+
if (m) return m.call(o);
4+
return {
5+
next: function () {
6+
if (o && i >= o.length) o = void 0;
7+
return { value: o && o[i++], done: !o };
8+
}
9+
};
10+
};
11+
var e_1, _a, e_2, _b;
12+
var state = {
13+
dragged: null
14+
};
15+
var i = 0;
16+
try {
17+
for (var _c = __values(document.getElementsByClassName('drag')), _d = _c.next(); !_d.done; _d = _c.next()) {
18+
var item = _d.value;
19+
i++;
20+
item.setAttribute('draggable', 'true');
21+
item.setAttribute('id', 'drag-' + i);
22+
(function (element) {
23+
var title = 'Drag me #' + i;
24+
element.setAttribute('data-label', title);
25+
new ResizeSensor(element, function (size) {
26+
element.setAttribute('data-label', title + " (" + size.width + "x" + size.height + ")");
27+
});
28+
})(item);
29+
item.addEventListener('dragstart', function (event) {
30+
state.dragged = event.target;
31+
event.dataTransfer.setData('text', 'thanks firefox');
32+
event.dataTransfer.dropEffect = 'move';
33+
});
34+
}
35+
}
36+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
37+
finally {
38+
try {
39+
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
40+
}
41+
finally { if (e_1) throw e_1.error; }
42+
}
43+
var _loop_1 = function (item) {
44+
(function (element) {
45+
item.addEventListener('drop', function (event) {
46+
event.preventDefault();
47+
item.classList.remove('drag-hover');
48+
state.dragged.parentNode.removeChild(state.dragged);
49+
element.appendChild(state.dragged);
50+
state.dragged = null;
51+
});
52+
})(item);
53+
item.addEventListener('dragleave', function (event) {
54+
item.classList.remove('drag-hover');
55+
});
56+
item.addEventListener('dragover', function (event) {
57+
item.classList.add('drag-hover');
58+
});
59+
item.addEventListener('dragover', function (event) {
60+
event.preventDefault();
61+
});
62+
};
63+
try {
64+
for (var _e = __values(document.getElementsByClassName('container')), _f = _e.next(); !_f.done; _f = _e.next()) {
65+
var item = _f.value;
66+
_loop_1(item);
67+
}
68+
}
69+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
70+
finally {
71+
try {
72+
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
73+
}
74+
finally { if (e_2) throw e_2.error; }
75+
}

tests/mutation/app.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
declare const ResizeSensor;
2+
3+
const state: {
4+
dragged: Element
5+
} = {
6+
dragged: null
7+
};
8+
9+
let i = 0;
10+
11+
for (const item of document.getElementsByClassName('drag')) {
12+
i++;
13+
item.setAttribute('draggable', 'true');
14+
item.setAttribute('id', 'drag-' + i);
15+
16+
(element => {
17+
const title = 'Drag me #' + i;
18+
element.setAttribute('data-label', title);
19+
20+
new ResizeSensor(element, (size) => {
21+
element.setAttribute('data-label', `${title} (${size.width}x${size.height})`);
22+
});
23+
})(item);
24+
25+
item.addEventListener('dragstart', (event: DragEvent) => {
26+
state.dragged = <Element>event.target;
27+
event.dataTransfer.setData('text', 'thanks firefox');
28+
event.dataTransfer.dropEffect = 'move';
29+
});
30+
}
31+
32+
for (const item of document.getElementsByClassName('container')) {
33+
(element => {
34+
item.addEventListener('drop', (event) => {
35+
event.preventDefault();
36+
item.classList.remove('drag-hover');
37+
38+
state.dragged.parentNode.removeChild(state.dragged);
39+
element.appendChild(state.dragged);
40+
41+
state.dragged = null;
42+
});
43+
})(item);
44+
45+
item.addEventListener('dragleave', (event) => {
46+
item.classList.remove('drag-hover');
47+
});
48+
49+
item.addEventListener('dragover', (event) => {
50+
item.classList.add('drag-hover');
51+
});
52+
53+
item.addEventListener('dragover', (event) => {
54+
event.preventDefault();
55+
});
56+
}

tests/mutation/index.html

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<!DOCTYPE html>
2+
<head>
3+
<meta charset="utf-8" />
4+
<style type="text/css">
5+
body {
6+
background-color: #fafafa;
7+
}
8+
9+
* {
10+
box-sizing: border-box;
11+
}
12+
13+
.container {
14+
margin: 15px;
15+
padding: 15px;
16+
border: 1px solid silver;
17+
border-radius: 3px;
18+
min-height: 250px;
19+
background-color: rgba(255, 255, 255, 0.86);
20+
}
21+
22+
.container.drag-hover {
23+
border: 1px solid red;
24+
background-color: rgba(255, 125, 15, 0.18);
25+
}
26+
27+
@keyframes wrapple {
28+
0%, 100% {
29+
width: 150px;
30+
height: 150px;
31+
}
32+
33+
50% {
34+
width: 120px;
35+
height: 120px;
36+
}
37+
}
38+
39+
.drag {
40+
border: 1px solid silver;
41+
border-radius: 5px;
42+
margin: 15px;
43+
width: 150px;
44+
height: 150px;
45+
background-color: #d1ffff;
46+
animation-name: wrapple;
47+
animation-duration: 4s;
48+
animation-iteration-count: infinite;
49+
50+
display: inline-flex;
51+
justify-content: center;
52+
flex-direction: column;
53+
text-align: center;
54+
}
55+
56+
.drag::after {
57+
font-size: 12px;
58+
content: attr(data-label);
59+
}
60+
</style>
61+
62+
<script src="../../src/ResizeSensor.js"></script>
63+
</head>
64+
<body>
65+
<div id="container1" class="container">
66+
<div class="drag" draggable="true"></div>
67+
<div class="drag"></div>
68+
</div>
69+
70+
<div id="container2" class="container">
71+
<div class="drag"></div>
72+
<div class="drag"></div>
73+
</div>
74+
75+
<script type="application/javascript" src="./app.js"></script>
76+
</body>

tsconfig.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"downlevelIteration": true,
5+
"lib" : ["dom","es6","dom.iterable","scripthost", "es2015.iterable", "es2015.collection"]
6+
}
7+
}

0 commit comments

Comments
 (0)