ember-sortable 2.4.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +239 -108
- package/MIGRATION_GUIDE_MODIFIERS.md +20 -13
- package/MIGRATION_GUIDE_V2.md +20 -8
- package/README.md +94 -169
- package/RELEASE.md +60 -0
- package/V2_MIGRATION_RFC.md +188 -222
- package/addon/modifiers/sortable-group.js +69 -58
- package/addon/modifiers/sortable-handle.js +22 -19
- package/addon/modifiers/sortable-item.js +126 -82
- package/addon/services/ember-sortable.js +3 -6
- package/addon/system/scroll-parent.js +1 -1
- package/addon/utils/coordinate.js +1 -1
- package/addon/utils/css-calculation.js +2 -2
- package/addon/utils/defaults.js +4 -3
- package/addon/utils/keyboard.js +3 -12
- package/addon-test-support/helpers/drag.js +3 -11
- package/addon-test-support/helpers/index.js +1 -4
- package/addon-test-support/helpers/reorder.js +4 -6
- package/addon-test-support/utils/keyboard.js +3 -12
- package/addon-test-support/utils/offset.js +6 -6
- package/app/services/ember-sortable-internal-state.js +1 -0
- package/config/environment.js +2 -2
- package/index.js +0 -20
- package/package.json +56 -33
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -25
- package/.github/workflows/github_ci.yml +0 -69
- package/addon/components/sortable-group.js +0 -741
- package/addon/components/sortable-handle.js +0 -30
- package/addon/components/sortable-item.js +0 -770
- package/addon/styles/components/sortable-group.css +0 -9
- package/addon/templates/components/sortable-group.hbs +0 -16
- package/addon/templates/components/sortable-handle.hbs +0 -1
- package/addon/templates/components/sortable-item.hbs +0 -2
- package/addon/utils/transitionend.js +0 -22
- package/app/components/sortable-group.js +0 -3
- package/app/components/sortable-handle.js +0 -4
- package/app/components/sortable-item.js +0 -3
- package/vendor/polyfills/closest.js +0 -21
|
@@ -1,23 +1,24 @@
|
|
|
1
|
+
/* eslint-disable ember/no-computed-properties-in-native-classes */
|
|
1
2
|
import Modifier from 'ember-modifier';
|
|
2
3
|
import { Promise, defer } from 'rsvp';
|
|
3
|
-
import {action, set} from '@ember/object';
|
|
4
|
-
import {
|
|
5
|
-
import {or} from '@ember/object/computed';
|
|
6
|
-
import {DRAG_ACTIONS, ELEMENT_CLICK_ACTION, END_ACTIONS} from "../utils/constant";
|
|
4
|
+
import { action, set } from '@ember/object';
|
|
5
|
+
import { DRAG_ACTIONS, ELEMENT_CLICK_ACTION, END_ACTIONS } from '../utils/constant';
|
|
7
6
|
import { run, throttle, bind, scheduleOnce, later } from '@ember/runloop';
|
|
8
7
|
import { DEBUG } from '@glimmer/env';
|
|
9
|
-
import {getX, getY} from
|
|
10
|
-
import ScrollContainer from
|
|
11
|
-
import scrollParent from
|
|
12
|
-
import {getBorderSpacing} from
|
|
8
|
+
import { getX, getY } from '../utils/coordinate';
|
|
9
|
+
import ScrollContainer from '../system/scroll-container';
|
|
10
|
+
import scrollParent from '../system/scroll-parent';
|
|
11
|
+
import { getBorderSpacing } from '../utils/css-calculation';
|
|
13
12
|
import { buildWaiter } from '@ember/test-waiters';
|
|
14
|
-
import {inject as service} from '@ember/service';
|
|
13
|
+
import { inject as service } from '@ember/service';
|
|
15
14
|
import { assert, deprecate } from '@ember/debug';
|
|
16
15
|
import config from 'ember-get-config';
|
|
16
|
+
import { registerDestructor } from '@ember/destroyable';
|
|
17
|
+
|
|
17
18
|
const { environment } = config;
|
|
18
19
|
const isTesting = environment === 'test';
|
|
19
20
|
|
|
20
|
-
const sortableItemWaiter = buildWaiter(
|
|
21
|
+
const sortableItemWaiter = buildWaiter('sortable-item-waiter');
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Modifier to mark an element as an item to be reordered
|
|
@@ -39,8 +40,9 @@ const sortableItemWaiter = buildWaiter("sortable-item-waiter");
|
|
|
39
40
|
* </ol>
|
|
40
41
|
*/
|
|
41
42
|
export default class SortableItemModifier extends Modifier {
|
|
43
|
+
className = 'sortable-item';
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
@service('ember-sortable-internal-state') sortableService;
|
|
44
46
|
|
|
45
47
|
_sortableGroup;
|
|
46
48
|
/**
|
|
@@ -52,22 +54,25 @@ export default class SortableItemModifier extends Modifier {
|
|
|
52
54
|
get sortableGroup() {
|
|
53
55
|
if (this._sortableGroup === undefined) {
|
|
54
56
|
this._sortableGroup = this.sortableService.fetchGroup(this.groupName);
|
|
55
|
-
assert(
|
|
57
|
+
assert(
|
|
58
|
+
`No sortable group named ${this.groupName} found. Please check that the groups and items have the same groupName`,
|
|
59
|
+
this._sortableGroup !== undefined
|
|
60
|
+
);
|
|
56
61
|
}
|
|
57
62
|
return this._sortableGroup.groupModifier;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
@reads("sortableGroup.direction")
|
|
64
|
-
direction;
|
|
65
|
+
get model() {
|
|
66
|
+
return this.args.named.model;
|
|
67
|
+
}
|
|
65
68
|
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
get direction() {
|
|
70
|
+
return this.sortableGroup.direction;
|
|
71
|
+
}
|
|
68
72
|
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
get groupDisabled() {
|
|
74
|
+
return this.sortableGroup.disabled;
|
|
75
|
+
}
|
|
71
76
|
|
|
72
77
|
/**
|
|
73
78
|
* This is the group name used to keep groups separate if there are more than one on the screen at a time.
|
|
@@ -77,7 +82,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
77
82
|
* @returns {*|string}
|
|
78
83
|
*/
|
|
79
84
|
get groupName() {
|
|
80
|
-
return this.args.named.groupName ||
|
|
85
|
+
return this.args.named.groupName || '_EmberSortableGroup';
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
/**
|
|
@@ -110,7 +115,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
110
115
|
get isDisabled() {
|
|
111
116
|
deprecate(
|
|
112
117
|
'"isDraggingDisabled" is deprecated. Please migrate to "disabled" named argument',
|
|
113
|
-
!(
|
|
118
|
+
!('isDraggingDisabled' in this.args.named),
|
|
114
119
|
{
|
|
115
120
|
id: 'ember-sortable.is-dragging-disabled',
|
|
116
121
|
url: 'https://github.com/adopted-ember-addons/ember-sortable#readme',
|
|
@@ -120,7 +125,8 @@ export default class SortableItemModifier extends Modifier {
|
|
|
120
125
|
available: '2.2.6',
|
|
121
126
|
enabled: '2.2.6',
|
|
122
127
|
},
|
|
123
|
-
}
|
|
128
|
+
}
|
|
129
|
+
);
|
|
124
130
|
|
|
125
131
|
return this.groupDisabled || this.args.named.disabled || this.args.named.isDraggingDisabled || false;
|
|
126
132
|
}
|
|
@@ -137,7 +143,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
137
143
|
@default "[data-sortable-handle]"
|
|
138
144
|
*/
|
|
139
145
|
get handle() {
|
|
140
|
-
return this.args.named.handle ||
|
|
146
|
+
return this.args.named.handle || '[data-sortable-handle]';
|
|
141
147
|
}
|
|
142
148
|
|
|
143
149
|
handleElement;
|
|
@@ -170,9 +176,9 @@ export default class SortableItemModifier extends Modifier {
|
|
|
170
176
|
}
|
|
171
177
|
set isDragging(value) {
|
|
172
178
|
if (value) {
|
|
173
|
-
this.element.classList.add(
|
|
179
|
+
this.element.classList.add('is-dragging');
|
|
174
180
|
} else {
|
|
175
|
-
this.element.classList.remove(
|
|
181
|
+
this.element.classList.remove('is-dragging');
|
|
176
182
|
}
|
|
177
183
|
this._isDragging = value;
|
|
178
184
|
}
|
|
@@ -185,7 +191,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
185
191
|
@default null
|
|
186
192
|
*/
|
|
187
193
|
get onDragStart() {
|
|
188
|
-
return this.args.named.onDragStart || (item => item);
|
|
194
|
+
return this.args.named.onDragStart || ((item) => item);
|
|
189
195
|
}
|
|
190
196
|
|
|
191
197
|
/**
|
|
@@ -196,7 +202,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
196
202
|
@default null
|
|
197
203
|
*/
|
|
198
204
|
get onDragStop() {
|
|
199
|
-
return this.args.named.onDragStop || (item => item);
|
|
205
|
+
return this.args.named.onDragStop || ((item) => item);
|
|
200
206
|
}
|
|
201
207
|
|
|
202
208
|
/**
|
|
@@ -211,9 +217,9 @@ export default class SortableItemModifier extends Modifier {
|
|
|
211
217
|
}
|
|
212
218
|
set isDropping(value) {
|
|
213
219
|
if (value) {
|
|
214
|
-
this.element.classList.add(
|
|
220
|
+
this.element.classList.add('is-dropping');
|
|
215
221
|
} else {
|
|
216
|
-
this.element.classList.remove(
|
|
222
|
+
this.element.classList.remove('is-dropping');
|
|
217
223
|
}
|
|
218
224
|
this._isDropping = value;
|
|
219
225
|
}
|
|
@@ -230,8 +236,9 @@ export default class SortableItemModifier extends Modifier {
|
|
|
230
236
|
@property isBusy
|
|
231
237
|
@type Boolean
|
|
232
238
|
*/
|
|
233
|
-
|
|
234
|
-
|
|
239
|
+
get isBusy() {
|
|
240
|
+
return this.isDragging || this.isDropping;
|
|
241
|
+
}
|
|
235
242
|
|
|
236
243
|
/**
|
|
237
244
|
@property disableCheckScrollBounds
|
|
@@ -245,15 +252,21 @@ export default class SortableItemModifier extends Modifier {
|
|
|
245
252
|
*/
|
|
246
253
|
@action
|
|
247
254
|
mouseDown(event) {
|
|
248
|
-
if (event.which !== 1) {
|
|
249
|
-
|
|
255
|
+
if (event.which !== 1) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (event.ctrlKey) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
250
261
|
|
|
251
262
|
this._primeDrag(event);
|
|
252
263
|
}
|
|
253
264
|
|
|
254
265
|
@action
|
|
255
266
|
keyDown(event) {
|
|
256
|
-
if (this.isDisabled) {
|
|
267
|
+
if (this.isDisabled) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
257
270
|
|
|
258
271
|
// If the event is coming from within the item, we do not want to activate keyboard reorder mode.
|
|
259
272
|
if (event.target === this.handleElement || event.target === this.element) {
|
|
@@ -276,7 +289,9 @@ export default class SortableItemModifier extends Modifier {
|
|
|
276
289
|
*/
|
|
277
290
|
freeze() {
|
|
278
291
|
let el = this.element;
|
|
279
|
-
if (!el) {
|
|
292
|
+
if (!el) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
280
295
|
|
|
281
296
|
el.style.transition = 'none';
|
|
282
297
|
}
|
|
@@ -286,7 +301,9 @@ export default class SortableItemModifier extends Modifier {
|
|
|
286
301
|
*/
|
|
287
302
|
reset() {
|
|
288
303
|
let el = this.element;
|
|
289
|
-
if (!el) {
|
|
304
|
+
if (!el) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
290
307
|
|
|
291
308
|
delete this._y;
|
|
292
309
|
delete this._x;
|
|
@@ -299,7 +316,9 @@ export default class SortableItemModifier extends Modifier {
|
|
|
299
316
|
*/
|
|
300
317
|
thaw() {
|
|
301
318
|
let el = this.element;
|
|
302
|
-
if (!el) {
|
|
319
|
+
if (!el) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
303
322
|
|
|
304
323
|
el.style.transition = '';
|
|
305
324
|
}
|
|
@@ -312,7 +331,9 @@ export default class SortableItemModifier extends Modifier {
|
|
|
312
331
|
* @private
|
|
313
332
|
*/
|
|
314
333
|
_primeDrag(startEvent) {
|
|
315
|
-
if (this.isDisabled) {
|
|
334
|
+
if (this.isDisabled) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
316
337
|
|
|
317
338
|
if (this.handleElement && !startEvent.target.closest(this.handle)) {
|
|
318
339
|
return;
|
|
@@ -323,18 +344,18 @@ export default class SortableItemModifier extends Modifier {
|
|
|
323
344
|
|
|
324
345
|
this._prepareDragListener = bind(this, this._prepareDrag, startEvent);
|
|
325
346
|
|
|
326
|
-
DRAG_ACTIONS.forEach(event => window.addEventListener(event, this._prepareDragListener));
|
|
347
|
+
DRAG_ACTIONS.forEach((event) => window.addEventListener(event, this._prepareDragListener));
|
|
327
348
|
|
|
328
349
|
this._cancelStartDragListener = () => {
|
|
329
|
-
DRAG_ACTIONS.forEach(event => window.removeEventListener(event, this._prepareDragListener));
|
|
350
|
+
DRAG_ACTIONS.forEach((event) => window.removeEventListener(event, this._prepareDragListener));
|
|
330
351
|
};
|
|
331
352
|
|
|
332
353
|
const selfCancellingCallback = () => {
|
|
333
|
-
END_ACTIONS.forEach(event => window.removeEventListener(event, selfCancellingCallback));
|
|
354
|
+
END_ACTIONS.forEach((event) => window.removeEventListener(event, selfCancellingCallback));
|
|
334
355
|
this._cancelStartDragListener();
|
|
335
356
|
};
|
|
336
357
|
|
|
337
|
-
END_ACTIONS.forEach(event => window.addEventListener(event, selfCancellingCallback));
|
|
358
|
+
END_ACTIONS.forEach((event) => window.addEventListener(event, selfCancellingCallback));
|
|
338
359
|
}
|
|
339
360
|
|
|
340
361
|
/**
|
|
@@ -351,7 +372,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
351
372
|
let dy = Math.abs(getY(startEvent) - getY(event));
|
|
352
373
|
|
|
353
374
|
if (distance <= dx || distance <= dy) {
|
|
354
|
-
DRAG_ACTIONS.forEach(event => window.removeEventListener(event, this._prepareDragListener));
|
|
375
|
+
DRAG_ACTIONS.forEach((event) => window.removeEventListener(event, this._prepareDragListener));
|
|
355
376
|
this._startDrag(startEvent);
|
|
356
377
|
}
|
|
357
378
|
}
|
|
@@ -364,25 +385,27 @@ export default class SortableItemModifier extends Modifier {
|
|
|
364
385
|
* @private
|
|
365
386
|
*/
|
|
366
387
|
_startDrag(event) {
|
|
367
|
-
if (this.isBusy) {
|
|
388
|
+
if (this.isBusy) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
368
391
|
|
|
369
392
|
let drag = this._makeDragHandler(event);
|
|
370
|
-
let dragThrottled = ev => throttle(this, drag, ev, 16, false);
|
|
393
|
+
let dragThrottled = (ev) => throttle(this, drag, ev, 16, false);
|
|
371
394
|
|
|
372
395
|
let drop = () => {
|
|
373
|
-
DRAG_ACTIONS.forEach(event => window.removeEventListener(event, dragThrottled));
|
|
374
|
-
END_ACTIONS.forEach(event => window.removeEventListener(event, drop));
|
|
396
|
+
DRAG_ACTIONS.forEach((event) => window.removeEventListener(event, dragThrottled));
|
|
397
|
+
END_ACTIONS.forEach((event) => window.removeEventListener(event, drop));
|
|
375
398
|
|
|
376
399
|
run(() => {
|
|
377
400
|
this._drop();
|
|
378
401
|
});
|
|
379
402
|
};
|
|
380
403
|
|
|
381
|
-
DRAG_ACTIONS.forEach(event => window.addEventListener(event, dragThrottled));
|
|
382
|
-
END_ACTIONS.forEach(event => window.addEventListener(event, drop));
|
|
404
|
+
DRAG_ACTIONS.forEach((event) => window.addEventListener(event, dragThrottled));
|
|
405
|
+
END_ACTIONS.forEach((event) => window.addEventListener(event, drop));
|
|
383
406
|
|
|
384
407
|
this.sortableGroup.prepare();
|
|
385
|
-
set(this,
|
|
408
|
+
set(this, 'isDragging', true);
|
|
386
409
|
this.onDragStart(this.model);
|
|
387
410
|
this._scrollOnEdges(drag);
|
|
388
411
|
}
|
|
@@ -414,7 +437,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
414
437
|
},
|
|
415
438
|
get bottom() {
|
|
416
439
|
return this.top + this.height;
|
|
417
|
-
}
|
|
440
|
+
},
|
|
418
441
|
};
|
|
419
442
|
|
|
420
443
|
let leadingEdgeKey, trailingEdgeKey, scrollKey, pageKey;
|
|
@@ -431,12 +454,14 @@ export default class SortableItemModifier extends Modifier {
|
|
|
431
454
|
}
|
|
432
455
|
|
|
433
456
|
let createFakeEvent = () => {
|
|
434
|
-
if (this._pageX == null && this._pageY == null) {
|
|
457
|
+
if (this._pageX == null && this._pageY == null) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
435
460
|
return {
|
|
436
461
|
pageX: this._pageX,
|
|
437
462
|
pageY: this._pageY,
|
|
438
463
|
clientX: this._pageX,
|
|
439
|
-
clientY: this._pageY
|
|
464
|
+
clientY: this._pageY,
|
|
440
465
|
};
|
|
441
466
|
};
|
|
442
467
|
|
|
@@ -497,7 +522,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
497
522
|
elementOrigin = this.x;
|
|
498
523
|
scrollOrigin = parentElement.getBoundingClientRect().left;
|
|
499
524
|
|
|
500
|
-
return event => {
|
|
525
|
+
return (event) => {
|
|
501
526
|
this._pageX = getX(event);
|
|
502
527
|
let dx = this._pageX - dragOrigin;
|
|
503
528
|
let scrollX = parentElement.getBoundingClientRect().left;
|
|
@@ -512,7 +537,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
512
537
|
elementOrigin = this.y;
|
|
513
538
|
scrollOrigin = parentElement.getBoundingClientRect().top;
|
|
514
539
|
|
|
515
|
-
return event => {
|
|
540
|
+
return (event) => {
|
|
516
541
|
this._pageY = getY(event);
|
|
517
542
|
let dy = this._pageY - dragOrigin;
|
|
518
543
|
let scrollY = parentElement.getBoundingClientRect().top;
|
|
@@ -536,7 +561,9 @@ export default class SortableItemModifier extends Modifier {
|
|
|
536
561
|
@private
|
|
537
562
|
*/
|
|
538
563
|
_applyPosition() {
|
|
539
|
-
if (!this.element || !this.element) {
|
|
564
|
+
if (!this.element || !this.element) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
540
567
|
|
|
541
568
|
const groupDirection = this.direction;
|
|
542
569
|
|
|
@@ -559,7 +586,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
559
586
|
@private
|
|
560
587
|
*/
|
|
561
588
|
_drag(dimension) {
|
|
562
|
-
if(!this.isDragging) {
|
|
589
|
+
if (!this.isDragging) {
|
|
563
590
|
return;
|
|
564
591
|
}
|
|
565
592
|
let updateInterval = this.updateInterval;
|
|
@@ -580,14 +607,16 @@ export default class SortableItemModifier extends Modifier {
|
|
|
580
607
|
@private
|
|
581
608
|
*/
|
|
582
609
|
_drop() {
|
|
583
|
-
if (!this.element) {
|
|
610
|
+
if (!this.element) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
584
613
|
|
|
585
614
|
let transitionPromise = this._waitForTransition();
|
|
586
615
|
|
|
587
616
|
this._preventClick();
|
|
588
617
|
|
|
589
|
-
set(this,
|
|
590
|
-
set(this,
|
|
618
|
+
set(this, 'isDragging', false);
|
|
619
|
+
set(this, 'isDropping', true);
|
|
591
620
|
|
|
592
621
|
this.sortableGroup.update();
|
|
593
622
|
transitionPromise.then(() => this._complete());
|
|
@@ -656,8 +685,8 @@ export default class SortableItemModifier extends Modifier {
|
|
|
656
685
|
*/
|
|
657
686
|
_complete() {
|
|
658
687
|
this.onDragStop(this.model);
|
|
659
|
-
set(this,
|
|
660
|
-
set(this,
|
|
688
|
+
set(this, 'isDropping', false);
|
|
689
|
+
set(this, 'wasDropped', true);
|
|
661
690
|
this.sortableGroup.commit();
|
|
662
691
|
}
|
|
663
692
|
|
|
@@ -677,7 +706,7 @@ export default class SortableItemModifier extends Modifier {
|
|
|
677
706
|
@property transitionDuration
|
|
678
707
|
@type Number
|
|
679
708
|
*/
|
|
680
|
-
|
|
709
|
+
get transitionDuration() {
|
|
681
710
|
let el = this.element;
|
|
682
711
|
let rule = getComputedStyle(el).transitionDuration;
|
|
683
712
|
let match = rule.match(/([\d.]+)([ms]*)/);
|
|
@@ -771,39 +800,54 @@ export default class SortableItemModifier extends Modifier {
|
|
|
771
800
|
}
|
|
772
801
|
|
|
773
802
|
addEventListener() {
|
|
774
|
-
this.element.addEventListener(
|
|
775
|
-
this.element.addEventListener(
|
|
776
|
-
this.element.addEventListener(
|
|
803
|
+
this.element.addEventListener('keydown', this.keyDown);
|
|
804
|
+
this.element.addEventListener('mousedown', this.mouseDown);
|
|
805
|
+
this.element.addEventListener('touchstart', this.touchStart);
|
|
777
806
|
}
|
|
778
807
|
|
|
779
808
|
removeEventListener() {
|
|
780
|
-
this.element.removeEventListener(
|
|
781
|
-
this.element.removeEventListener(
|
|
782
|
-
this.element.removeEventListener(
|
|
809
|
+
this.element.removeEventListener('keydown', this.keyDown);
|
|
810
|
+
this.element.removeEventListener('mousedown', this.mouseDown);
|
|
811
|
+
this.element.removeEventListener('touchstart', this.touchStart);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
element;
|
|
815
|
+
didSetup = false;
|
|
816
|
+
|
|
817
|
+
constructor(owner, args) {
|
|
818
|
+
super(owner, args);
|
|
819
|
+
registerDestructor(this, cleanup);
|
|
783
820
|
}
|
|
784
821
|
|
|
785
|
-
|
|
822
|
+
modify(element /*, positional, named*/) {
|
|
823
|
+
this.element = element;
|
|
824
|
+
|
|
786
825
|
this.element.classList.add(this.className);
|
|
787
826
|
|
|
788
827
|
// Instead of using `event.preventDefault()` in the 'primeDrag' event,
|
|
789
828
|
// (doesn't work in Chrome 56), we set touch-action: none as a workaround.
|
|
790
829
|
this.handleElement = this.element.querySelector(this.handle);
|
|
830
|
+
|
|
791
831
|
if (this.handleElement) {
|
|
792
832
|
this.handleElement.style['touch-action'] = 'none';
|
|
793
833
|
} else {
|
|
794
834
|
this.element.style['touch-action'] = 'none';
|
|
795
835
|
}
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
didInstall() {
|
|
799
|
-
this.addEventListener();
|
|
800
|
-
this.element.dataset.sortableItem=true;
|
|
801
|
-
this.sortableService.registerItem(this.groupName, this);
|
|
802
|
-
}
|
|
803
836
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
837
|
+
if (!this.didSetup) {
|
|
838
|
+
this.addEventListener();
|
|
839
|
+
this.element.dataset.sortableItem = true;
|
|
840
|
+
this.sortableService.registerItem(this.groupName, this);
|
|
841
|
+
this.didSetup = true;
|
|
842
|
+
}
|
|
807
843
|
}
|
|
844
|
+
}
|
|
808
845
|
|
|
846
|
+
/**
|
|
847
|
+
*
|
|
848
|
+
* @param {SortableItemModifier} instance
|
|
849
|
+
*/
|
|
850
|
+
function cleanup(instance) {
|
|
851
|
+
instance.removeEventListener();
|
|
852
|
+
instance.sortableService.deregisterItem(instance.groupName, instance);
|
|
809
853
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Service from '@ember/service';
|
|
2
2
|
|
|
3
3
|
export default class EmberSortableService extends Service {
|
|
4
|
-
|
|
5
4
|
/**
|
|
6
5
|
* Internal State for any groups currently in DOM
|
|
7
6
|
*
|
|
@@ -13,9 +12,7 @@ export default class EmberSortableService extends Service {
|
|
|
13
12
|
* }
|
|
14
13
|
* @type {{}}
|
|
15
14
|
*/
|
|
16
|
-
groups = {
|
|
17
|
-
|
|
18
|
-
};
|
|
15
|
+
groups = {};
|
|
19
16
|
|
|
20
17
|
/**
|
|
21
18
|
* Register a new group with the service
|
|
@@ -27,8 +24,8 @@ export default class EmberSortableService extends Service {
|
|
|
27
24
|
if (this.groups[groupName] === undefined) {
|
|
28
25
|
this.groups[groupName] = {
|
|
29
26
|
groupModifier: groupModifier,
|
|
30
|
-
items: []
|
|
31
|
-
}
|
|
27
|
+
items: [],
|
|
28
|
+
};
|
|
32
29
|
} else {
|
|
33
30
|
this.groups[groupName].groupModifier = groupModifier;
|
|
34
31
|
}
|
|
@@ -17,7 +17,7 @@ function getParentElements(element) {
|
|
|
17
17
|
export default function (element) {
|
|
18
18
|
let position = getComputedStyle(element).position;
|
|
19
19
|
let excludeStaticParent = position === 'absolute';
|
|
20
|
-
let scrollParent = getParentElements(element).filter(function(parent) {
|
|
20
|
+
let scrollParent = getParentElements(element).filter(function (parent) {
|
|
21
21
|
let parentElemStyles = getComputedStyle(parent);
|
|
22
22
|
if (excludeStaticParent && parentElemStyles.position === 'static') {
|
|
23
23
|
return false;
|
package/addon/utils/defaults.js
CHANGED
|
@@ -4,8 +4,7 @@ export const defaultA11yAnnouncementConfig = {
|
|
|
4
4
|
|
|
5
5
|
if (direction === 'y') {
|
|
6
6
|
message += 'Press up and down keys to change position,';
|
|
7
|
-
}
|
|
8
|
-
else {
|
|
7
|
+
} else {
|
|
9
8
|
message += 'Press left and right keys to change position,';
|
|
10
9
|
}
|
|
11
10
|
|
|
@@ -14,7 +13,9 @@ export const defaultA11yAnnouncementConfig = {
|
|
|
14
13
|
return message;
|
|
15
14
|
},
|
|
16
15
|
MOVE({ a11yItemName, index, maxLength, delta }) {
|
|
17
|
-
return `${a11yItemName} is moved to position, ${
|
|
16
|
+
return `${a11yItemName} is moved to position, ${
|
|
17
|
+
index + 1 + delta
|
|
18
|
+
} of ${maxLength}. Press Space to confirm new position, Escape to cancel.`;
|
|
18
19
|
},
|
|
19
20
|
CONFIRM({ a11yItemName }) {
|
|
20
21
|
return `${a11yItemName} is successfully repositioned.`;
|
package/addon/utils/keyboard.js
CHANGED
|
@@ -26,16 +26,7 @@ function createKeyTest(key, keyCode) {
|
|
|
26
26
|
export const isEnterKey = createKeyTest(ENTER_KEY, ENTER_KEY_CODE);
|
|
27
27
|
export const isEscapeKey = createKeyTest(ESCAPE_KEY, ESCAPE_KEY_CODE);
|
|
28
28
|
export const isSpaceKey = createKeyTest(SPACE_KEY, SPACE_KEY_CODE);
|
|
29
|
-
export const isLeftArrowKey = createKeyTest(
|
|
30
|
-
ARROW_KEYS.LEFT,
|
|
31
|
-
ARROW_KEY_CODES.LEFT
|
|
32
|
-
);
|
|
29
|
+
export const isLeftArrowKey = createKeyTest(ARROW_KEYS.LEFT, ARROW_KEY_CODES.LEFT);
|
|
33
30
|
export const isUpArrowKey = createKeyTest(ARROW_KEYS.UP, ARROW_KEY_CODES.UP);
|
|
34
|
-
export const isRightArrowKey = createKeyTest(
|
|
35
|
-
|
|
36
|
-
ARROW_KEY_CODES.RIGHT
|
|
37
|
-
);
|
|
38
|
-
export const isDownArrowKey = createKeyTest(
|
|
39
|
-
ARROW_KEYS.DOWN,
|
|
40
|
-
ARROW_KEY_CODES.DOWN
|
|
41
|
-
);
|
|
31
|
+
export const isRightArrowKey = createKeyTest(ARROW_KEYS.RIGHT, ARROW_KEY_CODES.RIGHT);
|
|
32
|
+
export const isDownArrowKey = createKeyTest(ARROW_KEYS.DOWN, ARROW_KEY_CODES.DOWN);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { triggerEvent, find, settled
|
|
1
|
+
import { triggerEvent, find, settled } from '@ember/test-helpers';
|
|
2
2
|
import { getOffset } from '../utils/offset';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -26,12 +26,7 @@ import { getOffset } from '../utils/offset';
|
|
|
26
26
|
@return {Promise}
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
export async function drag(
|
|
30
|
-
mode,
|
|
31
|
-
itemSelector,
|
|
32
|
-
offsetFn,
|
|
33
|
-
callbacks = {}
|
|
34
|
-
) {
|
|
29
|
+
export async function drag(mode, itemSelector, offsetFn, callbacks = {}) {
|
|
35
30
|
let start;
|
|
36
31
|
let move;
|
|
37
32
|
let end;
|
|
@@ -62,10 +57,7 @@ export async function drag(
|
|
|
62
57
|
// https://stackoverflow.com/a/5042051
|
|
63
58
|
const dx = offset.dx || 0;
|
|
64
59
|
const dy = offset.dy || 0;
|
|
65
|
-
const clientHeight =
|
|
66
|
-
itemElement.clientHeight ||
|
|
67
|
-
itemElement.offsetHeight ||
|
|
68
|
-
itemElement.parentNode.offsetHeight;
|
|
60
|
+
const clientHeight = itemElement.clientHeight || itemElement.offsetHeight || itemElement.parentNode.offsetHeight;
|
|
69
61
|
const scale = clientHeight / (rect.bottom - rect.top);
|
|
70
62
|
const halfwayX = itemOffset.left + (dx * scale) / 2;
|
|
71
63
|
const halfwayY = itemOffset.top + (dy * scale) / 2;
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { find, findAll } from '@ember/test-helpers';
|
|
2
2
|
import { drag } from './drag';
|
|
3
3
|
import { getOffset } from '../utils/offset';
|
|
4
|
-
|
|
5
|
-
In tests, the dummy app is rendered at half size.
|
|
6
|
-
To avoid rounding errors, we must therefore double
|
|
7
|
-
the overshoot.
|
|
8
|
-
*/
|
|
4
|
+
|
|
9
5
|
const OVERSHOOT = 2;
|
|
10
6
|
|
|
11
7
|
/**
|
|
@@ -38,6 +34,8 @@ export async function reorder(mode, itemSelector, ...resultSelectors) {
|
|
|
38
34
|
const dx = getOffset(targetElement).left - OVERSHOOT - getOffset(sourceElement).left;
|
|
39
35
|
const dy = getOffset(targetElement).top - OVERSHOOT - getOffset(sourceElement).top;
|
|
40
36
|
|
|
41
|
-
await drag(mode, sourceElement, () => {
|
|
37
|
+
await drag(mode, sourceElement, () => {
|
|
38
|
+
return { dx: dx, dy: dy };
|
|
39
|
+
});
|
|
42
40
|
}
|
|
43
41
|
}
|
|
@@ -26,16 +26,7 @@ function createKeyTest(key, keyCode) {
|
|
|
26
26
|
export const isEnterKey = createKeyTest(ENTER_KEY, ENTER_KEY_CODE);
|
|
27
27
|
export const isEscapeKey = createKeyTest(ESCAPE_KEY, ESCAPE_KEY_CODE);
|
|
28
28
|
export const isSpaceKey = createKeyTest(SPACE_KEY, SPACE_KEY_CODE);
|
|
29
|
-
export const isLeftArrowKey = createKeyTest(
|
|
30
|
-
ARROW_KEYS.LEFT,
|
|
31
|
-
ARROW_KEY_CODES.LEFT
|
|
32
|
-
);
|
|
29
|
+
export const isLeftArrowKey = createKeyTest(ARROW_KEYS.LEFT, ARROW_KEY_CODES.LEFT);
|
|
33
30
|
export const isUpArrowKey = createKeyTest(ARROW_KEYS.UP, ARROW_KEY_CODES.UP);
|
|
34
|
-
export const isRightArrowKey = createKeyTest(
|
|
35
|
-
|
|
36
|
-
ARROW_KEY_CODES.RIGHT
|
|
37
|
-
);
|
|
38
|
-
export const isDownArrowKey = createKeyTest(
|
|
39
|
-
ARROW_KEYS.DOWN,
|
|
40
|
-
ARROW_KEY_CODES.DOWN
|
|
41
|
-
);
|
|
31
|
+
export const isRightArrowKey = createKeyTest(ARROW_KEYS.RIGHT, ARROW_KEY_CODES.RIGHT);
|
|
32
|
+
export const isDownArrowKey = createKeyTest(ARROW_KEYS.DOWN, ARROW_KEY_CODES.DOWN);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** Vanilla Javascript equivalent of JQuery's `.offset`.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
* Reference: https://github.com/nefe/You-Dont-Need-jQuery
|
|
3
|
+
*
|
|
4
|
+
* @method getOffset
|
|
5
|
+
* @param {Element} el an element
|
|
6
|
+
*/
|
|
7
7
|
export function getOffset(el) {
|
|
8
8
|
const box = el.getBoundingClientRect();
|
|
9
9
|
|
|
@@ -11,4 +11,4 @@ export function getOffset(el) {
|
|
|
11
11
|
top: box.top + window.pageYOffset - document.documentElement.clientTop,
|
|
12
12
|
left: box.left + window.pageXOffset - document.documentElement.clientLeft,
|
|
13
13
|
};
|
|
14
|
-
}
|
|
14
|
+
}
|