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> </style>
<script src="http://d3js.org/d3.v4.0.0-alpha.50.min.js"></script> <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="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/matrices.js'></script>
<script src='js/diagram.js'></script> <script src='js/diagram.js'></script>
<script src='js/ui.js'></script> <script src='js/ui.js'></script>
@ -71,8 +72,10 @@ body {
https://openfootball.github.io/questions.html https://openfootball.github.io/questions.html
<h5>TODO</h5> <h5>TODO</h5>
embiggen current event flag
move styling out of index.html 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 hide rounds
round persistence round persistence
sort 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) => { getGoalsFor: (data, eventKey, n) => {
const team = data.tourneys[eventKey].teams[n]; const team = data.tourneys[eventKey].teams[n];
return team.ga; return team.gf;
}, },
getGoalsAgainst: (data, eventKey, n) => { getGoalsAgainst: (data, eventKey, n) => {
const team = data.tourneys[eventKey].teams[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"), const svg = d3.select("svg"),
width = +svg.attr("width"), width = +svg.attr("width"),
height = +svg.attr("height"), height = +svg.attr("height"),
@ -132,14 +132,25 @@ const Diagram = {
.padAngle(0.05) .padAngle(0.05)
.call(null, matrix); .call(null, matrix);
// const sortedChords = Sorter.sort(chords, 0, chords.groups.length - 1, let sortedChords = chords;
// // Diagram.getCountryName.bind(null, data, eventKey), switch (sort) {
// // Diagram.getGoalsFor.bind(null, data, eventKey), case SORT_TYPES.COUNTRY:
// Diagram.getGoalsAgainst.bind(null, data, eventKey), sortedChords = Sorter.sort(chords, 0, chords.groups.length - 1,
// // Diagram.getPopulation.bind(null, data, eventKey), Diagram.getCountryName.bind(null, data, eventKey),
// Diagram.swapGroups.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); // let sortedChords = Diagram.swapGroups(data, "1930", chords, 2, 10);
// sortedChords = Diagram.swapGroups(data, "1930", chords, 2, 8); // sortedChords = Diagram.swapGroups(data, "1930", chords, 2, 8);
// [ Romania, Belgium, Serbia, France, US, Mexico, Paraguay, Peru, Uruguay, Chile, Bolivia, Brazil, Argentina ] // [ 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.schemeCategory20);
// const color = d3.scaleOrdinal(d3.schemeCategory10); // 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 = ["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"];
// const colors = ["#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"]; // 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 color = i => colors[i % colors.length];
const g = svg.append("g") const g = svg.append("g")

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

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

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

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

Loading…
Cancel
Save