Sort state and persistence complete.

master
Ben Burlingham 9 years ago
parent 16f6b87a71
commit 7506974691
  1. 5
      index.html
  2. 7
      js/constants.js
  3. 40
      js/diagram.js
  4. 33
      js/main.js
  5. 105
      js/ui.js
  6. 9
      res/events.css
  7. 11
      res/sort.css

@ -29,6 +29,7 @@ body {
</style>
<script src="http://d3js.org/d3.v4.0.0-alpha.50.min.js"></script>
<script src="http://d3js.org/d3-chord.v0.0.min.js"></script>
<script src='js/constants.js'></script>
<script src='js/matrices.js'></script>
<script src='js/diagram.js'></script>
<script src='js/ui.js'></script>
@ -71,8 +72,10 @@ body {
https://openfootball.github.io/questions.html
<h5>TODO</h5>
embiggen current event flag
move styling out of index.html
add team country population below team name
move fetch into main
add sort metric below team name
hide rounds
round persistence
sort persistence

@ -0,0 +1,7 @@
const CONSTANTS = {
SORT_TYPES: {
GOALS: 'goals',
COUNTRY: 'country',
POPULATION: 'population',
},
};

@ -112,15 +112,15 @@ const Diagram = {
getGoalsFor: (data, eventKey, n) => {
const team = data.tourneys[eventKey].teams[n];
return team.ga;
return team.gf;
},
getGoalsAgainst: (data, eventKey, n) => {
const team = data.tourneys[eventKey].teams[n];
return team.gf;
return team.ga;
},
build: (data, eventKey, matrix) => {
build: (data, eventKey, sort, SORT_TYPES, matrix) => {
const svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
@ -132,14 +132,25 @@ const Diagram = {
.padAngle(0.05)
.call(null, matrix);
// const sortedChords = Sorter.sort(chords, 0, chords.groups.length - 1,
// // Diagram.getCountryName.bind(null, data, eventKey),
// // Diagram.getGoalsFor.bind(null, data, eventKey),
// Diagram.getGoalsAgainst.bind(null, data, eventKey),
// // Diagram.getPopulation.bind(null, data, eventKey),
// Diagram.swapGroups.bind(null, data, eventKey));
let sortedChords = chords;
switch (sort) {
case SORT_TYPES.COUNTRY:
sortedChords = Sorter.sort(chords, 0, chords.groups.length - 1,
Diagram.getCountryName.bind(null, data, eventKey),
Diagram.swapGroups.bind(null, data, eventKey));
break;
case SORT_TYPES.GOALS:
sortedChords = Sorter.sort(chords, 0, chords.groups.length - 1,
Diagram.getGoalsFor.bind(null, data, eventKey),
Diagram.swapGroups.bind(null, data, eventKey));
break;
case SORT_TYPES.POPULATION:
sortedChords = Sorter.sort(chords, 0, chords.groups.length - 1,
Diagram.getPopulation.bind(null, data, eventKey),
Diagram.swapGroups.bind(null, data, eventKey));
break;
}
const sortedChords = chords; // SORTED: "null"
// let sortedChords = Diagram.swapGroups(data, "1930", chords, 2, 10);
// sortedChords = Diagram.swapGroups(data, "1930", chords, 2, 8);
// [ Romania, Belgium, Serbia, France, US, Mexico, Paraguay, Peru, Uruguay, Chile, Bolivia, Brazil, Argentina ]
@ -155,15 +166,14 @@ const Diagram = {
// const color = d3.scaleOrdinal(d3.schemeCategory20);
// const color = d3.scaleOrdinal(d3.schemeCategory10);
// const color = d3.scaleOrdinal(d3.interpolateCool);
// const color = d3.scaleSequential(d3.interpolateRainbow);
const color = d3.scaleLinear().domain([0,10]).range(["red", "blue"]).interpolate(d3.interpolateRgb)
const len = data.tourneys[eventKey].teams.length;
// const color = d3.scaleLinear().domain([0, len]).range(["#edf8b1", "#081d58"]).interpolate(d3.interpolateRgb);
// const color = d3.scaleLinear().domain([0, len]).range(["#aaa", "green"]).interpolate(d3.interpolateRgb);
const color = d3.scaleLinear().domain([0, len]).range(["gainsboro", "darkgreen"]).interpolate(d3.interpolateRgb);
// const colors = ["#f1eef6","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"];
// const colors = ["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"];
// const colors = ["#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"];
// const colors = ["#1B9E77", "#D95F02", "#7570B3", "#E7298A", "#66A61E", "#E6AB02", "#A6761D", "#666666"];
// const color = i => colors[i % colors.length];
const g = svg.append("g")

@ -39,8 +39,10 @@ const main = {
},
generateUI: () => {
const state = main.getState();
UI.buildEventsPane(main.changeEvent);
UI.buildSortPane(main.changeSort);
UI.buildSortPane(main.changeSort, CONSTANTS.SORT_TYPES);
UI.buildRoundsPane(main.changeRound);
},
@ -49,12 +51,12 @@ const main = {
const rounds = main.getRounds(state.eventKey);
UI.updateEventsPane(state.eventKey);
UI.updateRoundsPane(rounds);
// UI.updateSortPane(state.sort);
// UI.updateRoundsPane(rounds);
UI.updateSortPane(state.sort);
const matrix = Matrices.buildMatrix(main.json, state.eventKey);
Diagram.clear();
Diagram.build(main.json, state.eventKey, matrix);
Diagram.build(main.json, state.eventKey, state.sort, CONSTANTS.SORT_TYPES, matrix);
},
initJSON: (strData) => {
@ -75,20 +77,37 @@ const main = {
}, {});
},
initState: () => {
const state = main.getState();
if (state.eventKey === undefined) {
state.eventKey = "1930";
}
if (state.sort === undefined) {
state.sort = null;
}
if (state.rounds === undefined) {
}
main.setState(state);
},
setState: (next) => {
const prev = main.getState();
const url = window.location.href.split('?')[0];
const eventKey = next.eventKey || prev.eventKey;
const round = next.round || prev.round || null;
const rounds = next.rounds || prev.rounds || null;
const sort = next.sort || prev.sort || null;
history.pushState(null, null, `${url}?eventKey=${eventKey}&sort=${sort}&round=${round}`);
history.pushState(null, null, `${url}?eventKey=${eventKey}&sort=${sort}&rounds=${rounds}`);
},
}
fetch('worldcup.json')
.then(main.initJSON)
.then(main.setState.call(null, { sort: null, eventKey: "1930" }))
.then(main.initState)
.then(main.generateUI)
.then(main.updateUI);

@ -21,21 +21,24 @@ const UI = {
},
findRoot: (node) => {
while (node !== document.body && node.getAttribute(UI.DATA.EVENT) === null) {
while (node !== document.body && node.getAttribute(UI.DATA.ROOT) === null) {
node = node.parentNode;
}
return node;
},
updateEventsPane: (eventKey) => {
const events = document.querySelectorAll(`.${UI.CLASSNAMES.EVENT.ITEM}`);
events.forEach(node => {
clearActive: (nodes) => {
nodes.forEach(node => {
const classes = node.className.split(' ');
classes.splice(1, classes.indexOf('active'));
node.className = classes.join(' ');
});
},
updateEventsPane: (eventKey) => {
const eventItems = document.querySelectorAll(`.${UI.CLASSNAMES.EVENT.ITEM}`);
UI.clearActive(eventItems);
const activeEventNode = document.querySelector(`[${UI.DATA.EVENT}="${eventKey}"`);
activeEventNode.className += ' active';
@ -43,29 +46,16 @@ const UI = {
updateRoundsPane: (rounds) => {
const roundsDiv = document.querySelector('.rounds');
},
while (roundsDiv.hasChildNodes()) {
roundsDiv.firstChild.remove();
}
console.warn(rounds)
rounds.forEach(round => {
const item = document.createElement('div');
item.className = 'round-item';
item.setAttribute('data-round-id', round.roundId);
const hide = document.createElement('div');
hide.className = 'round-hide';
hide.innerHTML = 'hide';
const text = document.createElement('div');
text.className = 'round-text';
text.innerHTML = round.roundName;
updateSortPane: (sort) => {
const sortItems = document.querySelectorAll('.sort-item');
UI.clearActive(sortItems);
item.appendChild(text);
item.appendChild(hide);
roundsDiv.appendChild(item);
sortItems.forEach(node => {
if (node.getAttribute(UI.DATA.SORT) === sort) {
node.className += ' active';
}
});
},
@ -106,15 +96,17 @@ const UI = {
const flagIcon = document.createElement('div');
item.className = UI.CLASSNAMES.EVENT.ITEM;
year.className = UI.CLASSNAMES.EVENT.YEAR;
location.className = UI.CLASSNAMES.EVENT.LOCATION;
flag.className = UI.CLASSNAMES.EVENT.FLAG;
item.addEventListener('click', onClick);
item.setAttribute(UI.DATA.EVENT, evt.year);
item.setAttribute(UI.DATA.ROOT, true);
year.className = UI.CLASSNAMES.EVENT.YEAR;
year.innerHTML = evt.year;
location.className = UI.CLASSNAMES.EVENT.LOCATION;
location.innerHTML = evt.location;
flag.className = UI.CLASSNAMES.EVENT.FLAG;
flagIcon.className = `flag-icon flag-icon-${evt.icon}`;
flag.appendChild(flagIcon);
@ -126,12 +118,12 @@ const UI = {
});
},
buildSortPane: (onClick) => {
buildSortPane: (onClick, SORT_TYPES) => {
const sortList = [
{ text: 'Order by continent', value: null },
{ text: 'Order by goals scored', value: 'goals-scored' },
{ text: 'Order by country name', value: 'country-name' },
{ text: 'Order by country population', value: 'country-population' },
{ text: 'Order by goals scored', value: SORT_TYPES.GOALS },
{ text: 'Order by country name', value: SORT_TYPES.COUNTRY },
{ text: 'Order by country population', value: SORT_TYPES.POPULATION },
];
const sortDiv = document.querySelector('.sort');
@ -147,6 +139,8 @@ const UI = {
item.className = UI.CLASSNAMES.SORT.ITEM;
item.addEventListener('click', onClick);
item.setAttribute(UI.DATA.SORT, sort.value);
item.setAttribute(UI.DATA.ROOT, true);
item.addEventListener('click', onClick);
text.className = UI.CLASSNAMES.SORT.TEXT;
text.innerHTML = sort.text;
@ -157,36 +151,29 @@ const UI = {
},
buildRoundsPane: (onClick) => {
// <div class="option-item inactive">
// <div class="option-text">Round Robin</div>
// <div class="option-toggle">Hide</div>
// </div>
// const roundsDiv = document.querySelector('.rounds');
//
// <div class="option-item">
// <div class="option-text">Round of 16</div>
// <div class="option-toggle">Hide</div>
// </div>
// while (roundsDiv.hasChildNodes()) {
// roundsDiv.firstChild.remove();
// }
//
// <div class="option-item">
// <div class="option-text">Quarterfinals</div>
// <div class="option-toggle">Hide</div>
// </div>
// rounds.forEach(round => {
// const item = document.createElement('div');
// item.className = 'round-item';
// item.setAttribute('data-round-id', round.roundId);
//
// <div class="option-item">
// <div class="option-text">Semifinals</div>
// <div class="option-toggle">Hide</div>
// </div>
// const hide = document.createElement('div');
// hide.className = 'round-hide';
// hide.innerHTML = 'hide';
//
// <div class="option-item">
// <div class="option-text">Third Place</div>
// <div class="option-toggle">Hide</div>
// </div>
// const text = document.createElement('div');
// text.className = 'round-text';
// text.innerHTML = round.roundName;
//
// <div class="option-item">
// <div class="option-text">Final</div>
// <div class="option-toggle">Hide</div>
// </div>
// item.appendChild(text);
// item.appendChild(hide);
// roundsDiv.appendChild(item);
// });
},
getRoundName: (name) => {

@ -8,8 +8,11 @@
}
.event-item {
background: #CBFFC0;
border-radius: 0 16px 16px 0;
/*background: #CBFFC0;*/
border-color: #fff;
/*border-radius: 0 16px 16px 0;*/
border-style: solid;
border-width: 1px 0;
cursor: pointer;
filter: grayscale(100%);
height: 24px;
@ -21,6 +24,8 @@
.event-item.active,
.event-item.active:hover {
background: #fdfdfd;
border-color: #aaa;
filter: grayscale(0%);
opacity: 1;
}

@ -10,6 +10,17 @@
.sort-item {
border: 1px solid brickred;
cursor: pointer;
font-size: 13px;
line-height: 34px;
}
.sort-item:hover {
background: yellow;
}
.sort-item.active {
background: red;
}
.sort-text {

Loading…
Cancel
Save