Visualize sport seasons with interactive standings
npm install replay-tableReplay Table
=========
A library fo visualizing sport season results with interactive standings:
!sparklines-demo
div with replayTable class on your page and supply a link to the input file using data-source attribute:
data-source="/path/to/file.csv">
3. Include D3.js and Replay Table scripts (70+16 KB gzipped) and the stylesheet. Apply some magic to the body:
`
...
...
`
4. Enjoy!
The library is highly customizable via data- attributes. Check out customization for the details.
Also feel free to embed ready-to-use Replay Tables from our gallery.
Library
npm install -S replay-table
The only dependency is D3.js. D3 is not included with the library so don't forget to plug it up.
The library consists of 5 modules: configure → extract → transform → calculate → visualize.
Take a look at how we use them in the magic function:
`
return Array.from(document.getElementsByClassName('replayTable'))
.map(table => {
const config = replayTable.configure(table.id, table.dataset); //build a config from data- attributes
return Promise.resolve(replayTable.extract(config.extract)) //fetch the input
.then(raw => {
const transformed = replayTable.transform(raw, config.transform); //transform into predefined format
const calculated = replayTable.calculate(transformed, config.calculate); //calculate wins, goals, etc.
return replayTable.visualize(calculated, config.visualize); //render interactive standings
})
.catch(error => crash(error));
});
`
Sometimes you won't need all the modules: for example, feel free to omit configure if you already have a config.
A Replay Table is returned from the visualize module. It has methods like play() and to(roundIndex) so you can control its behaviour from code.
Customization
* Configure
* Presets
* Extract
* Transfrom
* List of Matches
* Points Table
* Calculate
* Visualize
* Classic
* Sparklines
Configure
Makes configs for other modules based on the div data- attributes. The output looks like this:
`
extract: {
extractor: csv
},
transform: {
transformer: 'pointsTable',
changeToOutcome: {
25: 'win'
},
insertStartRound: 'Start →'
},
calculate: {
orderBy: ['points', 'wins']
},
visualize: {
columns: ['position', 'item', 'points', 'points.change'],
labels: ['#', 'Driver', 'Points']
}
`
$3
To save you some time and cognitive effort we've constructed presets
that you can use via data-preset attribute:
matches,
f1,
winLoss,
chgk.
So this table:
`
data-source="/path/to/file.csv">
data-transformer="listOfMatches"
data-change-to-outcome="{ 1: 'win', 0: 'loss' }"
data-order-by="winningPercentage,wins"
data-visualizer="classic"
data-columns="position,item,rounds,wins,losses,winningPercentage,outcome,match"
data-labels="#,Team,G,W,L,Win %"
is identical to this:
`
data-source="/path/to/file.csv">
data-preset="winLoss"
Extract
Fetches the input file, returns a promise.
| Parameter | Attribute | Required | Accepts | Default | Examples |
|-----------|-----------|----------|---------------|---------------|----------|
| source | data-source | yes | string | null | /assets/data/football/2016-2017/english-premier-league.json |
| extractor | data-extractor | no | extractor | csv | csv, json |
If extractor is not defined we try to guess it from the file extension.
Transform
Transforms raw data into the predefined format:
`
[
{
name: 'round name',
results: {
[
{
change: 25,
extras: {
item: {
team: 'Mercedes'
}
},
item: 'Lewis Hamilton',
outcome: 'win'
},
{
...
},
...
]
}
},
{
...
},
...
]
`
| Parameter | Attribute | Accepts | Parses | Default | Examples |
|-----------|-----------|---------|--------|---------------|----------|
| transformer | data-transformer | transformer | | listOfMatches | listOfMatches, pointsTable |
| changeToOutcome | data-change-to-outcome | object | JSON object | { 3: 'win', 1: 'draw', 0: 'loss'} | { 1: 'win', 0: 'loss'} |
| filterItems | data-filter-items | array of strings | comma-separated string | [] | ['Golden State Warriors', 'San Antonio Spurs', ...] |
| insertStartRound | data-insert-start-round | string | | 0 | Start |
$3
The structure looks like this:
| Round name | First Item | First Item Score | Second Item | Second Item Score |
|------------|------------|------------------|-------------|-------------------|
| Round | Item | Score | Item | Score |
List should be sorted by round.
Here is an example:
| Match Week | Home | Points | Away | Points |
|------|------|--------|------|--------|
| 1 | Bournemouth | 0 | Aston Villa | 1 |
| 1 | Chelsea | 2 | Swansea | 2 |
| 1 | Everton | 2 | Watford | 2 |
| ... | ... | ... | ... | ... |
Also works with football-data.org fixtures.
| Parameter | Attribute | Accepts | Default | Examples |
|-----------|-----------|---------|---------------|----------|
| format | data-format | csv or football-data.org | csv | csv, football-data.org |
| locationFirst | data-location-first | home or away | home | home, away |
| collapseToRounds | data-collapse-to-rounds | boolean | false | true, false |
Use collapseToRounds when you've got dates instead of match weeks: it groups each team's 1st, 2nd, 3rd, ... games.
$3
The structure looks like this:
| Item name | [1st extra column name] | [2nd extra column name] | [...] | 1st round name | 2nd round name | ... | last round name |
|-----------|-------------------------|-------------------------|-----|----------------|----------------|-----|-----------------|
| item | [1st piece of extra info] | [2nd piece of extra info] | [...] | 1st round points | 2nd round points | ... | last round points |
The Formula One example (csv):
| Driver | Team | Australia | Bahrain | ... | Abu Dhabi |
|------|---|---|---|-----|----|
| Lewis Hamilton | Mercedes | 18 | 15 | ... | 25 |
| Nico Rosberg | Mercedes | 25 | 25 | ... | 18 |
| Daniel Ricciardo | Red Bull | 12 | 12 | ... | 10 |
| ... | ... | .... | ... | ... | ... |
Watch the live demo.
| Parameter | Attribute | Accepts | Default | Examples |
|-----------|-----------|---------|---------------|----------|
| extraColumnsNumber | data-extra-columns-number | int | 0 | 1, 2 |
Calculate
Calculates wins, goals, points, etc. and adds metadata. The output looks like this:
`
{
meta: {
lastRound: 38
},
results: {
[
{
meta: {
index: 2,
isLast: false,
items: 20,
name: "2"
},
results: {
[
{
change: 3,
draws: {
change: 0,
total: 0
},
extras: {},
item: 'Leicester',
losses: {
change: 0,
total: 0
},
match: {
location: "away",
opponent: "West Ham",
opponentScore: 1,
score: 2
},
outcome: "win",
points: {
change: 3,
total: 6
},
position: {
highest: 1,
lowest: 4,
strict: 1
},
wins: {
change: 1,
total: 2
}
...//goalsFor, goalsAgainst, goalsDifference, rounds, winningPercentage
},
....
]
}
},
...
]
}
}
`
See the whole list of calculations in the calculations.js.
| Parameter | Attribute | Accepts | Parses | Default | Examples |
|-----------|-----------|---------|--------|---------------|----------|
| orderBy | data-order-by | array of calculations | comma-separated string | ['points'] | ['winningPercentage', 'wins'] |
Visualize
Renders interactive standings out of calculated data.
Returns a class instance with useful methods:
* first(), last(), next(), previous() and to(roundIndex)
* play() and pause()
* preview(roundIndex) and endPreview()
* drillDown(item) and endDrillDown()
| Parameter | Attribute | Accepts | Parses | Default | Examples |
|-----------|-----------|---------|--------|---------------|----------|
| visualizer | data-visualizer | visualizer | | classic | classic, sparklines |
| controls | data-conrols | array of controls | comma-separated string | ['play', 'previous', 'next', 'slider'] | ['play', 'slider'] |
| startFromRound | data-start-from-round | int | | null | 0, 15 |
| roundsTotalNumber | data-rounds-total-number | int | | null | 38, 82 |
| positionWhenTied | data-position-when-tied | int | | strict, highest, range or average | strict, highest |
| animationSpeed | data-animation-speed | float | | 1.0 | 0.5, 2.0 |
$3
!classic-f1-demo
Formula One
A simple table with controls on top. Works for any sport and is highly customizable.
| Parameter | Attribute | Accepts | Parses | Default | Examples |
|-----------|-----------|---------|--------|---------------|----------|
| columns | data-columns | array of columns | comma-separated string | ['position', 'item', 'points'] | ['position', 'item', 'points', 'outcome', 'points.change] |
| labels | data-labels | array of strings | comma-separated string | ['#', 'Team', 'Points'] | ['Position', 'Driver', 'Points'] |
| colors | data-colors | object | JSON object | { 'win': '#ACE680', 'draw': '#B3B3B3', 'loss': '#E68080' } | { 'win': 'green', 'draw': 'gray', 'loss': 'red' } |
| durations | data-durations | object | JSON object | { move: 750, freeze: 750, outcomes: 200} | { move: 500, freeze: 400, outcomes: 250} |
$3
!sparklines-demo
English Premier League
A powerful interactive visualization for the sports with matches and points. Might be slow on old devices and in Firefox.
| Parameter | Attribute | Accepts | Parses | Default | Examples |
|-----------|-----------|---------|--------|---------------|----------|
| controls | data-conrols | array of controls | comma-separated string | ['play'] | ['play', 'previous', 'next'] |
| colors | data-colors | object | JSON object | { 'win': '#21c114', 'draw': '#828282', 'loss': '#e63131' } | { 'win': 'green', 'draw': 'gray', 'loss': 'red' } |
| sparkColors | data-spark-colors | object | JSON object | { 'win': '#D7E7C1', 'draw': '#F0F0F0', 'loss': '#EFCEBA' } | { 'win': 'green', 'draw': 'gray', 'loss': 'red' } |
| currentSparkColors | data-current-spark-colors | object | JSON object | { 'win': '#AAD579', 'draw': '#CCCCCC', 'loss': '#E89B77' } | { 'win': 'green', 'draw': 'gray', 'loss': 'red' } |
| durations | data-durations | object | JSON object | { move: 1000, freeze: 500, pre: 750} | { move: 750, freeze: 750, pre: 375} |
| pointsLabel | data-points-label | string | | points | очков |
| allLabel | data-all-label | string | | All | Все` |