Skip to content

Instantly share code, notes, and snippets.

@whiteinge
Created July 25, 2018 22:46
Show Gist options
  • Select an option

  • Save whiteinge/84167d982556be3ac714c42f11d008ca to your computer and use it in GitHub Desktop.

Select an option

Save whiteinge/84167d982556be3ac714c42f11d008ca to your computer and use it in GitHub Desktop.
Minimal RxJS + Flux drag-and-drop to reorder POC
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>rx-drag-to-reorder</title>
<style>
#container {
width: 30em;
}
.list {
list-style-type: none;
padding-left: 0;
}
.list li {
display: block;
height: 2em;
background-color: lightgreen;
margin: 0.5em 0;
transition: margin-bottom 0.2s ease-in-out;
}
.list li.dragged {
background-color: orangered;
}
.list li.hovered {
margin-bottom: 2.5em;
}
.list li:first-child.hovered:before {
content: "";
display: block;
height: 2em;
background-color: lightblue;
border: 2px dashed red;
}
.list li.hovered:after {
content: "";
display: block;
height: 2em;
background-color: lightblue;
border: 2px dashed red;
margin-top: 1em;
}
</style>
</head>
<body>
<div id="container"></div>
<!-- <script src="rx.all.min.js"></script> -->
<!-- <script src="rx.dom.min.js"></script> -->
<!-- <script src="lodash.min.js"></script> -->
<script src="https://unpkg.com/rx@4.1.0/dist/rx.all.min.js"></script>
<script src="https://unpkg.com/rx-dom@7.0.3/dist/rx.dom.min.js"></script>
<script src="https://unpkg.com/lodash@4.17.4/lodash.min.js"></script>
<script src="index.js"></script>
</body>
</html>
const listItems = ['foo', 'bar', 'baz', 'qux', 'quux', 'quuz', 'corge',
'grault', 'garply', 'waldo', 'fred', 'plugh', 'xyzzy', 'thud']
const render = el => content => { el.innerHTML = content };
// ----------------------------------------------------------------------------
const Dispatcher = new Rx.Subject();
Dispatcher.onCompleted = () => {};
const send = (tag, arg) => ev => Dispatcher.onNext({
tag,
data: typeof arg === 'function' ? arg(ev) : arg,
})
// ----------------------------------------------------------------------------
const list = Dispatcher.filter(x => x.tag === 'LIST')
.startWith(listItems)
const dragIdx = Dispatcher.filter(x => x.tag === 'ENTER')
.pluck('data')
.first()
.merge(Rx.Observable.never())
.startWith(null)
.takeUntil(Dispatcher.filter(x => x.tag === 'DRAGEND'))
.repeat()
const hoverIdx = Dispatcher.filter(x => x.tag === 'ENTER')
.pluck('data')
.startWith(null)
.takeUntil(Dispatcher.filter(x => x.tag === 'DRAGEND'))
.repeat()
.distinctUntilChanged()
const listOrdered = Dispatcher.filter(x => x.tag === 'DRAGEND')
.pluck('data')
.withLatestFrom([
list,
dragIdx.filter(x => x != null),
hoverIdx.filter(x => x != null),
])
.merge(list.take(1))
.scan((list, [, , dragIdx, dropIdx]) => {
const val = list[dragIdx]
list.splice(dragIdx, 1)
list.splice(dropIdx, 0, val)
return list
})
const app = Rx.Observable.combineLatest([
listOrdered,
hoverIdx,
dragIdx,
], (xs, hoverIdx, dragIdx) => ''.concat(
'<ul class="list">', xs.map((x, xIdx) => `<li
draggable="true"
class="${xIdx === hoverIdx ? 'hovered' : ''} ${xIdx === dragIdx ? 'dragged' : ''}"
ondragend="send('DRAGEND', ${xIdx})(event)"
ondragenter="send('ENTER', ${xIdx})()"
>
${x}</li>`).join('\n'),
'</ul>',
));
// ----------------------------------------------------------------------------
const sub1 = Dispatcher
.subscribe(x => console.log('N', x), x => console.log('E', x));
const sub2 = app
.subscribe(render(document.querySelector('#container')))
@whiteinge

whiteinge commented Jul 25, 2018

Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment