Skip to content

Instantly share code, notes, and snippets.

@ourmaninamsterdam
Last active October 17, 2019 20:31
Show Gist options
  • Save ourmaninamsterdam/05aba4ff624916b2c0e072a7829bbcb5 to your computer and use it in GitHub Desktop.
Save ourmaninamsterdam/05aba4ff624916b2c0e072a7829bbcb5 to your computer and use it in GitHub Desktop.
RxRangeSlider - first play with RxJS
const rxRangeSlider = ({ rangeNode, handlesContainerNode, handleStartNode, handleEndNode, start: [stepStart, stepEnd], stepSize, bounds: [rangeStart, rangeEnd] }) => {
const KEY_LEFT = 37;
const KEY_RIGHT = 39;
const VALID_KEYS = [KEY_LEFT, KEY_RIGHT];
const INCREMENT_LOWER = 'INCREMENT_LOWER';
const DECREMENT_LOWER = 'DECREMENT_LOWER';
const INCREMENT_UPPER = 'INCREMENT_UPPER';
const DECREMENT_UPPER = 'DECREMENT_UPPER';
const restrictToRange = (min, max, num) => Math.min(Math.max(min, num), max);
const isLeftKey = e => e.keyCode === KEY_LEFT;
const isRightKey = e => e.keyCode === KEY_RIGHT;
const handleStartNode$ = Rx.Observable.fromEvent(handleStartNode, "keydown");
const handleEndNode$ = Rx.Observable.fromEvent(handleEndNode, "keydown");
const incrementLowerRange$ = Rx.Observable.merge(handleStartNode$).filter(isRightKey).map(() => state =>
stateReducer(state, { type: INCREMENT_LOWER })
);
const decrementLowerRange$ = Rx.Observable.merge(handleStartNode$).filter(isLeftKey).map(() => state =>
stateReducer(state, { type: DECREMENT_LOWER })
);
const incrementUpperRange$ = Rx.Observable.merge(handleEndNode$).filter(isRightKey).map(() => state =>
stateReducer(state, { type: INCREMENT_UPPER })
);
const decrementUpperRange$ = Rx.Observable.merge(handleEndNode$).filter(isLeftKey).map(() => state =>
stateReducer(state, { type: DECREMENT_UPPER })
);
const drawRange = (nodes, currentStart, currentEnd, rangeStart, rangeEnd) => {
const container = nodes[0].parentNode;
const width = Math.abs((currentStart - currentEnd) / rangeEnd * 100);
const left = (currentStart / rangeEnd) * 100;
Array.prototype.slice.call(nodes).forEach(node => {
node.style.left = [left, '%'].join('');
node.style.width = [width, '%'].join('');
});
}
const stateReducer = (state, action) => {
if(action.type === INCREMENT_LOWER) {
return {
...state,
start: restrictToRange(rangeStart, state.end, state.start + stepSize)
}
}
if(action.type === DECREMENT_LOWER) {
return {
...state,
start: restrictToRange(rangeStart, rangeEnd, state.start - stepSize)
}
}
if(action.type === INCREMENT_UPPER) {
return {
...state,
end: restrictToRange(rangeStart, rangeEnd, state.end + stepSize)
}
}
if(action.type === DECREMENT_UPPER) {
console.log(DECREMENT_UPPER)
return {
...state,
end: restrictToRange(state.start, rangeEnd, state.end - stepSize)
}
}
return state;
};
const state$ = Rx.Observable.merge(incrementLowerRange$, decrementLowerRange$, incrementUpperRange$, decrementUpperRange$).scan(
(state, change) => change(state),
{
start: stepStart,
end: stepEnd
}
);
state$.do(state => drawRange([rangeNode, handlesContainerNode], state.start, state.end, rangeStart, rangeEnd)).subscribe();
drawRange([rangeNode, handlesContainerNode], stepStart, stepEnd, rangeStart, rangeEnd);
return state$;
};
const sliderNode = document.querySelector('#slider');
const config = {
bounds: [0, 100],
start: [20, 60],
stepSize: 10,
rangeNode: sliderNode.querySelector(".slider__range"),
handlesContainerNode: sliderNode.querySelector(".slider__handles"),
handleStartNode: sliderNode.querySelector(".slider__handle--left"),
handleEndNode: sliderNode.querySelector(".slider__handle--right")
};
const myRxRangeSlider = rxRangeSlider(config);
myRxRangeSlider.subscribe(state => {
console.log(state);
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment