Skip to content

Commit

Permalink
feat compatibility with d3 v5 and v6 (#158)
Browse files Browse the repository at this point in the history
Note that most changes relate to the index no longer being passed to the keypress listener. We now embed the index into the data.
  • Loading branch information
johnwalley authored Sep 15, 2020
1 parent aa35781 commit 4262b09
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 71 deletions.
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ If you need to include a slider within an svg element this is for you. For examp

If you don't need to work inside an svg element then I would consider using one of the many excellent html-based components which may be better suited to your needs. Of course you might just love using d3!

## Looking for d3 v6 support?

There is a pre-release version of `d3-simple-slider` available [here](https://www.npmjs.com/package/d3-simple-slider/v/2.0.0-rc.2) which supports the latest version of d3.

## Installing

If you use NPM, `npm install d3-simple-slider`. Otherwise, download the [latest release](https://github.com/johnwalley/d3-simple-slider/releases/latest). AMD, CommonJS, and vanilla environments are supported. In vanilla, a `d3` global is exported:
Expand Down
2 changes: 1 addition & 1 deletion example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/>
<title>d3-simple-slider</title>

<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="../dist/d3-simple-slider.js"></script>

<link
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "d3-simple-slider",
"version": "1.9.0",
"version": "1.10.0",
"description": "Renders an SVG slider",
"keywords": [
"d3",
Expand Down Expand Up @@ -62,10 +62,10 @@
"d3-array": "1 - 2",
"d3-axis": "1 - 2",
"d3-dispatch": "1 - 2",
"d3-drag": "1",
"d3-drag": "1 - 2",
"d3-ease": "1 - 2",
"d3-scale": "2 - 3",
"d3-selection": "1",
"d3-transition": "1"
"d3-selection": "1 - 2",
"d3-transition": "1 - 2"
}
}
13 changes: 13 additions & 0 deletions src/d3-compat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { event } from 'd3-selection';

export function adaptListener(listener) {
return function (a, b) {
if (a && a.target) {
// d3@v6
listener.call(this, a, b);
} else {
// d3@v5
listener.call(this, event, a);
}
};
}
143 changes: 82 additions & 61 deletions src/slider.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import 'd3-transition';

import { axisBottom, axisLeft, axisRight, axisTop } from 'd3-axis';
import { event, select } from 'd3-selection';
import { max, min, scan } from 'd3-array';
import { scaleLinear, scaleTime } from 'd3-scale';

import { adaptListener } from './d3-compat';
import { dispatch } from 'd3-dispatch';
import { drag } from 'd3-drag';
import { easeQuadOut } from 'd3-ease';
import { select } from 'd3-selection';

var UPDATE_DURATION = 200;
var SLIDER_END_PADDING = 8;
Expand Down Expand Up @@ -145,7 +146,10 @@ function slider(orientation, scale) {
: 'ns-resize'
)
.call(
drag().on('start', dragstarted).on('drag', dragged).on('end', dragended)
drag()
.on('start', adaptListener(dragstarted))
.on('drag', adaptListener(dragged))
.on('end', adaptListener(dragended))
);

sliderEnter
Expand Down Expand Up @@ -188,14 +192,18 @@ function slider(orientation, scale) {
.attr('stroke-linecap', 'round')
.merge(sliderSelection.select('.track-overlay'));

handleSelection = sliderEnter.selectAll('.parameter-value').data(value);
handleSelection = sliderEnter.selectAll('.parameter-value').data(
value.map(function (d, i) {
return { value: d, index: i };
})
);

var handleEnter = handleSelection
.enter()
.append('g')
.attr('class', 'parameter-value')
.attr('transform', function (d) {
return transformAlong(scale(d));
return transformAlong(scale(d.value));
})
.attr('font-family', 'sans-serif')
.attr(
Expand All @@ -215,7 +223,9 @@ function slider(orientation, scale) {
.attr('aria-label', 'handle')
.attr('aria-valuemax', domain[1])
.attr('aria-valuemin', domain[0])
.attr('aria-valuenow', value)
.attr('aria-valuenow', function (d) {
return d.value;
})
.attr(
'aria-orientation',
orientation === left || orientation === right
Expand All @@ -226,53 +236,56 @@ function slider(orientation, scale) {
.attr('tabindex', 0)
.attr('fill', 'white')
.attr('stroke', '#777')
.on('keydown', function (d, i) {
var change = step || (domain[1] - domain[0]) / KEYBOARD_NUMBER_STEPS;

// TODO: Don't need to loop over value because we know which element needs to change
function newValue(adjustedValue) {
return value.map(function (d, j) {
if (value.length === 2) {
return j === i
? i === 0
? Math.min(adjustedValue, alignedValue(value[1]))
: Math.max(adjustedValue, alignedValue(value[0]))
: d;
} else {
return j === i ? adjustedValue : d;
}
});
}
.on(
'keydown',
adaptListener(function (event, datum) {
var change = step || (domain[1] - domain[0]) / KEYBOARD_NUMBER_STEPS;

// TODO: Don't need to loop over value because we know which element needs to change
function newValue(adjustedValue) {
return value.map(function (d, j) {
if (value.length === 2) {
return j === datum.index
? datum.index === 0
? Math.min(adjustedValue, alignedValue(value[1]))
: Math.max(adjustedValue, alignedValue(value[0]))
: d;
} else {
return j === datum.index ? adjustedValue : d;
}
});
}

switch (event.key) {
case 'ArrowLeft':
case 'ArrowDown':
slider.value(newValue(+value[i] - change));
event.preventDefault();
break;
case 'PageDown':
slider.value(newValue(+value[i] - 2 * change));
event.preventDefault();
break;
case 'ArrowRight':
case 'ArrowUp':
slider.value(newValue(+value[i] + change));
event.preventDefault();
break;
case 'PageUp':
slider.value(newValue(+value[i] + 2 * change));
event.preventDefault();
break;
case 'Home':
slider.value(newValue(domain[0]));
event.preventDefault();
break;
case 'End':
slider.value(newValue(domain[1]));
event.preventDefault();
break;
}
});
switch (event.key) {
case 'ArrowLeft':
case 'ArrowDown':
slider.value(newValue(+value[datum.index] - change));
event.preventDefault();
break;
case 'PageDown':
slider.value(newValue(+value[datum.index] - 2 * change));
event.preventDefault();
break;
case 'ArrowRight':
case 'ArrowUp':
slider.value(newValue(+value[datum.index] + change));
event.preventDefault();
break;
case 'PageUp':
slider.value(newValue(+value[datum.index] + 2 * change));
event.preventDefault();
break;
case 'Home':
slider.value(newValue(domain[0]));
event.preventDefault();
break;
case 'End':
slider.value(newValue(domain[1]));
event.preventDefault();
break;
}
})
);

if (displayValue) {
handleEnter
Expand Down Expand Up @@ -346,7 +359,7 @@ function slider(orientation, scale) {
context.selectAll('.axis line').attr('stroke', '#aaa');

context.selectAll('.parameter-value').attr('transform', function (d) {
return transformAlong(scale(d));
return transformAlong(scale(d.value));
});

fadeTickText();
Expand All @@ -366,7 +379,7 @@ function slider(orientation, scale) {
});
}

function dragstarted() {
function dragstarted(event) {
select(this).classed('active', true);

var pos = identityClamped(
Expand Down Expand Up @@ -399,7 +412,7 @@ function slider(orientation, scale) {
updateValue(newValue, true);
}

function dragged() {
function dragged(event) {
var pos = identityClamped(
orientation === bottom || orientation === top ? event.x : event.y
);
Expand All @@ -414,7 +427,7 @@ function slider(orientation, scale) {
updateValue(newValue, true);
}

function dragended() {
function dragended(event) {
select(this).classed('active', false);

var pos = identityClamped(
Expand Down Expand Up @@ -543,16 +556,20 @@ function slider(orientation, scale) {
if (animate) {
selection
.selectAll('.parameter-value')
.data(newValue)
.data(
newValue.map(function (d, i) {
return { value: d, index: i };
})
)
.transition()
.ease(easeQuadOut)
.duration(UPDATE_DURATION)
.attr('transform', function (d) {
return transformAlong(scale(d));
return transformAlong(scale(d.value));
})
.select('.handle')
.attr('aria-valuenow', function (d) {
return d;
return d.value;
});

if (fill) {
Expand All @@ -574,13 +591,17 @@ function slider(orientation, scale) {
} else {
selection
.selectAll('.parameter-value')
.data(newValue)
.data(
newValue.map(function (d, i) {
return { value: d, index: i };
})
)
.attr('transform', function (d) {
return transformAlong(scale(d));
return transformAlong(scale(d.value));
})
.select('.handle')
.attr('aria-valuenow', function (d) {
return d;
return d.value;
});

if (fill) {
Expand Down

0 comments on commit 4262b09

Please sign in to comment.