-
Notifications
You must be signed in to change notification settings - Fork 1
/
Droppable.js
108 lines (86 loc) · 2.93 KB
/
Droppable.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
define([
'wrap!underscore'
],
function (
_
) {
var droppables = [], currentHover = null
function pointInside (pointX, pointY, x, y, w, h) {
return x <= pointX && x + w >= pointX &&
y <= pointY && y + h >= pointY
}
function isHovering (droppable, dragX, dragY, dragW, dragH) {
return pointInside(dragX, dragY, droppable.x, droppable.y, droppable.width, droppable.height) // top left
|| pointInside(dragX + dragW, dragY, droppable.x, droppable.y, droppable.width, droppable.height) // top right
|| pointInside(dragX, dragY + dragH, droppable.x, droppable.y, droppable.width, droppable.height) // bottom left
|| pointInside(dragX + dragW, dragY + dragH, droppable.x, droppable.y, droppable.width, droppable.height) // bottom right
}
function distance (droppable, dragX, dragY, dragW, dragH) {
if (!isHovering(droppable, dragX, dragY, dragW, dragH)) return -1
return Math.sqrt(Math.pow(dragX - droppable.x, 2) + Math.pow(dragY - droppable.y, 2))
}
function closestDroppable (x, y, w, h) {
var dist, closestDistance, droppable, closestView = null
for (var i = 0; i < droppables.length; i++) {
droppable = droppables[i]
dist = distance(droppable, x, y, w, h)
if (dist !== -1) {
if (!closestView || dist < closestDistance) {
closestDistance = dist
closestView = droppable
}
}
}
return closestView
}
return {
setDroppable: function (droppable, x, y, w, h) {
if (droppable) {
this.enableDroppable(x, y, w, h)
}
else {
this.disableDroppable()
}
},
enableDroppable: function (x, y, w, h) {
if (this.droppable) return
this.droppable = true
if (!this.x) this.x = 0
if (!this.y) this.y = 0
droppables.push(this)
},
disableDroppable: function () {
if (!this.droppable) return
var index = _.indexOf(droppables, this)
if (index === -1) return console.error("couldnt find droppable, wtf")
droppables.splice(index, 1)
this.droppable = false
},
_droppableOnDragEnd: function (view, x, y, w, h) {
var closestView = closestDroppable(x, y, w, h)
if (currentHover) {
currentHover.trigger('dropunhover', view)
view.trigger('dropunhover', currentHover)
currentHover = null
}
if (closestView) {
closestView.trigger('drop', view)
view.trigger('drop', closestView)
}
return closestView
},
_droppableOnDragMove: function (view, x, y, w, h) {
var closestView = closestDroppable(x, y, w, h)
if (currentHover === closestView) return
if (currentHover) {
currentHover.trigger('dropunhover', view)
view.trigger('dropunhover', currentHover)
}
if (closestView) {
closestView.trigger('drophover', view)
view.trigger('drophover', closestView)
}
currentHover = closestView
}
}
})