Skip to content

Commit e02c37c

Browse files
committed
Rewrite cyclejs-sortable
1 parent cecc87b commit e02c37c

10 files changed

+339
-770
lines changed

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"documentation": "typedoc --out docs src && cp-cli .nojekyll docs/.nojekyll",
1919
"prepublishOnly": "npm run build && npm run documentation && cp-cli examples docs/",
2020
"examples": "npm run build:examples && npm run examples:simple && npm run examples:horizontal && npm run examples:parentSelector && npm run examples:updateEvent",
21-
"examples:simple": "browserify build/examples/simple/src/index.js -o examples/simple/index.js && open-cli examples/simple/index.html",
21+
"examples:simple": "browserify build/examples/simple/src/index.js -o examples/simple/index.js",
2222
"examples:horizontal": "browserify build/examples/horizontal/src/index.js -o examples/horizontal/index.js && open-cli examples/horizontal/index.html",
2323
"examples:parentSelector": "browserify build/examples/parentSelector/src/index.js -o examples/parentSelector/index.js && open-cli examples/parentSelector/index.html",
2424
"examples:updateEvent": "browserify build/examples/updateEvent/src/index.js -o examples/updateEvent/index.js && open-cli examples/updateEvent/index.html"

src/definitions.ts

-90
This file was deleted.

src/eventHandler.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { VNode } from '@cycle/dom';
2+
3+
import { SortableOptions } from './makeSortable';
4+
5+
import { mousedownHandler } from './eventHandlers/mousedown';
6+
import { mouseupHandler } from './eventHandlers/mouseup';
7+
import { mousemoveHandler } from './eventHandlers/mousemove';
8+
9+
export function handleEvent(
10+
options: SortableOptions
11+
): (node: VNode, event: MouseEvent) => VNode {
12+
return function(node: VNode, event: MouseEvent): VNode {
13+
const eventHandlerMapping = {
14+
mousedown: mousedownHandler,
15+
touchstart: mousedownHandler,
16+
mouseleave: mouseupHandler,
17+
mouseup: mouseupHandler,
18+
touchend: mouseupHandler,
19+
mousemove: mousemoveHandler,
20+
touchmove: mousemoveHandler
21+
};
22+
return eventHandlerMapping[event.type](node, event, options);
23+
};
24+
}

src/eventHandlers.ts

-31
This file was deleted.

src/eventHandlers/mousedown.ts

+76-56
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,86 @@
11
import { VNode } from '@cycle/dom';
2-
import { select } from 'snabbdom-selector';
3-
import { EventHandler, MouseOffset, SortableOptions } from '../definitions';
42

5-
import {
6-
getIndex,
7-
getGhostStyle,
8-
findParent,
9-
addAttributes,
10-
addGhostClass,
11-
replaceNode,
12-
getBodyStyle,
13-
addKeys
14-
} from '../helpers';
3+
import { SortableOptions } from '../makeSortable';
4+
import { addDataEntry } from '../helpers';
155

16-
/**
17-
* Used to create the ghost and hide the item dragged
18-
* @type {EventHandler}
19-
*/
20-
export const mousedownHandler: EventHandler = (node, event, options) => {
21-
const item: Element = findParent(
22-
event.target as Element,
23-
options.parentSelector + ' > *'
24-
);
25-
const itemRect: ClientRect = item.getBoundingClientRect();
26-
const parentNode: Element = item.parentElement;
27-
const parentRect: ClientRect = parentNode.getBoundingClientRect();
28-
const mouseOffset: MouseOffset = {
29-
x: itemRect.left - event.clientX,
30-
y: itemRect.top - event.clientY,
31-
itemLeft: itemRect.left,
32-
itemTop: itemRect.top,
33-
parentLeft: parentRect.left,
34-
parentTop: parentRect.top
35-
};
6+
export const selectNames = [
7+
'-webkit-touch-callout',
8+
'-webkit-user-select',
9+
'-khtml-user-select',
10+
'-moz-user-select',
11+
'-ms-user-select',
12+
'user-select'
13+
];
3614

37-
const body: Element = findParent(event.target as Element, 'body');
38-
body.setAttribute('style', getBodyStyle());
15+
export function mousedownHandler(
16+
node: VNode,
17+
ev: MouseEvent,
18+
opts: SortableOptions
19+
): VNode {
20+
const item: Element = ev.currentTarget as Element;
21+
const indexClicked = [...item.parentElement.children].indexOf(item);
3922

40-
const parent: VNode = select(options.parentSelector, node)[0];
41-
const index: number = getIndex(item);
42-
const ghostAttrs: { [name: string]: string } = {
43-
'data-mouseoffset': JSON.stringify(mouseOffset),
44-
'data-itemdimensions': JSON.stringify({
45-
width: itemRect.width,
46-
height: itemRect.height
23+
const children = node.children
24+
.map(addData)
25+
.map(hideSelected(indexClicked))
26+
.concat(
27+
createGhost(indexClicked, ev, item, node.children[
28+
indexClicked
29+
] as VNode)
30+
);
31+
32+
return {
33+
...addDataEntry(node, 'style', {
34+
...selectNames
35+
.map(n => ({ [n]: 'none' }))
36+
.reduce((a, c) => ({ ...a, ...c }), {}),
37+
position: 'relative'
4738
}),
48-
'data-itemindex': index.toString(),
49-
'data-originalIndex': index.toString(),
50-
style: getGhostStyle(mouseOffset, item)
39+
children
5140
};
41+
}
5242

53-
const items: VNode[] = parent.children as VNode[];
43+
function addData(node: VNode, index: number): VNode {
44+
return addDataEntry(node, 'dataset', {
45+
originalIndex: index
46+
});
47+
}
5448

55-
const children: VNode[] = [
56-
...items.slice(0, index),
57-
addAttributes(items[index], { style: 'opacity: 0;' }),
58-
...items.slice(index + 1),
59-
addGhostClass(
60-
addAttributes({ ...items[index], elm: undefined }, ghostAttrs),
61-
options.ghostClass
62-
)
63-
].map((c, i) => addAttributes(c, { 'data-index': i }));
49+
function hideSelected(index: number): (node: VNode, i: number) => VNode {
50+
return function(node, i) {
51+
return i !== index
52+
? node
53+
: addDataEntry(node, 'style', {
54+
opacity: 0
55+
});
56+
};
57+
}
6458

65-
return replaceNode(node, options.parentSelector, { ...parent, children });
66-
};
59+
function createGhost(
60+
clicked: number,
61+
ev: any,
62+
item: Element,
63+
node: VNode
64+
): VNode {
65+
const rect = item.getBoundingClientRect();
66+
const parentRect = item.parentElement.getBoundingClientRect();
67+
const offsetX = ev.clientX - rect.left + parentRect.left;
68+
const offsetY = ev.clientY - rect.top + parentRect.top;
69+
70+
return addDataEntry(
71+
addDataEntry(node, 'dataset', {
72+
offsetX,
73+
offsetY,
74+
item
75+
}),
76+
'style',
77+
{
78+
position: 'absolute',
79+
left: ev.clientX - offsetX + 'px',
80+
top: ev.clientY - offsetY + 'px',
81+
width: rect.width + 'px',
82+
height: rect.height + 'px',
83+
'pointer-events': 'none'
84+
}
85+
);
86+
}

0 commit comments

Comments
 (0)