draggable-rails 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/draggable/rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/behaviour/collidable.js +99 -0
  4. data/vendor/assets/javascripts/behaviour/snappable.js +107 -0
  5. data/vendor/assets/javascripts/core/accessibility.js +58 -0
  6. data/vendor/assets/javascripts/core/mirror.js +129 -0
  7. data/vendor/assets/javascripts/draggable.js +487 -0
  8. data/vendor/assets/javascripts/droppable.js +168 -0
  9. data/vendor/assets/javascripts/events/abstract-event.js +45 -0
  10. data/vendor/assets/javascripts/events/collidable-event.js +25 -0
  11. data/vendor/assets/javascripts/events/drag-event.js +91 -0
  12. data/vendor/assets/javascripts/events/draggable-event.js +17 -0
  13. data/vendor/assets/javascripts/events/droppable-event.js +21 -0
  14. data/vendor/assets/javascripts/events/mirror-event.js +43 -0
  15. data/vendor/assets/javascripts/events/sensor-event.js +47 -0
  16. data/vendor/assets/javascripts/events/snappable-event.js +15 -0
  17. data/vendor/assets/javascripts/events/sortable-event.js +35 -0
  18. data/vendor/assets/javascripts/events/swappable-event.js +23 -0
  19. data/vendor/assets/javascripts/index.js +18 -0
  20. data/vendor/assets/javascripts/sensors/drag-sensor.js +158 -0
  21. data/vendor/assets/javascripts/sensors/force-touch-sensor.js +166 -0
  22. data/vendor/assets/javascripts/sensors/mouse-sensor.js +110 -0
  23. data/vendor/assets/javascripts/sensors/sensor.js +23 -0
  24. data/vendor/assets/javascripts/sensors/touch-sensor.js +145 -0
  25. data/vendor/assets/javascripts/sortable.js +161 -0
  26. data/vendor/assets/javascripts/swappable.js +104 -0
  27. data/vendor/assets/javascripts/utils.js +52 -0
  28. metadata +26 -1
