Skip to content

Commit

Permalink
Temp
Browse files Browse the repository at this point in the history
  • Loading branch information
tsov committed Dec 8, 2017
1 parent bbfffa2 commit 5360c32
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/Draggable/Draggable.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Focusable, Mirror, Announcement} from './Plugins';
import {
MouseSensor,
TouchSensor,
KeyboardSensor,
} from './Sensors';

import {
Expand Down Expand Up @@ -119,7 +120,7 @@ export default class Draggable {
document.addEventListener('drag:pressure', this[onDragPressure], true);

this.addPlugin(...[Mirror, Focusable, Announcement, ...this.options.plugins]);
this.addSensor(...[MouseSensor, TouchSensor, ...this.options.sensors]);
this.addSensor(...[MouseSensor, TouchSensor, KeyboardSensor, ...this.options.sensors]);

const draggableInitializedEvent = new DraggableInitializedEvent({
draggable: this,
Expand Down Expand Up @@ -322,7 +323,7 @@ export default class Draggable {

this.source = this.originalSource.cloneNode(true);

if (!isDragEvent(originalEvent)) {
if (!isDragEvent(originalEvent) && !isKeyboardEvent(originalEvent)) {
const appendableContainer = this[getAppendableContainer]({source: this.originalSource});
this.mirror = this.source.cloneNode(true);

Expand Down Expand Up @@ -636,6 +637,10 @@ function isDragEvent(event) {
return /^drag/.test(event.type);
}

function isKeyboardEvent(event) {
return /^key/.test(event.type);
}

function applyUserSelect(element, value) {
element.style.webkitUserSelect = value;
element.style.mozUserSelect = value;
Expand Down
186 changes: 186 additions & 0 deletions src/Draggable/Sensors/KeyboardSensor/KeyboardSensor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import {closest, matches} from 'shared/utils';
import Sensor from './../Sensor';

import {
DragStartSensorEvent,
DragMoveSensorEvent,
DragStopSensorEvent,
} from './../SensorEvent';

const SPACE_CODE = 32;

This comment has been minimized.

Copy link
@svinkle

svinkle Dec 15, 2017

Member

Wondering if we should also include the Enter key and attach its event alongside any Space events. I mean, it depends on what the draggable element is in the end, and which role we attach to it. 🤔

This comment has been minimized.

Copy link
@tsov

tsov Jan 9, 2018

Author Member

@svinkle yes, key maps still need to be adjusted. We should also use the ctrl+m fallback and enter to place, rather than space again. Will update and ping when ready 👍

const DOWN_CODE = 40;
const RIGHT_CODE = 39;
const UP_CODE = 38;
const LEFT_CODE = 37;

export default class KeyboardSensor extends Sensor {
constructor(containers = [], options = {}) {
super(containers, options);

this.dragging = false;

this._onKeyup = this._onKeyup.bind(this);
this._onFocus = this._onFocus.bind(this);
this._onBlur = this._onBlur.bind(this);
}

attach() {
document.addEventListener('focus', this._onFocus, true);
document.addEventListener('blur', this._onBlur, true);
document.addEventListener('keydown', this._onKeyup, true);
}

detach() {
document.removeEventListener('focus', this._onFocus, true);
document.removeEventListener('blur', this._onBlur, true);
document.removeEventListener('keydown', this._onKeyup, true);
}

_onFocus(event) {
const draggable = event.target;
const container = closest(event.target, this.containers);
const isDraggable = Boolean(matches(event.target, this.options.handle || this.options.draggable));
const isContainer = Boolean(container);

if (isDraggable && isContainer) {
this.potentialDraggable = draggable;
this.potentialContainer = container;
}
}

_onBlur() {
this.potentialDraggable = null;
this.potentialContainer = null;
}

_onKeyup(event) {
if (!isRelevantKeycode(event)) {
return;
}

if ((this.potentialDraggable && this.potentialContainer) || this.dragging) {
if (event.keyCode === SPACE_CODE) {
this._toggleDrag(event);
event.preventDefault();
return;
}
}

if (!this.dragging) {
return;
}

let target;

if (event.keyCode === RIGHT_CODE || event.keyCode === DOWN_CODE) {
// console.log(this._nextDraggable(this.currentDraggable));
target = this._nextDraggable(this.currentDraggable) || this.allDraggableElements[0];

}

if (event.keyCode === LEFT_CODE || event.keyCode === UP_CODE) {
// console.log(this._previousDraggable(this.currentDraggable));
target = this._previousDraggable(this.currentDraggable) || this.allDraggableElements[this.allDraggableElements.length - 1];
// event.preventDefault();
}

if (!target) {
return;
}

console.log(target);

const rect = target.getBoundingClientRect();

const dragMoveEvent = new DragMoveSensorEvent({
clientX: rect.left + 1,
clientY: rect.top + 1,
target,
container: this.currentContainer,
originalEvent: event,
});

this.trigger(this.currentContainer, dragMoveEvent);
event.preventDefault();
}

_toggleDrag(event) {
if (this.dragging) {
this._dragStop(event);
} else {
this._dragStart(event);
}
}

_dragStart(event) {
const target = this.potentialDraggable;
const container = this.potentialContainer;

const dragStartEvent = new DragStartSensorEvent({
target,
container,
originalEvent: event,
});

this.trigger(container, dragStartEvent);

this.currentDraggable = target;
this.currentContainer = container;
this.dragging = !dragStartEvent.canceled();

requestAnimationFrame(() => {
if (!this.currentContainer) { return; }
this.allDraggableElements = [];
this.containers.forEach((currentContainer) => {
this.allDraggableElements = [
...this.allDraggableElements,
...currentContainer.querySelectorAll(this.options.draggable),
];
});
});
}

_dragStop(event) {
const dragStopEvent = new DragStopSensorEvent({
target: this.potentialDraggable,
container: this.potentialContainer,
originalEvent: event,
});

this.trigger(this.currentContainer, dragStopEvent);
this.dragging = false;
this.allDraggableElements = null;
this.currentDraggable = null;
this.currentContainer = null;
}

_nextDraggable(currentDraggable) {
let currentIndex;
this.allDraggableElements.forEach((draggableElement, index) => {
if (draggableElement === currentDraggable) {
currentIndex = index;
}
});
return this.allDraggableElements[++currentIndex];
}

_previousDraggable(currentDraggable) {
let currentIndex;
this.allDraggableElements.forEach((draggableElement, index) => {
if (draggableElement === currentDraggable) {
currentIndex = index;
}
});
return this.allDraggableElements[--currentIndex];
}
}

function isRelevantKeycode(event) {
return Boolean(
event.keyCode === SPACE_CODE ||
event.keyCode === DOWN_CODE ||
event.keyCode === RIGHT_CODE ||
event.keyCode === UP_CODE ||
event.keyCode === LEFT_CODE
);
}
1 change: 1 addition & 0 deletions src/Draggable/Sensors/KeyboardSensor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
## Keyboard sensor
3 changes: 3 additions & 0 deletions src/Draggable/Sensors/KeyboardSensor/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import KeyboardSensor from './KeyboardSensor';

export default KeyboardSensor;
2 changes: 2 additions & 0 deletions src/Draggable/Sensors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import MouseSensor from './MouseSensor';
import TouchSensor from './TouchSensor';
import DragSensor from './DragSensor';
import ForceTouchSensor from './ForceTouchSensor';
import KeyboardSensor from './KeyboardSensor';

export {
Sensor,
MouseSensor,
TouchSensor,
DragSensor,
ForceTouchSensor,
KeyboardSensor,
};
2 changes: 2 additions & 0 deletions src/shared/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import closest from './closest';
import scroll from './scroll';
import matches from './matches';

export {
closest,
scroll,
matches,
};
1 change: 1 addition & 0 deletions src/shared/utils/matches/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
## matches
3 changes: 3 additions & 0 deletions src/shared/utils/matches/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import matches from './matches';

export default matches;
8 changes: 8 additions & 0 deletions src/shared/utils/matches/matches.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const matchFunction = Element.prototype.matches ||
Element.prototype.webkitMatchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector;

export default function matches(element, selector) {
return matchFunction.call(element, selector);
}

0 comments on commit 5360c32

Please sign in to comment.