Started using RxJs. Can't find a way around this problem. I have a draggable control:
startDrag = rx.Observable.fromEvent(myElem,'mousedown')
now, because the control is too small mousemove
and mouseup
events should be at document level (otherwise it won't stop dragging unless cursor exactly on the element)
endDrag = rx.Observable.fromEvent document,'mouseup'
position = startDrag.flatMap ->
rx.Observable.fromEvent document,'mousemove'
.map (x)-> x.clientX
.takeUntil endDrag
now how do I "catch" the right moment when is not being dragged anymore (mouseup
).
you see the problem with subscribing to endDrag
? It will fire every time clicked anywhere, and not just myElem
How do I check all 3 properties at once? It should take only those document.mouseups that happened exactly after startDrag
and position
Upd: I mean the problem is not with moving the element. That part is easy - subscribe to position
, change element's css.
My problem is - I need to detect the moment of mouseup
and know the exact element that's been dragged (there are multiple elements on the page). How to do that I have no idea.
I have adapted the drag and drop example provided at the RxJS repo to behave as you need.
mouseUp
listens at document
.
The targeted element is added to the return from select
.
Drag movements are handled inside of map
and map
returns the element that was targeted in the mouseDown
event.
Call last
after takeUntil(mouseUp)
so subscribe
will only be reached when the drag process ends (once per drag).
function main() {
var dragTarget = document.getElementById('dragTarget');
// Get the three major events
var mouseup = Rx.Observable.fromEvent(document, 'mouseup');
var mousemove = Rx.Observable.fromEvent(document, 'mousemove');
var mousedown = Rx.Observable.fromEvent(dragTarget, 'mousedown');
var mousedrag = mousedown.selectMany(function(md) {
// calculate offsets when mouse down
var startX = md.offsetX;
var startY = md.offsetY;
// Calculate delta with mousemove until mouseup
return mousemove.select(function(mm) {
if (mm.preventDefault) mm.preventDefault();
else event.returnValue = false;
return {
// Include the targeted element
elem: mm.target,
pos: {
left: mm.clientX - startX,
top: mm.clientY - startY
}
};
})
.map(function(data) {
// Update position
dragTarget.style.top = data.pos.top + 'px';
dragTarget.style.left = data.pos.left + 'px';
// Just return the element
return data.elem;
})
.takeUntil(mouseup)
.last();
});
// Here we receive the element when the drag is finished
subscription = mousedrag.subscribe(function(elem) {
alert('Drag ended on #' + elem.id);
});
}
main();
#dragTarget {
position: absolute;
width: 20px;
height: 20px;
background: #0f0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.all.min.js"></script>
<div id="dragTarget"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With