@@ -0,0 +1,168 @@
1
+ import Draggable from './draggable';
2
+ import {closest} from './utils';
3
+
4
+ import {
5
+ DroppableOverEvent,
6
+ DroppableOutEvent,
7
+ } from './events/droppable-event';
8
+
9
+ const classes = {
10
+ 'droppable:active': 'draggable-droppable--active',
11
+ 'droppable:occupied': 'draggable-droppable--occupied',
12
+ };
13
+
14
+ export default class Droppable {
15
+ constructor(containers = [], options = {}) {
16
+ this.draggable = new Draggable(containers, options);
17
+ this.options = {...options};
18
+
19
+ this._onDragStart = this._onDragStart.bind(this);
20
+ this._onDragMove = this._onDragMove.bind(this);
21
+ this._onDragStop = this._onDragStop.bind(this);
22
+
23
+ this.draggable
24
+ .on('drag:start', this._onDragStart)
25
+ .on('drag:move', this._onDragMove)
26
+ .on('drag:stop', this._onDragStop);
27
+ }
28
+
29
+ destroy() {
30
+ this.draggable
31
+ .off('drag:start', this._onDragStart)
32
+ .off('drag:move', this._onDragMove)
33
+ .off('drag:stop', this._onDragStop)
34
+ .destroy();
35
+ }
36
+
37
+ on(type, callback) {
38
+ this.draggable.on(type, callback);
39
+ return this;
40
+ }
41
+
42
+ off(type, callback) {
43
+ this.draggable.off(type, callback);
44
+ return this;
45
+ }
46
+
47
+ getClassNameFor(name) {
48
+ return this.options.classes[name] || classes[name];
49
+ }
50
+
51
+ _onDragStart(event) {
52
+ if (event.canceled()) {
53
+ return;
54
+ }
55
+
56
+ this.droppables = this._getDroppables();
57
+ const droppable = event.sensorEvent.target.closest(this.options.droppable);
58
+
59
+ if (!droppable) {
60
+ event.cancel();
61
+ return;
62
+ }
63
+
64
+ this.initialDroppable = droppable;
65
+
66
+ for (const droppableElement of this.droppables) {
67
+ if (droppableElement.classList.contains(this.getClassNameFor('droppable:occupied'))) {
68
+ continue;
69
+ }
70
+
71
+ droppableElement.classList.add(this.getClassNameFor('droppable:active'));
72
+ }
73
+ }
74
+
75
+ _onDragMove(event) {
76
+ if (event.canceled()) {
77
+ return;
78
+ }
79
+
80
+ const droppable = this._closestDroppable(event.sensorEvent.target);
81
+ const overEmptyDroppable = droppable && !droppable.classList.contains(this.getClassNameFor('droppable:occupied'));
82
+
83
+ if (overEmptyDroppable && this._drop(event, droppable)) {
84
+ this.lastDroppable = droppable;
85
+ } else if ((!droppable || droppable === this.initialDroppable) && this.lastDroppable) {
86
+ this._release(event);
87
+ this.lastDroppable = null;
88
+ }
89
+ }
90
+
91
+ _onDragStop() {
92
+ const occupiedClass = this.getClassNameFor('droppable:occupied');
93
+
94
+ for (const droppable of this.droppables) {
95
+ droppable.classList.remove(this.getClassNameFor('droppable:active'));
96
+ }
97
+
98
+ if (this.lastDroppable && this.lastDroppable !== this.initialDroppable) {
99
+ this.initialDroppable.classList.remove(occupiedClass);
100
+ }
101
+
102
+ this.droppables = null;
103
+ this.lastDroppable = null;
104
+ this.initialDroppable = null;
105
+ }
106
+
107
+ _drop(event, droppable) {
108
+ const droppableOverEvent = new DroppableOverEvent({
109
+ dragEvent: event,
110
+ droppable,
111
+ });
112
+
113
+ this.draggable.triggerEvent(droppableOverEvent);
114
+
115
+ if (droppableOverEvent.canceled()) {
116
+ return false;
117
+ }
118
+
119
+ const occupiedClass = this.getClassNameFor('droppable:occupied');
120
+
121
+ if (this.lastDroppable) {
122
+ this.lastDroppable.classList.remove(occupiedClass);
123
+ }
124
+
125
+ droppable.appendChild(event.source);
126
+ droppable.classList.add(occupiedClass);
127
+
128
+ return true;
129
+ }
130
+
131
+ _release(event) {
132
+ const droppableOutEvent = new DroppableOutEvent({
133
+ dragEvent: event,
134
+ droppable: this.lastDroppable,
135
+ });
136
+
137
+ this.draggable.triggerEvent(droppableOutEvent);
138
+
139
+ if (droppableOutEvent.canceled()) {
140
+ return;
141
+ }
142
+
143
+ this.initialDroppable.appendChild(event.source);
144
+ this.lastDroppable.classList.remove(this.getClassNameFor('droppable:occupied'));
145
+ }
146
+
147
+ _closestDroppable(target) {
148
+ if (!this.droppables) {
149
+ return null;
150
+ }
151
+
152
+ return closest(target, (element) => Array.from(this.droppables).includes(element));
153
+ }
154
+
155
+ _getDroppables() {
156
+ const droppables = this.options.droppable;
157
+
158
+ if (typeof droppables === 'string') {
159
+ return document.querySelectorAll(droppables);
160
+ } else if (droppables instanceof NodeList || droppables instanceof Array) {
161
+ return droppables;
162
+ } else if (typeof droppables === 'function') {
163
+ return droppables();
164
+ } else {
165
+ return [];
166
+ }
167
+ }
168
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * All events fired by draggable inherit this class. You can call `cancel()` to
3
+ * cancel a specific event or you can check if an event has been canceled by
4
+ * calling `canceled()`.
5
+ * @abstract
6
+ * @class
7
+ */
8
+ export default class AbstractEvent {
9
+ static type = 'event';
10
+ static cancelable = false;
11
+
12
+ constructor(data) {
13
+ this._canceled = false;
14
+ this.data = data;
15
+ }
16
+
17
+ get type() {
18
+ return this.constructor.type;
19
+ }
20
+
21
+ get cancelable() {
22
+ return this.constructor.cancelable;
23
+ }
24
+
25
+ /**
26
+ * Cancels a specific event
27
+ * @abstract
28
+ */
29
+ cancel() {
30
+ // We should be declaring if events are cancelable
31
+ // if (!this.cancelable) {
32
+ // throw new Error('This event is not cancelable');
33
+ // }
34
+ this._canceled = true;
35
+ }
36
+
37
+ /**
38
+ * Check if event has been canceled
39
+ * @abstract
40
+ * @return {Boolean}
41
+ */
42
+ canceled() {
43
+ return Boolean(this._canceled);
44
+ }
45
+ }
@@ -0,0 +1,25 @@
1
+ import AbstractEvent from './abstract-event';
2
+
3
+ export class CollidableEvent extends AbstractEvent {
4
+ static type = 'collidable';
5
+
6
+ get dragEvent() {
7
+ return this.data.dragEvent;
8
+ }
9
+ }
10
+
11
+ export class CollidableInEvent extends CollidableEvent {
12
+ static type = 'collidable:in';
13
+
14
+ get collidingElement() {
15
+ return this.data.collidingElement;
16
+ }
17
+ }
18
+
19
+ export class CollidableOutEvent extends CollidableEvent {
20
+ static type = 'collidable:out';
21
+
22
+ get collidingElement() {
23
+ return this.data.collidingElement;
24
+ }
25
+ }
@@ -0,0 +1,91 @@
1
+ import AbstractEvent from './abstract-event';
2
+
3
+ export class DragEvent extends AbstractEvent {
4
+ get source() {
5
+ return this.data.source;
6
+ }
7
+
8
+ get mirror() {
9
+ return this.data.mirror;
10
+ }
11
+
12
+ get sourceContainer() {
13
+ return this.data.sourceContainer;
14
+ }
15
+
16
+ get sensorEvent() {
17
+ return this.data.sensorEvent;
18
+ }
19
+
20
+ get originalEvent() {
21
+ if (this.sensorEvent) {
22
+ return this.sensorEvent.originalEvent;
23
+ }
24
+
25
+ return null;
26
+ }
27
+
28
+ hasMirror() {
29
+ return Boolean(this.mirror);
30
+ }
31
+ }
32
+
33
+ export class DragStartEvent extends DragEvent {
34
+ static type = 'drag:start';
35
+ }
36
+
37
+ export class DragMoveEvent extends DragEvent {
38
+ static type = 'drag:move';
39
+ }
40
+
41
+ export class DragOutContainerEvent extends DragEvent {
42
+ static type = 'drag:out:container';
43
+
44
+ get overContainer() {
45
+ return this.data.overContainer;
46
+ }
47
+ }
48
+
49
+ export class DragOutEvent extends DragEvent {
50
+ static type = 'drag:out';
51
+
52
+ get overContainer() {
53
+ return this.data.overContainer;
54
+ }
55
+
56
+ get over() {
57
+ return this.data.over;
58
+ }
59
+ }
60
+
61
+ export class DragOverContainerEvent extends DragEvent {
62
+ static type = 'drag:over:container';
63
+
64
+ get overContainer() {
65
+ return this.data.overContainer;
66
+ }
67
+ }
68
+
69
+ export class DragOverEvent extends DragEvent {
70
+ static type = 'drag:over';
71
+
72
+ get overContainer() {
73
+ return this.data.overContainer;
74
+ }
75
+
76
+ get over() {
77
+ return this.data.over;
78
+ }
79
+ }
80
+
81
+ export class DragPressureEvent extends DragEvent {
82
+ static type = 'drag:pressure';
83
+
84
+ get pressure() {
85
+ return this.data.pressure;
86
+ }
87
+ }
88
+
89
+ export class DragStopEvent extends DragEvent {
90
+ static type = 'drag:stop';
91
+ }
@@ -0,0 +1,17 @@
1
+ import AbstractEvent from './abstract-event';
2
+
3
+ export class DraggableEvent extends AbstractEvent {
4
+ static type = 'draggable';
5
+
6
+ get draggable() {
7
+ return this.data.draggable;
8
+ }
9
+ }
10
+
11
+ export class DraggableInitializedEvent extends DraggableEvent {
12
+ static type = 'draggable:initialize';
13
+ }
14
+
15
+ export class DraggableDestroyEvent extends DraggableEvent {
16
+ static type = 'draggable:destroy';
17
+ }
@@ -0,0 +1,21 @@
1
+ import AbstractEvent from './abstract-event';
2
+
3
+ export class DroppableEvent extends AbstractEvent {
4
+ static type = 'droppable';
5
+
6
+ get dragEvent() {
7
+ return this.data.dragEvent;
8
+ }
9
+
10
+ get droppable() {
11
+ return this.data.droppable;
12
+ }
13
+ }
14
+
15
+ export class DroppableOverEvent extends DroppableEvent {
16
+ static type = 'droppable:over';
17
+ }
18
+
19
+ export class DroppableOutEvent extends DroppableEvent {
20
+ static type = 'droppable:out';
21
+ }
@@ -0,0 +1,43 @@
1
+ import AbstractEvent from './abstract-event';
2
+
3
+ export class MirrorEvent extends AbstractEvent {
4
+ get source() {
5
+ return this.data.source;
6
+ }
7
+
8
+ get mirror() {
9
+ return this.data.mirror;
10
+ }
11
+
12
+ get sourceContainer() {
13
+ return this.data.sourceContainer;
14
+ }
15
+
16
+ get sensorEvent() {
17
+ return this.data.sensorEvent;
18
+ }
19
+
20
+ get originalEvent() {
21
+ if (this.sensorEvent) {
22
+ return this.sensorEvent.originalEvent;
23
+ }
24
+
25
+ return null;
26
+ }
27
+ }
28
+
29
+ export class MirrorCreatedEvent extends MirrorEvent {
30
+ static type = 'mirror:created';
31
+ }
32
+
33
+ export class MirrorAttachedEvent extends MirrorEvent {
34
+ static type = 'mirror:attached';
35
+ }
36
+
37
+ export class MirrorMoveEvent extends MirrorEvent {
38
+ static type = 'mirror:move';
39
+ }
40
+
41
+ export class MirrorDestroyEvent extends MirrorEvent {
42
+ static type = 'mirror:destroy';
43
+ }
@@ -0,0 +1,47 @@
1
+ import AbstractEvent from './abstract-event';
2
+
3
+ export class SensorEvent extends AbstractEvent {
4
+ get originalEvent() {
5
+ return this.data.originalEvent;
6
+ }
7
+
8
+ get clientX() {
9
+ return this.data.clientX;
10
+ }
11
+
12
+ get clientY() {
13
+ return this.data.clientY;
14
+ }
15
+
16
+ get target() {
17
+ return this.data.target;
18
+ }
19
+
20
+ get container() {
21
+ return this.data.container;
22
+ }
23
+
24
+ get overContainer() {
25
+ return this.data.overContainer;
26
+ }
27
+
28
+ get pressure() {
29
+ return this.data.pressure;
30
+ }
31
+ }
32
+
33
+ export class DragStartSensorEvent extends SensorEvent {
34
+ static type = 'drag:start';
35
+ }
36
+
37
+ export class DragMoveSensorEvent extends SensorEvent {
38
+ static type = 'drag:move';
39
+ }
40
+
41
+ export class DragStopSensorEvent extends SensorEvent {
42
+ static type = 'drag:stop';
43
+ }
44
+
45
+ export class DragPressureSensorEvent extends SensorEvent {
46
+ static type = 'drag:pressure';
47
+ }