Skip to content

Instantly share code, notes, and snippets.

@PhiLhoSoft

PhiLhoSoft/ReadMe.md

Created Jun 23, 2015
Embed
What would you like to do?
Improving Most.js' Drag'n'Drop example
<div class="playground">
<div class="box draggable"><span class="rest">Drag</span><span class="drag">Drop</span> me, baby!</div>
</div>
<style>
body {
font-size: 1em;
font-family: 'Helvetica Nueue', Helvetica, sans-serif;
}
.playground { width: 100%; height: 100%; }
.box {
-webkit-transition: box-shadow 100ms ease;
color: white;
background: #28f;
text-align: center;
padding: 1em;
box-shadow: 1px 1px 5px #444;
}
.draggable {
transform: translate3d(0,0,0);
cursor: move;
width: 150px;
height: 150px;
position: absolute;
}
.dragging {
box-shadow: 10px 10px 40px #444;
}
.draggable .drag {
font-style: italic;
font-weight: bold;
display: none;
}
.dragging .drag {
display: inline;
}
.dragging .rest {
display: none;
}
</style>
var most = require('most');
var DROP = 0, GRAB = 1, DRAG = 2;
(function()
{
// The thing we want to make draggable
var playground = document.querySelector('.playground');
var draggable = document.querySelector('.draggable');
var dragOffset = {};
// A higher-order stream (stream whose events are themselves streams)
// A mousedown DOM event generates a stream event which is
// a stream of 1 GRAB followed by DRAGS (ie mousemoves).
var drag = most.fromEvent('mousedown', draggable)
.map(function(e)
{
e.preventDefault();
console.log('e: ' + e.clientX + ', ' + e.clientY);
console.log('draggable: ' + draggable.offsetLeft + ', ' + draggable.offsetTop + " (" + draggable.offsetWidth + "x" + draggable.offsetHeight + ")");
dragOffset.dx = e.clientX - draggable.offsetLeft;
dragOffset.dy = e.clientY - draggable.offsetTop;
console.log("dragOffset: " + JSON.stringify(dragOffset));
return most.fromEvent('mousemove', playground)
.map(function(e)
{
return eventToDragInfo(DRAG, e);
})
.startWith(eventToDragInfo(GRAB, e));
});
// A mouseup DOM event generates a stream event which is a
// stream containing a DROP
var drop = most.fromEvent('mouseup', playground)
.map(function(e)
{
return most.of(eventToDragInfo(DROP, e));
});
// Merge the drag and drop streams
// Then use switch() to ensure that the resulting stream behaves
// like the drag stream until an event occurs on the drop stream. Then
// it will behave like the drop stream until the drag stream starts
// producing events again.
// This effectively *toggles behavior* between dragging behavior and
// dropped behavior.
most.merge(drag, drop)
.switch()
.reduce(handleDrag, dragOffset);
})();
function eventToDragInfo(action, e)
{
return { action: action, target: e.target, x: e.clientX, y: e.clientY };
}
function handleDrag(offset, dd)
{
var el = dd.target;
// console.log(dd);
if (dd.action === GRAB)
{
el.classList.add('dragging');
return offset;
}
if (dd.action === DROP)
{
el.classList.remove('dragging');
return offset;
}
var els = dd.target.style;
els.left = (dd.x - offset.dx) + 'px';
els.top = (dd.y - offset.dy) + 'px';
return offset;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment