Skip to content

Commit a8f5272

Browse files
committed
Add keyboard events for reorder
1 parent 7a20a60 commit a8f5272

File tree

2 files changed

+63
-5
lines changed

2 files changed

+63
-5
lines changed

angular-legacy-sortable.js

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,58 @@
9595
});
9696
}
9797

98+
function _withPrevItem(evt, item) {
99+
evt.preventDefault();
100+
var prev = item.previousElementSibling;
101+
if (prev) {
102+
item.parentNode.insertBefore(item, prev);
103+
evt.target.focus();
104+
}
105+
}
106+
107+
function _withNextItem(evt, item) {
108+
var next = item.nextElementSibling;
109+
if (next) {
110+
item.parentNode.insertBefore(next, item);
111+
evt.target.focus();
112+
}
113+
}
114+
115+
function _onKeyDown(evt) {
116+
var item = evt.target.closest(el.children[0].tagName);
117+
if (item) {
118+
evt.oldIndex = Array.prototype.indexOf.call(item.parentNode.children, item);
119+
}
120+
121+
var direction = sortable.options.direction || 'vertical';
122+
123+
if (direction === 'vertical') {
124+
if (evt.key === 'ArrowUp' || evt.keyCode === 38) {
125+
_withPrevItem(evt, item);
126+
}
127+
128+
if (evt.key === 'ArrowDown' || evt.keyCode === 40) {
129+
_withNextItem(evt, item);
130+
}
131+
}
132+
133+
if (direction === 'horizontal') {
134+
if (evt.key === 'ArrowLeft' || evt.keyCode === 37) {
135+
_withPrevItem(evt, item);
136+
}
137+
138+
if (evt.key === 'ArrowRight' || evt.keyCode === 39) {
139+
_withNextItem(evt, item);
140+
}
141+
}
142+
143+
if (item) {
144+
evt.newIndex = Array.prototype.indexOf.call(item.parentNode.children, item);
145+
}
146+
147+
_emitEvent(evt);
148+
scope.$apply();
149+
}
98150

99151
function _sync(/**Event*/evt) {
100152
var items = getSource();
@@ -185,13 +237,17 @@
185237
},
186238
onSort: function (/**Event*/evt) {
187239
_emitEvent(evt);
188-
}
240+
},
189241
}));
190242

243+
el.addEventListener('keydown', function(evt) {
244+
_onKeyDown.call(sortable, evt);
245+
});
246+
191247
// Create watchers for `options`
192248
angular.forEach([
193249
'sort', 'disabled', 'draggable', 'handle', 'animation', 'group', 'ghostClass', 'filter',
194-
'onStart', 'onEnd', 'onAdd', 'onUpdate', 'onRemove', 'onSort', 'onMove', 'onClone', 'setData',
250+
'onStart', 'onEnd', 'onAdd', 'onUpdate', 'onRemove', 'onSort', 'onMove', 'onClone', 'onKeyDown', 'setData',
195251
'delay', 'animation', 'forceFallback'
196252
], function (name) {
197253
watchers.push(scope.$watch('ngSortable.' + name, function (value) {

example/exampleApp.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
angular.module('exampleApp', ['ng-sortable'])
22
.component('dragAndDropExample', {
3-
template: `<ul ng-sortable="$ctrl.sortableConf">
4-
<li ng-repeat="item in $ctrl.items" style="display: inline-block; width: 100px; height: 20px; background: red; font-size: 1rem; outline: 1px solid yellow;">
3+
template: `<ul ng-sortable="$ctrl.sortableConf" style="display: flex; gap: 1em; flex-direction: column;">
4+
<li ng-repeat="item in $ctrl.items" style="display: block; width: 100px; height: 50px; font-size: 1rem; outline: 1px solid yellow;">
55
<span id={{item}}> {{ item }}</span>
6+
<button class="drag-handle" aria-labelledby="drag-instructions">&varr;</button>
67
</li>
7-
</ul>`,
8+
</ul><span hidden id="drag-instructions">Use the Up and Down arrow keys to move this item in the list</span>`,
89
controller: class ExampleAppController {
910
constructor() {
1011
this.items = ['burgers', 'chips', 'hotdog', 'icecream']
1112
this.sortableConf = {
13+
handle: '.drag-handle',
1214
forceFallback: true,
1315
onStart: this.onStart,
1416
onMove: this.onMove,

0 commit comments

Comments
 (0)