Currently, I am working with an AngularJS component that needs to respond to both single clicks and drags for resizing purposes. To tackle this problem, I have integrated RxJS (ReactiveX) into my application in search of a suitable solution. The Angular aspect of the request is relatively minor...
To simplify the issue at hand (and improve my skills), I created a slider directive inspired by the rx.angular.js drag-and-drop example available at: http://plnkr.co/edit/UqdyB2 You can find the relevant code in the Slide.js file (the remaining code pertains to other experiments). The core logic of this implementation is as follows:
function(scope, element, attributes)
{
var thumb = element.children(0);
var sliderPosition = element[0].getBoundingClientRect().left;
var sliderWidth = element[0].getBoundingClientRect().width;
var thumbPosition = thumb[0].getBoundingClientRect().left;
var thumbWidth = thumb[0].getBoundingClientRect().width;
// Based on the drag-and-drop example from rx-angular.js
// Capture the three main events
var mousedown = rx.Observable.fromEvent(thumb, 'mousedown');
var mousemove = rx.Observable.fromEvent(element, 'mousemove');
var mouseup = rx.Observable.fromEvent($document, 'mouseup');
// My aim is to differentiate between a single click and a click-and-drag scenario.
// I believe that if we receive a mouseup shortly after mousedown, it signifies a single click;
// mousedown.delay(200).takeUntil(mouseup)
// .subscribe(function() { console.log('Simple click'); }, undefined, function() { console.log('Simple click completed'); });
var locatedMouseDown = mousedown.map(function (event)
{
event.preventDefault();
// console.log('Click', event.clientX - sliderPosition);
// calculate offsets when mouse down
var initialThumbPosition = thumb[0].getBoundingClientRect().left - sliderPosition;
return { from: initialThumbPosition, offset: event.clientX - sliderPosition };
});
// Combine mouse down with mouse move until mouse up
var mousedrag = locatedMouseDown.flatMap(function (clickInfo)
{
return mousemove.map(function (event)
{
var move = event.clientX - sliderPosition - clickInfo.offset;
// console.log('Move', clickInfo);
// calculate offsets from mouse down to mouse moves
return clickInfo.from + move;
}).takeUntil(mouseup);
});
mousedrag
.map(function (position)
{
if (position < 0)
return 0;
if (position > sliderWidth - thumbWidth)
return sliderWidth - thumbWidth;
return position;
})
.subscribe(function (position)
{
// console.log('Drag', position);
// Update position
thumb.css({ left: position + 'px' });
});
}
This functionality primarily limits dragging horizontally within a specified range.
Now, I want to detect a mousedown event and consider it a click if a corresponding mouseup occurs within a brief timeframe (e.g., 200 ms). In such cases, I intend to perform specific actions, such as resetting the position to zero.
I attempted using delay().takeUntil(mouseup)
, referencing another answer on SO, but without success. It is possible that employing a switch() might be necessary to avoid following the drag process. Any insights or suggestions would be greatly appreciated. Thank you in advance.