Reputation: 1952
This questions relates to RXJS. I'm trying to adapt the drag and drop example in github to work for a class of divs not just a single element ID. https://github.com/Reactive-Extensions/RxJS/blob/master/examples/dragndrop/dragndrop.html
simple changes to give the div a class nor an ID dont work and i lose ability to drag the element
3 simple changes:
HTML line 7 i.e. <div class="dragTarget">Drag Me!</div>
CSS line 1 i.e. .dragTarget { style attributes unchanged }
JS line 4 i.e var dragTarget = document.getElementsByClassName('dragTarget');
Im not skilled enough to know if this is a bug in RXJS or that the example is not generalised enough. The documentation on RXJS events suggests these changes should be sufficient. Any help appreciated. Thanks.
Upvotes: 5
Views: 1959
Reputation: 108501
fromEvent
will use the on
and off
methods of any Object you pass it, otherwise it will use addEventListener
and removeEventListener
. So if you're using jQuery, you can simply select all of them and use that (Observable.fromEvent($('.targetNode'), 'mouseup')
for example).
Otherwise, you can use any object with an on
and off
method to subscribe or unsubscribe from the events, like I'm doing below.
Other than that, you can use the target
property on the MouseEvent
objects you get in each stream to get the actual DOM node you care to move...
Something like the example below should do the trick.
(function (global) {
/**
selectNodes is a method to select a NodeList, but convert it to
a type that has `on` and `off` methods RxJS 2 expects to see for `fromEvent`
*/
function selectNodes(selector) {
var nodes = document.querySelectorAll(selector);
return {
// the selected nodes
nodes: [].slice.call(this.nodes),
// subscribe to an event on every selected node
on: function(eventName, handler) {
this.nodes.forEach(function(node) { node.addEventListener(eventName, handler); });
},
// unsubscribe from the event on every selected node
off: function(eventName, handler) {
this.nodes.forEach(function(node) { node.removeEventListener(eventName, handler); });
}
};
}
function main () {
// IMPORTANT CHANGE: Use the selectNodes method we made
var dragTargets = selectNodes('.dragTarget');
// Get the three major events
var mouseup = Rx.Observable.fromEvent(dragTargets, 'mouseup');
var mousemove = Rx.Observable.fromEvent(document, 'mousemove');
var mousedown = Rx.Observable.fromEvent(dragTargets, 'mousedown');
var mousedrag = mousedown.flatMap(function (md) {
// calculate offsets when mouse down
var startX = md.offsetX, startY = md.offsetY;
// Calculate delta with mousemove until mouseup
return mousemove.map(function (mm) {
mm.preventDefault();
return {
left: mm.clientX - startX,
top: mm.clientY - startY,
target: mm.target, // IMPORTANT CHANGE: the element you care about
};
}).takeUntil(mouseup);
});
// Update position
var subscription = mousedrag.subscribe(function (d) {
d.target.style.top = d.top + 'px';
d.target.style.left = d.left + 'px';
});
}
main();
}(window));
Upvotes: 5