replay-table
v1.0.6
Published
Visualize sport seasons with interactive standings
Downloads
48
Maintainers
Readme
Replay Table
A library fo visualizing sport season results with interactive standings:
Live Demos
Quickstart
Prepare an input file with season results or download one from our examples.
Put a
div
withreplayTable
class on your page and supply a link to the input file usingdata-source
attribute:<div class="replayTable" data-source="/path/to/file.csv"> </div>
Include D3.js and Replay Table scripts (70+16 KB gzipped) and the stylesheet. Apply some magic to the body:
<head> ... <script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script> <script type="text/javascript" src="https://unpkg.com/replay-table/dist/replay-table.min.js"></script> <link rel="stylesheet" type="text/css" href="https://unpkg.com/replay-table/dist/replay-table.css"> </head> <body> ... <script type="text/javascript">replayTable.magic()</script> </body>
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
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']
}
Presets
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:
<div class="replayTable"
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 %"
</div>
is identical to this:
<div class="replayTable"
data-source="/path/to/file.csv">
data-preset="winLoss"
</div>
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
|
List of Matches
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.
Points Table
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()
andto(roundIndex)
play()
andpause()
preview(roundIndex)
andendPreview()
drillDown(item)
andendDrillDown()
| 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
|
Classic
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}
|
Sparklines
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
| Все
|
Contribution
Please, post your suggestions and bugs via Github issues. PRs are also welcome!
If you own an API or a database with sports results we'd be happy to collaborate.
We'd also be happy to work with sport journalists to leverage Replay Table for a better season recap.
Credits
The library was built using the orange time at Targetprocess by Anton Iokov (@antoniokov) and Daria Krupenkina (@dariak).
Sparklines prototype was made by Vitali Yanusheuski.
Contact
We're open to your ideas and are ready to help with integrating Replay Table into your website.
Please, write us an email to [email protected] or ping on Twitter at @antoniokov.