Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue #854 - Range slider, min value over max value. #864

Merged
merged 2 commits into from
Nov 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/js/bootstrap-slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,9 @@ const windowIsDefined = (typeof window === "object");
this._setDataVal(val);
this._trigger('slideStop', val);

// No longer need 'dragged' after mouse up
this._state.dragged = null;

return false;
},
_calculateValue: function(snapToClosestTick) {
Expand Down
167 changes: 136 additions & 31 deletions test/specs/DraggingHandlesSpec.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,60 @@
describe("Dragging handles tests", function() {
var testSlider;
var mouseEventArguments;
var tickOffsets;

beforeEach(function() {
// Create slider
testSlider = new Slider(document.getElementById("testSlider1"), {
ticks: [0, 1, 2, 3, 4, 5, 6],
value: [4, 5],
step: 1,
range: true,
});
// Set up default set of mouse event arguments
mouseEventArguments = [
'mousemove', // type
true, // canBubble
true, // cancelable
document, // view,
0, // detail
0, // screenX
0, // screenY
undefined, // clientX
testSlider.sliderElem.offsetTop, // clientY,
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey,
0, // button
null // relatedTarget
];
// Calculate and store the 'clientX' for each tick in the slider
tickOffsets = testSlider.ticks.map(function (tick) {
return tick.offsetLeft + testSlider.sliderElem.offsetLeft;
});
});

afterEach(function() {
if(testSlider) {
if(testSlider instanceof Slider) { testSlider.destroy(); }
testSlider = null;
}
});

describe("Dragging handles over each other", function() {
it("should swap reliably given imprecision", function() {
testSlider = new Slider(document.getElementById("testSlider1"), {
ticks: [0, 1, 2, 3, 4, 5, 6],
value: [4, 5],
step: 1,
range: true,
});
var mouseEventArguments = [
'mousemove', // type
true, // canBubble
true, // cancelable
document, // view,
0, // detail
0, // screenX
0, // screenY
undefined, // clientX
testSlider.sliderElem.offsetTop, // clientY,
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey,
0, // button
null // relatedTarget
];
// Create mouse event with position to the left of problem tick
var mouseLeft = document.createEvent('MouseEvents');
mouseEventArguments[7] = testSlider.ticks[4].offsetLeft + testSlider.sliderElem.offsetLeft; // clientX
mouseEventArguments[7] = tickOffsets[4]; // clientX
mouseLeft.initMouseEvent.apply(mouseLeft, mouseEventArguments);
// Create mouse event with position on problem tick
var mouseOverlap = document.createEvent('MouseEvents');
mouseEventArguments[7] = testSlider.ticks[5].offsetLeft + testSlider.sliderElem.offsetLeft; // clientX
mouseEventArguments[7] = tickOffsets[5]; // clientX
mouseOverlap.initMouseEvent.apply(mouseOverlap, mouseEventArguments);
// Create mouse event with position to the right of problem tick
var mouseRight = document.createEvent('MouseEvents');
mouseEventArguments[7] = testSlider.ticks[6].offsetLeft + testSlider.sliderElem.offsetLeft; // clientX
mouseEventArguments[7] = tickOffsets[6]; // clientX
mouseRight.initMouseEvent.apply(mouseRight, mouseEventArguments);
// Simulate drag without swapping
testSlider.mousedown(mouseLeft);
Expand Down Expand Up @@ -64,14 +83,100 @@ describe("Dragging handles tests", function() {
expect(testSlider.getValue()).toEqual([4, 5]);
// End with mouse up
testSlider.mouseup();
expect(testSlider._state.dragged).toBe(0);
expect(testSlider._state.dragged).toBeNull();
expect(testSlider.getValue()).toEqual([4, 5]);
});
});
afterEach(function() {
if(testSlider) {
if(testSlider instanceof Slider) { testSlider.destroy(); }
testSlider = null;

describe("Drag handles over each other and use keyboard to move handles over each other", function() {
var keyboardEvent;

function createMouseEvent(type, tickIdx) {
var mouseEvent = document.createEvent('MouseEvent');
mouseEventArguments[0] = type;
mouseEventArguments[7] = tickOffsets[tickIdx];
mouseEvent.initMouseEvent.apply(mouseEvent, mouseEventArguments);
return mouseEvent;
}

beforeEach(function() {
// Create keyboard event
keyboardEvent = document.createEvent('Event');
keyboardEvent.initEvent('keydown', true, true);
});

afterEach(function() {
keyboardEvent = null;
});

it("should drag and keydown handles properly to the right then back to the left", function() {
// Simulate drag without swapping
testSlider.mousedown(createMouseEvent('mousedown', 4));
expect(testSlider._state.dragged).toBe(0);
expect(testSlider.getValue()).toEqual([4, 5]);

// Simulate handle overlap
testSlider.mousemove(createMouseEvent('mousemove', 5));
expect(testSlider._state.dragged).toBe(0);
expect(testSlider.getValue()).toEqual([5, 5]);

// Simulate left over right drag
testSlider.mousemove(createMouseEvent('mousemove', 6));
expect(testSlider._state.dragged).toBe(1);
expect(testSlider.getValue()).toEqual([5, 6]);

// End with mouse up
testSlider.mouseup();
expect(testSlider._state.dragged).toBeNull();
expect(testSlider.getValue()).toEqual([5, 6]);

// Now move the handles past each other with the Left arrow key
keyboardEvent.keyCode = keyboardEvent.which = 37;

// Move handle2 to the left with keyboard
testSlider.handle2Keydown(keyboardEvent);
expect(testSlider._state.keyCtrl).toBeUndefined();
expect(testSlider.getValue()).toEqual([5, 5]);

// Move handle2 to the left again
testSlider.handle2Keydown(keyboardEvent);
expect(testSlider._state.keyCtrl).toBeUndefined();
expect(testSlider.getValue()).toEqual([4, 5]);
});

it("should drag and keydown handles properly to the left then back to the right", function() {
// Simulate drag without swapping
testSlider.mousedown(createMouseEvent('mousedown', 5));
expect(testSlider._state.dragged).toBe(1);
expect(testSlider.getValue()).toEqual([4, 5]);

// Simulate handle overlap
testSlider.mousemove(createMouseEvent('mousemove', 4));
expect(testSlider._state.dragged).toBe(1);
expect(testSlider.getValue()).toEqual([4, 4]);

// Simulate left over right drag
testSlider.mousemove(createMouseEvent('mousemove', 3));
expect(testSlider._state.dragged).toBe(0);
expect(testSlider.getValue()).toEqual([3, 4]);

// End with mouse up
testSlider.mouseup();
expect(testSlider._state.dragged).toBeNull();
expect(testSlider.getValue()).toEqual([3, 4]);

// Now move the handles past each other with the Right arrow key
keyboardEvent.keyCode = keyboardEvent.which = 39;

// Move handle1 to the right with keyboard
testSlider.handle1Keydown(keyboardEvent);
expect(testSlider._state.keyCtrl).toBeUndefined();
expect(testSlider.getValue()).toEqual([4, 4]);

// Move handle1 to the right again
testSlider.handle1Keydown(keyboardEvent);
expect(testSlider._state.keyCtrl).toBeUndefined();
expect(testSlider.getValue()).toEqual([4, 5]);
});
});
});