Fotball VM
Data
Et eksempler på en turneringsbeskrivelse er slik:
_res2006.js
var results2006={"year":2006,"place":"Tyskland", "description":"Gruppespill i 8 grupper. Topp 2 i hver gruppe til 1/8 finaler", "groups": [ {"gname":"Gruppe A","advance":2, "Teams":[{"name":"Tyskland", "p":9}, {"name":"Ecuador", "p":6}, {"name":"Polen", "p":3}, {"name":"Costa Rica", "p":1} ], "matches":[{"m":"0609,Tyskland,Costa Rica,4-2"}, {"m":"0609,Polen,Ecuador,0-2"}, {"m":"0614,Tyskland,Polen,1-0"}, {"m":"0615,Ecuador,Costa Rica,3-0"}, {"m":"0620,Ecuador,Tyskland,0-3"}, {"m":"0620,Costa Rica,Polen,1-2"} ] }, {"gname":"Gruppe B","advance":2, "Teams":[{"name":"England", "p":7}, {"name":"Sverige", "p":5}, {"name":"Paraguay", "p":3}, {"name":"Trinidad og Tobago", "p":1} ], "matches":[{"m":"0610,England,Paraguay,1-0"}, {"m":"0610,Trinidad og Tobago,Sverige,0-0"}, {"m":"0615,England,Trinidad og Tobago,2-0"}, {"m":"0615,Sverige,Paraguay,1-0"}, {"m":"0620,Sverige,England,2-2"}, {"m":"0620,Paraguay,Trinidad og Tobago,2-0"} ] }, {"gname":"Gruppe C","advance":2, "Teams":[{"name":"Argentina", "p":7}, {"name":"Nederland", "p":7}, {"name":"Elfenbenskysten", "p":3}, {"name":"Serbia og Montenegro", "p":0} ], "matches":[{"m":"0610,Argentina,Elfenbenskysten,2-1"}, {"m":"0611,Serbia og Montenegro,Nederland,0-1"}, {"m":"0616,Argentina,Serbia og Montenegro,6-0"}, {"m":"0616,Nederland,Elfenbenskysten,2-1"}, {"m":"0621,Nederland,Argentina,0-0"}, {"m":"0621,Elfenbenskysten,Serbia og Montenegro,3-2"} ] }, {"gname":"Gruppe D","advance":2, "Teams":[{"name":"Portugal","p":9}, {"name":"Mexico", "p":4}, {"name":"Angola", "p":2}, {"name":"Iran", "p":1} ], "matches":[{"m":"0611,Mexico,Iran,3-1"}, {"m":"0611,Angola,Portugal,0-1"}, {"m":"0616,Mexico,Angola,0-0"}, {"m":"0617,Portugal,Iran,2-0"}, {"m":"0621,Portugal,Mexico,2-1"}, {"m":"0621,Iran,Angola,1-1"} ] }, {"gname":"Gruppe E","advance":2, "Teams":[{"name":"Italia", "p":7}, {"name":"Ghana", "p":6}, {"name":"Tsjekkia","p":3}, {"name":"USA", "p":1} ], "matches":[{"m":"0612,USA,Tsjekkia,0-3"}, {"m":"0612,Italia,Ghana,2-0"}, {"m":"0617,Tsjekkia,Ghana,0-2"}, {"m":"0617,Italia,USA,1-1"}, {"m":"0627,Tsjekkia,Italia,0-2"}, {"m":"0627,Ghana,USA,2-1"} ] }, {"gname":"Gruppe F","advance":2, "Teams":[{"name":"Brasil", "p":9}, {"name":"Australia", "p":4}, {"name":"Kroatia", "p":2}, {"name":"Japan", "p":1} ], "matches":[{"m":"0612,Australia,Japan,3-1"}, {"m":"0613,Brasil,Kroatia,1-0"}, {"m":"0618,Japan,Kroatia,0-0"}, {"m":"0618,Brasil,Australia,2-0"}, {"m":"0622,Japan,Brasil,1-4"}, {"m":"0622,Kroatia,Australia,2-2"} ] }, {"gname":"Gruppe G","advance":2, "Teams":[{"name":"Sveits", "p":7}, {"name":"Frankrike", "p":5}, {"name":"Sør Korea", "p":4}, {"name":"Togo", "p":0} ], "matches":[{"m":"0613,Sør Korea,Togo,2-1"}, {"m":"0613,Frankrike,Sveits,0-0"}, {"m":"0618,Frankrike,Sør Korea,1-1"}, {"m":"0619,Togo,Sveits,0-2"}, {"m":"0623,Togo,Frankrike,0-2"}, {"m":"0623,Sveits,Sør Korea,2-0"} ] }, {"gname":"Gruppe H","advance":2, "Teams":[{"name":"Spania", "p":9}, {"name":"Ukraina", "p":6}, {"name":"Tunisia", "p":1}, {"name":"Saudi Arabia","p":1} ], "matches":[{"m":"0614,Spania,Ukraina,4-0"}, {"m":"0614,Tunisia,Saudi Arabia,2-2"}, {"m":"0619,Saudi Arabia,Ukraina,0-4"}, {"m":"0619,Spania,Tunisia,3-1"}, {"m":"0623,Saudi Arabia,Spania,0-1"}, {"m":"0623,Ukraina,Tunisia,1-0"} ] }, {"gname":"1/8 dels finaler","advance":8, "Teams":[{"name":"Tyskland", "p":3}, {"name":"Argentina", "p":3}, {"name":"Italia", "p":3}, {"name":"Ukraina", "p":3}, {"name":"England", "p":3}, {"name":"Portugal", "p":3}, {"name":"Brasil", "p":3}, {"name":"Frankrike", "p":3}, {"name":"Sverige", "p":0}, {"name":"Ecuador", "p":0}, {"name":"Mexico", "p":0}, {"name":"Nederland", "p":0}, {"name":"Australia", "p":0}, {"name":"Sveits", "p":0}, {"name":"Ghana", "p":0}, {"name":"Spania", "p":0} ], "matches":[{"m":"0624,Tyskland,Sverige,2-0"}, {"m":"0624,Argentina,Mexico,2-1(e.o)"}, {"m":"0625,England,Ecuador,1-0"}, {"m":"0625,Portugal,Nederland,1-0"}, {"m":"0626,Italia,Australia,1-0"}, {"m":"0626,Sveits,Ukraina,0-0 (0-3 str.)"}, {"m":"0627,Brasil,Ghana,3-0"}, {"m":"0627,Spania,Frankrike,1-3"} ] }, {"gname":"1/4 finaler","advance":4, "Teams":[{"name":"Tyskland", "p":3}, {"name":"Italia", "p":3}, {"name":"Portugal", "p":3}, {"name":"Frankrike", "p":3}, {"name":"Argentina", "p":0}, {"name":"Ukraina", "p":0}, {"name":"England", "p":0}, {"name":"Brasil", "p":0} ], "matches":[{"m":"0630,Tyskland,Argentina,1-1 (4-2 str.)"}, {"m":"0630,Italia,Ukraina,3-0"}, {"m":"0701,England,Portugal,0-0(1-3 str.)"}, {"m":"0701,Brasil,Frankrike,0-1"} ] }, {"gname":"Semi finaler","advance":2, "Teams":[{"name":"Italia", "p":3}, {"name":"Frankrike", "p":3}, {"name":"Portugal", "p":0}, {"name":"Tyskland", "p":0} ], "matches":[{"m":"0704,Tyskland,Italia,0-2 (e.o)"}, {"m":"0705,Portugal,Frankrike,0-1"} ] }, {"gname":"Bronse finale","advance":1, "Teams":[{"name":"Tyskland", "p":3}, {"name":"Portugal", "p":0} ], "matches":[{"m":"0708,Tyskland,Portugal,3-1"} ] }, {"gname":"Finale","advance":1, "Teams":[{"name":"Italia", "p":3}, {"name":"Frankrike", "p":0} ], "matches":[{"m":"0709,Italia,Frankrike,1-1(e.o)(5-3 str.)"} ] } ] };
Her er det gjort noen diskutable valg.
- For det første. Dataene er statiske og de er lagt opp slik at det skal være minst mulig bearbeiding når de skal vises. Det er ganske mange vekslende og tildels kompliserte regler for poenggivning og rangering i de ulike turneringene. Den strukturen som bærer det hele er en gruppe. En gruppe kan være en innledende gruppe eller en finale. Vi lagrer eksplisitt hvilke lag som går videre og alle kampresultatene.
- For det andre. Dataene er lagret direkte som Javascript-variable, og alle disse lastes opp når siden lastes. Dette utgjør tilsammen ikke mer enn 120kb data. Alternativet er at vi lagret resultater for en turnering på en fil som JSON, lastet den opp og parset den ved behov. Vi vet at JSON-formatet og formatet på et Javascript-objekt er prinsippielt det samme. Vi kunne derfor ha brukt den samme beskrivelsen, untatt variabletilordningen, som lastbart JSON-format.
I tillegg til turneringsvariablene er det lagt til litt mer generell og åpen informasjon om turneringene. Dette er beskjedne datmengder og de er lagt til på selve websiden, i elementer med display:none. Disse elementene hentes fram etter behov.
Javascript
Javaskriptet som setter opp turneringer er i sin helhet slik:
_wm.js
// all data for the actual tournament // available as a js variable on file //(var results2010 on res2010.js) var data=null; // all group objects var groups=null; // total unique list of all team names (sorted) var totalTeamNameList=null; // story, as fetched from the website in(id=stories) var story=null; //********** helpers **************** //------------------------ // get formatted date as a tablerow // 0612,Sør Korea,Hellas,2-0 -> <td>12. juni</td> // <td>Sør Korea</td><td>Hellas</td><td>2-0</td> function getFormattedMatchString(m){ var parts=m.split(','); // date format var d=parts[0]; var month=d.substring(0,2); if(month=="05")month="mai"; else if(month=="06")month="juni"; else if(month=="07")month="juli"; var day=parseInt(d.substring(2)); return'<tr><td>'+day+'. '+month+'</td><td>'+parts[1]+ '</td><td>'+parts[2]+'</td><td>'+parts[3]+'</td></tr>'; } //------------------------ // get correct flagname for country function getFlagImage(cname){ var flagName=cname.replace(/ /g,'_'); flagName=flagName.replace(/ø/g,'o'); flagName=flagName.replace(/Ø/g,'O'); if((flagName=="Tyskland")&&(data.year==1938)) flagName='Tyskland_38'; return '<img src="flags/'+flagName+'.png" alt=""/>'; } //------------------------ // used by filter for making namelist unique function onlyUnique(value, index, self) { return self.indexOf(value) === index; } //**************************************************** //------------------------ // find alll teamnames function identifyAllTeams(){ var TeamNameList= new Array(); for(var ix=0;ix < groups.length;ix++){ var teamsInGroup=groups[ix].Teams; for(var tix=0;tix<teamsInGroup.length;tix++) TeamNameList[TeamNameList.length]= teamsInGroup[tix].name; } // make unique and sorted list totalTeamNameList=TeamNameList.filter(onlyUnique); totalTeamNameList.sort(); } //------------------ // produce content in ingress in story function makeFinalResult(fg){ var gold=fg.Teams[0].name; var silver=fg.Teams[1].name; return gold+' slo '+ silver+' i finalen.'; } //------------------------ // produce the content within one group tab // all info of a group function makeOneGroupTabberTab(g){ // header // clean up to shorten tab header lengths var groupName=g.gname; groupName=groupName.replace("Gruppe",""); groupName=groupName.replace("finaler",""); groupName=groupName.replace("finale",""); groupName=groupName.replace("dels",""); groupName=groupName.replace("Finale","Fin"); var H='<h3>'+groupName+'</h3>'; // resultTable , only advancers var S='<div class="resulttable"> <table>'; //for(var tix=0;tix<g.Teams.length;tix++){ for(var tix=0;tix<g.advance;tix++){ // set class according to advance from group or not var mark='out'; if(tix < g.advance) mark='advance'; // drop points in final groups var countryName=g.Teams[tix].name; var flagImage=getFlagImage(countryName); if(g.gname.toLowerCase().indexOf("final")==-1) S+='<tr><td>'+flagImage+'</td><td class="'+mark+'">'+ countryName+'</td><td>'+g.Teams[tix].p+'</td></tr>'; else S+='<tr><td>'+flagImage+'</td><td class="'+mark+'">'+ countryName+'</td><td></td></tr>'; } S+='</table></div>'; // matchlist table var T='<div class="matchtable"><table>'; for(var mix=0;mix < g.matches.length;mix++){ var match=g.matches[mix]; var line=getFormattedMatchString(match.m); T+=line; } T+='</table></div>'; // put it together var result='<div class="tabbertab">'+H+S+T+'</div>'; return result; } //------------------------ // final result pluss story function makeStoryBox(){ // final var content='<p id="storyIntro">'+ makeFinalResult(groups[groups.length-1])+ '</p>'; // add story content+='<div id="storyAdded" class="hideStory"'+ story+ '</div>'; // toggle storyAdded content+='<button id="toggler" onclick="toggleStory()">'+ 'mer...</button>'; document.getElementById("story").innerHTML=content; } function toggleStory(){ var elt=document.getElementById("storyAdded"); elt.classList.toggle("hideStory"); var belt=document.getElementById("toggler"); if(belt.innerHTML=="mer...") belt.innerHTML="mindre..."; else belt.innerHTML="mer..."; } //--------------------------- // identify result object from selection in select elt function getData(year){ switch(year){ case 1930:return results1930; case 1934:return results1934; case 1938:return results1938; case 1950:return results1950; case 1954:return results1954; case 1958:return results1958; case 1962:return results1962; case 1966:return results1966; case 1970:return results1970; case 1974:return results1974; case 1978:return results1978; case 1982:return results1982; case 1986:return results1986; case 1990:return results1990; case 1994:return results1994; case 1998:return results1998; case 2002:return results2002; case 2006:return results2006; case 2010:return results2010; case 2014:return results2014; default: return results2014 } } // when new selected function changeVM(){ var selectBox = document.getElementById("vm"); var selectedYear = selectBox.options[selectBox.selectedIndex].value; //console.log(selectedYear); var results=getData(parseInt(selectedYear)); //console.log(results); setUp(results); } //------------------------ // set up a tournament // results is js variable function setUp(results){ try{ // global data data=results; // header document.getElementById("tournament").innerHTML= 'Fotball VM ';//+data.year+" - "+data.place; // for print only: document.getElementById("tname").innerHTML= 'Fotball VM '+data.year+" - "+data.place; // pick up the story story=document.getElementById('story'+data.year).innerHTML; // pick up the groups groups=data.groups; // pick up all teams as a unique, sorted list identifyAllTeams(); //----------- // make story box makeStoryBox(); //--------- // make tabber // first is organization and all teams var tabberContent='<div class="tabbertab"><h3>*</h3>'+ '<p>'+data.description+'</p>'+ '<p>'+totalTeamNameList.length+' lag:'+ '<br/>'+totalTeamNameList.join(', ')+'</p>'+ '</div>'; // group tabs for(var gix=0;gix < groups.length;gix++){ tabberContent+=makeOneGroupTabberTab(groups[gix]); } document.getElementById("grouptabber").innerHTML= '<div class="tabber" id="myTabber" >'+tabberContent+'</div>'; // let the tabber library do its work tabberAutomatic(); } catch(e){ console.log(e); tabberAutomatic(); } } //------------------------ // when loaded, since this script is defered // set up an initial tournament // match of selectedindex (0) // and actual datavariable(results2014) is handmade document.getElementById("vm").selectedIndex=0; setUp(results2014);
Stilsett
Det er benyttet et enkelt stilsett i tillegg til de stilene som er definert for tabber-koden:
_wm.css
html{line-height:120%; } body{font-size: 62.5%; background: #ddd; color: #333; font-family: Cambria,Georgia,Times New Roman,Times,serif; font-weight: 500; margin:0px 0px 0px 0px; padding:0px; font-size:1em } /*top,right,bottom,left*/ @media screen{ /* header*/ #tname{display:none}/*print only*/ #tournament,#selectvm #vm{ font-family:inherit;font-size:1.3em;font-weight:bold; padding:10px 0px 10px 0px; margin:10px 0px 0px 10px} #selectvm #vm{ height:2.1em; padding:10px 5px 0px 5px; border-width:thin; border-color:red} #selectvm option{font-size:0.8em;} #story,#myTabber{font-size:1em;color:black; width:95%; max-width:500px; border:1px solid #aaa; box-shadow: 5px 5px 5px #888888; margin: 10px 0px 10px 5px; padding:5px; background-color:white;/*#F5F5DC;*/ overflow:auto; } .hideStory{display:none} /* all links */ a{text-decoration: none;} /*a:link{ background: url(exicon.gif) no-repeat 100% 0;padding: 0 20px 0 0; } a:visited { color: purple; background: url(exicon.gif) no-repeat 100% -100px; padding: 0 20px 0 0; } a:hover { color: red; background: url(exicon.gif) no-repeat 100% -200px; padding: 0 20px 0 0; } */ /* within tab, se also tabber.css, marked bs*/ .organize{font: 12px/14px Verdana, Arial, Helvetica, sans-serif} .resulttable{margin-top:10px} .resulttable table{font: 11px/13px Verdana, Arial, Helvetica, sans-serif; border-collapse:collapse; width: 300px;} .resulttable table td{padding-bottom:5px} .resulttable table tr td:nth-child(1) {width:40px} .resulttable table tr td:nth-child(2) {width:90px} .out{color:gray} .advance{color:green;font-weight:bold} .matchtable{margin-top:10px} .matchtable table{ font: 11px/16px Verdana, Arial, Helvetica, sans-serif; border-collapse:collapse; width: 390px; } .matchtable table td{width:70px} .matchtable table tr td:nth-child(1){width:40px} .matchtable table tr td:nth-child(4){width:70px} } @media print { /*#selectvm{display:none}*/ #tournament,#selectvm{display:none} .matchtable{margin-top:30px} .out{color:gray} .advance{color:green;font-weight:bold} #tname{display:inline-block;font-size:32px;font-weight:bold} }