diff --git a/football_db_intro.md b/football_db_intro.md new file mode 100644 index 0000000..50480f5 --- /dev/null +++ b/football_db_intro.md @@ -0,0 +1,539 @@ +title: football.db - Using Open Football Data in JavaScript + +%css + +pre { + padding: 4px 4px 4px 4px; + border-top: #bbb 1px solid; + border-bottom: #bbb 1px solid; + background: #f3f3f3; +} + +%end + +# `football.db` - Using Open Football Data in JavaScript + +### Agenda + +- What's `football.db`? +- Example: La Liga - `es/teams.txt` +- Example: Champions League - `club/europe/2012_13/cl_ii.txt` +- Leagues and Tournaments / National Teams +- Intn'l Club Tournaments (Champions Leagues & Friends) +- National Club Leagues & Cups +- How to use `football.db` in JavaScript +- How to use HTTP JSON API - `GET /event/euro.2012/teams` +- How to use HTTP JSON API II - `GET /event/euro.2012/rounds` +- How to use HTTP JSON API III - `GET /event/euro.2012/round/6` +- How to use HTTP JSON(P) API in JavaScript & jQuery +- All Together Now - Machday Widget Example - `footballdb.widget.js` + + + +# What's `football.db`? + +A free open public domain football (soccer) database & schema +for use in any (programming) language + +(e.g. uses plain text fixtures/data sets) + +``` +### Teams + +barcelona, Barcelona|FC Barcelona|Fútbol Club Barcelona, BAR, city:barcelona +``` + +``` +### Matches + +2013-03-12 20:45 Barcelona 4-0 Milan +``` + + +# Example: La Liga - `es/teams.txt` + +``` +################################ +# Primera División de España - La Liga + +barcelona, Barcelona|FC Barcelona|Fútbol Club Barcelona, BAR, city:barcelona +espanyol, Espanyol Barcelona|Real CD Espanyol, ESP, city:barcelona + +madrid, Real Madrid|Real Madrid CF, RMD, city:madrid +atletico, Atlético Madrid|Club Atlético de Madrid, ATL, city:madrid +getafe, Getafe|Getafe CF|Getafe Club de Fútbol, GET, city:madrid +rayo, Rayo Vallecano|Rayo Vallecano de Madrid, RAY, city:madrid + +realbetis, Real Betis Sevilla|Real Betis|Real Betis Balompié, BET, city:sevilla +sevilla, Sevilla|Sevilla FC|Sevilla Fútbol Club, SEV, city:sevilla + +valencia, Valencia|FC Valencia|CF Valencia|Valencia CF, VAL, city:valencia +levante, Levante|Levante UD|Levante Unión Deportiva, LEV, city:valencia + +malaga, Málaga|FC Málaga|Málaga CF|CF Málaga, MAG, city:malaga +athletic, Athletic Bilbao, ATH, city:bilbao +granada, Granada|Granada CF|Granada Club de Fútbol, GRA, city:granada +osasuna, Osasuna|CA Osasuna|Club Atlético Osasuna, OSA, city:pamplona +... +``` + +Source: [`es/teams.txt`](https://github.com/geraldb/football.db/blob/master/es/teams.txt) + + + +# Example: Champions League - `club/europe/2012_13/cl_ii.txt` + +``` +#################################### +# Champions League 2012/13 - Finalrunden + +(8) Achtelfinale Rückspiele // Di./Mi., 5.+6./12.+13. Mär 2013 + +2013-03-05 20:45 Manchester United 1-2 Real Madrid +2013-03-05 20:45 Borussia Dortmund 3-0 Schachtar Donezk + +2013-03-06 20:45 Paris Saint-Germain 1-1 Valencia +2013-03-06 20:45 Juventus 2-0 Celtic Glasgow + +2013-03-12 20:45 Schalke 04 2-3 Galatasaray +2013-03-12 20:45 Barcelona 4-0 Milan + +2013-03-13 20:45 Málaga 2-0 Porto +2013-03-13 20:45 Bayern München 0-2 Arsenal +... +``` + +Source: [`club/europe/2012_13/cl_ii.txt`](https://github.com/geraldb/football.db/blob/master/club/europe/2012_13/cl_ii.txt) + + + +# Leagues and Tournaments / National Teams + +### World + +- FIFA World Cup 2010, 2014 + +``` +########### +# Groups + +Group A | South Africa Mexico Uruguay France +Group B | Argentina Nigeria South Korea Greece +Group C | England United States Algeria Slovenia +Group D | Germany Australia Serbia Ghana +Group E | Netherlands Denmark Japan Cameroon +Group F | Italy Paraguay New Zealand Slovakia +Group G | Brazil North Korea Côte d'Ivoire Portugal +Group H | Spain Switzerland Honduras Chile + + +################ +# Group A + +Matchday 1 / Group A + +(1) Fr 2010-06-11 16:00 South Africa - Mexico 1-1 +(2) Fr 2010-06-11 20:30 Uruguay - France 0-0 + +... +``` + +Source: [`world/2010/cup.txt`](https://github.com/geraldb/football.db/blob/master/world/2010/cup.txt) + + +# Leagues and Tournaments / National Teams (Cont.) + +### World (Cont.) + + +- FIFA World Cup Quali 2014 +- FIFA Confederations Cup 2009, 2013 + +### America (North/Central America and the Caribeans, South America) + +- CONCACAF Copa Oro / Gold Cup 2011, 2013 +- CONMEBOL Copa América 2011, 2015 + +### Europe + +- UEFA European Football Championship (Euro) 2012, 2008 + + + +# Intn'l Club Tournaments (Champions Leagues & Friends) + +### Amercia (North/Central America and the Caribeans, South America) + +- CONCACAF Champions League 2011/12, 2012/13 +- CONMEBOL Copa Sudamericana 2012 +- CONMEBOL Copa Libertadores 2012, 2013 + +### Europe + +- UEFA Champions League 2011/12, 2012/13 +- UEFA Europa League 2011/12 + + +# National Club Leagues & Cups + +### Europe + +- Österreichische Bundesliga 2011/12, 2012/13 +- ÖFB Cup 2011/12, 2012/13 + +``` +###################################################### +# Österreichische Bundesliga 2012/13 - Frühjahr + +21. Runde // Sa+So 16.+17. Feb 2013 + +2013-02-16 16:00 SV Ried - FC Wacker Innsbruck 3:0 +2013-02-16 18:30 SV Mattersburg - Sturm Graz 0:0 +2013-02-16 18:30 FC Admira Wacker - SC Wiener Neustadt 1:2 +2013-02-16 18:30 => 2013-03-06 18:30 Wolfsberger AC - RB Salzburg 1:1 + +2013-02-17 16:00 Rapid Wien - Austria Wien 1:2 + + +22. Runde // Sa+So 23.+24. Feb 2013 + +2013-02-23 16:00 FC Wacker Innsbruck - SV Mattersburg 2:0 +2013-02-23 18:30 SC Wiener Neustadt - SV Ried 0:0 +2013-02-23 18:30 Sturm Graz - Wolfsberger AC 1:3 +2013-02-23 18:30 Austria Wien - FC Admira Wacker 4:0 + +2013-02-24 16:00 RB Salzburg - Rapid Wien 3:3 + +... +``` + +Source: [`at/2012_13/bl_ii.txt`](https://github.com/geraldb/football.db/blob/master/at/2012_13/bl_ii.txt) + + + +# National Club Leagues & Cups (Cont.) + +### Europe (Cont.) + +- English Permier League 2012/13 +- Deutsche Bundesliga 2012/13 +- Romania Liga 1 2012/13 + +### North America + +- México Primera División Apertura 2012, Clausura 2013 + +### South America + +- Campeonato Brasileiro Série A + +Anything missing? Add your leagues, teams, fixtures and more. + + + + +# How to use `football.db` in JavaScript + +Use the `football.db` HTTP JSON(P) API - Examples + +List all teams for an event (league+season) `/event/:key/teams` + +- `/event/de.2012_13/teams` | Deutsche 1. Bundesliga 2012/13 +- `/event/world.2010/teams` | World Cup 2010 + +List all rounds for an event (league+season) `/event/:key/rounds` + +- `/event/de.2012_13/rounds` | Deutsche 1. Bundesliga 2012/13 +- `/event/world.2010/rounds` | World Cup 2010 + + +List all games in a round for an event (league+season) `/event/:key/round/:pos` + +- `/event/de.2012_13/round/5` | Deutsche 1. Bundesliga 2012/13 - 5th Round +- `/event/world.2010/round/20` | World Cup 2010 - 20th Round (=> Final) + + +Try it live @ [`footballdb.herokuapp.com/api`](http://footballdb.herokuapp.com/api) + + + +# How to use HTTP JSON API - `GET /event/euro.2012/teams` + +List all teams for an event `/event/:key/teams` + +``` +GET /event/euro.2012/teams + +{ + "event": + { + "key":"euro.2012", + "title":"Euro 2012" + }, + "teams": + [ + {"key":"pol","title":"Poland","code":"POL"}, + {"key":"gre","title":"Greece","code":"GRE"}, + {"key":"rus","title":"Russia","code":"RUS"}, + {"key":"cze","title":"Czech Republic","code":"CZE"}, + {"key":"ned","title":"Netherlands","code":"NED"}, + {"key":"den","title":"Denmark","code":"DEN"}, + {"key":"ger","title":"Germany","code":"GER"}, + {"key":"por","title":"Portugal","code":"POR"}, + {"key":"esp","title":"Spain","code":"ESP"}, + {"key":"ita","title":"Italy","code":"ITA"}, + {"key":"irl","title":"Irland","code":"IRL"}, + {"key":"cro","title":"Croatia","code":"CRO"}, + {"key":"ukr","title":"Ukraine","code":"UKR"}, + {"key":"swe","title":"Sweden","code":"SWE"}, + {"key":"fra","title":"France","code":"FRA"}, + {"key":"eng","title":"England","code":"ENG"} + ] +} +``` + + + +# How to use HTTP JSON API (Cont.) - `GET /event/euro.2012/rounds` + +List all rounds for an event `/event/:key/rounds` + +``` +GET /event/euro.2012/rounds + +{ + "event": + { + "key":"euro.2012", + "title":"Euro 2012" + }, + "rounds": + [ + {"pos":1,"title":"1. Round"}, + {"pos":2,"title":"2. Round"}, + {"pos":3,"title":"3. Round"}, + {"pos":4,"title":"Quarter-finals"}, + {"pos":5,"title":"Semi-finals"}, + {"pos":6,"title":"Final"} + ] +} +``` + + + +# How to use HTTP JSON API (Cont.) - `GET /event/euro.2012/round/6` + +List all games in a round for an event `/event/:key/round/:pos` + +``` +GET /event/euro.2012/round/6 + +{ + "event": { "key":"euro.2012", "title":"Euro 2012" }, + "round": { pos": 6, "title": "Final" }, + "games": + [ + { + "team1_key": "esp", + "team1_title": "Spain", + "team1_code": "ESP", + "team2_key": "ita", + "team2_title": "Italy", + "team2_code": "ITA", + "play_at": "2012/07/01", + "score1": 4, + "score2": 0, + "score3": null, + "score4": null, + "score5": null, + "score6": null + } + ] +} +``` + + +# How to use HTTP JSON(P) API in JavaScript & jQuery + +In your hypertext (HTML) document using a plain vanilla cross-domain JavaScript request +(using the JSONP technique): + +``` + + + +``` + +Or using the jQuery library using the getJSON function: + +``` +$.getJSON('http://footballdb.herokuapp.com/api/v1/event/en.2012_13/round/2?callback=?', function(json) { + // Do something with the returned data +}); +``` + +Note: Add the `callback=?` query parameter to tell jQuery to use a cross-domain JSONP request. + +That’s it. + + + +# All Together Now - Machday Widget Example - `footballdb.widget.js` + +Use like: + +``` +var footballdb_widget = footballdb_widget_new( '#widget', '/api/v1' ) +footballdb_widget.update( 'euro.2012', '1' ) +footballdb_widget_update( 'euro.2012', '2' ) +etc. +``` + +Results in: + +``` +Euro 2012 - Semi-finals + +2012/06/27 | Portugal (POR) 2-4 iE / 0-0 nV / 0-0 Spain (ESP) +2012/06/28 | Germany (GER) 1-2 Italy (ITA) +``` + +Source: + +``` +var footballdb_widget_new = function( widget_id, api_path_prefix ) { + + var _api_path_prefix = ''; + var _$widget; + + function _init( widget_id, api_path_prefix ) + { + _api_path_prefix = api_path_prefix; + _$widget = $( widget_id ); + } + + function _update( event_key, round_pos ) + { + var api_link = _api_path_prefix + "/event/" + event_key + "/round/" + round_pos; + + $.getJSON( api_link, function(json) { + + var snippet = ""; // build up a hypertext (html) snippet to add/append + + snippet += "

"; + snippet += json.event.title; + snippet += " - "; + snippet += json.round.title; + snippet += "

"; + + snippet += ""; + + _$widget.html( snippet ); + }); // getJSON + } // fn _update + + // call c'tor/constructor + _init( widget_id, api_path_prefix ); + + // return/export public api + return { + update: _update + } + +} // fn football_widget_new +``` + + +# That's it. Thank you. + +### Links + +- [github.com/openfootball](https://github.com/openfootball) + +More Open Data Projects + +- [github.com/openbeer](https://github.com/openbeer) +- [github.com/openwine](https://github.com/openwine) +- [github.com/openmundi](https://github.com/openmundi) + +### Questions? Comments? + + + +# Bonus: What's `beer.db`? + +A free open public domain beer database & schema +for use in any (programming) language + + +(e.g. uses plain text fixtures/data sets) + +``` +### Brewery + +guinness, St. James's Gate Brewery / Guinness Brewery, 1759, D, city:dublin +``` + +``` +### Beer + +Guinness|Guinness Draught, 4.2%, by:guinness, irish_dry_stout|dry_stout|stout +``` + +# Bonus: How to use HTTP JSON API - `GET /beer/guinness` + +Get beer by key `/beer/:key` + +``` +GET /beer/guinness + +{ + "beer": + { + "key":"guinness", + "title":"Guinness", + "synonyms": "Guinness Draught", + "abv":"4.2", + "srm":null, + "og":null, + "tags":["irish_dry_stout","dry_stout","stout"], + "brewery": + { + "key": "guinness", + "title": "St. James's Gate Brewery / Guinness Brewery" + }, + "country": + { + "key":"ie", + "title":"Irland" + } + } +} +``` diff --git a/i/fifa-match-schedule-download.png b/i/fifa-match-schedule-download.png new file mode 100644 index 0000000..8cc6ffe Binary files /dev/null and b/i/fifa-match-schedule-download.png differ diff --git a/i/fifa-match-schedule-inside.png b/i/fifa-match-schedule-inside.png new file mode 100644 index 0000000..9847e74 Binary files /dev/null and b/i/fifa-match-schedule-inside.png differ diff --git a/i/fifa-match-schedule.png b/i/fifa-match-schedule.png new file mode 100644 index 0000000..b27ad12 Binary files /dev/null and b/i/fifa-match-schedule.png differ diff --git a/i/github-openfootball-worldcup.png b/i/github-openfootball-worldcup.png new file mode 100644 index 0000000..07da940 Binary files /dev/null and b/i/github-openfootball-worldcup.png differ diff --git a/i/github-openfootball.png b/i/github-openfootball.png new file mode 100644 index 0000000..b673ad4 Binary files /dev/null and b/i/github-openfootball.png differ diff --git a/i/sport-db-admin.png b/i/sport-db-admin.png new file mode 100644 index 0000000..4af4678 Binary files /dev/null and b/i/sport-db-admin.png differ diff --git a/i/sportbook.png b/i/sportbook.png new file mode 100644 index 0000000..d90476d Binary files /dev/null and b/i/sportbook.png differ diff --git a/i/wikipedia-worldcup.png b/i/wikipedia-worldcup.png new file mode 100644 index 0000000..be71b31 Binary files /dev/null and b/i/wikipedia-worldcup.png differ diff --git a/i/worldcup2014-db-download.png b/i/worldcup2014-db-download.png new file mode 100644 index 0000000..0697d87 Binary files /dev/null and b/i/worldcup2014-db-download.png differ diff --git a/open_data_world_cup.md b/open_data_world_cup.md new file mode 100644 index 0000000..80913d1 --- /dev/null +++ b/open_data_world_cup.md @@ -0,0 +1,568 @@ +title: Using Open Football Data - Get Ready for the World Cup in Brazil 2014 w/ Ruby + + +%css + +pre { + padding: 4px 4px 4px 4px; + border-top: #bbb 1px solid; + border-bottom: #bbb 1px solid; + background: #f3f3f3; +} + +%end + + +# Using Open Football Data - Get Ready for the World Cup in Brazil 2014 w/ Ruby + +### Agenda + +- The State of Open Data - World Cup in Brazil 2014 +- Do-It-Yourself -- Let's Build `football.db` - Open Football Data +- Do-It-Yourself -- What Wiki Package to Use? +- Do-It-Yourself -- What Source Format to Use? +- Ruby, Ruby, Ruby -- `sportdb` Ruby Gem +- How to use `football.db` in Ruby - Models +- How to use `football.db` with HTTP JSON(P) API +- More Goodies - Examples Web Apps and Books +- Bonus: License -- What is Public Domain? Why Public Domain? +- Bonus: Beer? Wine? Alpine Ski? Formula 1? +- Bonus: How to use HTTP JSON API - `GET /beer/guinness` + + + +# World Cup in Brazil 2014 - The World's Biggest (Sport) Event + +When: + +- 25 (match)days -- 12 June - 13 July + +Where: + +- 12 cities -- Rio de Janeiro, São Paulo, Brasília, Fortaleza, + Belo Horizonte, Porto Alegre, Salvador, Recife, + Cuiabá, Manaus, Natal, Curitiba + +Teams: + +- 32 teams -- Australia, Iran, Japan, South Korea, + Algeria, Cameroon, Ghana, Ivory Coast, Nigeria, + Costa Rica, Honduras, Mexico, United States, + Argentina, Brazil, Chile, Colombia, Ecuador, + Uruguay, Belgium, Bosnia and Herzegovina, + Croatia, England, France, Germany, + Greece, Italy, Netherlands, Portugal, + Russia, Spain, Switzerland + +Matches: + +- 64 matches -- Groups stage (8x4): (Group A, Group B + Group C, Group D, Group E, Group F, Group G + Group H); Knockout stage: Round of 16, + Quarter-finals, + Semi-finals, + Third place match, + Final + + + + +# The State of Open Data - World Cup in Brazil 2014 + +Q: Where can I get the teams, groups, match schedule (fixtures), +players, stadiums lets say in CSV, JSON or SQL? + +Q: Where can I download lets say `world-cup-2014.db`? + +Let's search (google): + +- [`open data world cup brazil`](http://google.com/search?q=open+data+world+cup+brazil) or +- [`json world cup brazil`](http://google.com/search?q=json+world+cup+brazil) + +Nothing. Nada. Nichts. Niente. Zilch. Zero. + + + + +# The State of Open Data - World Cup in Brazil 2014 (Cont.) + + +### Official FIFA Site ([`fifa.com/worldcup`](http://www.fifa.com/worldcup)) + +=> No open data. Offers a booklet¹ (PDF) for download for match schedule. + +¹) Single page, really w/ six FIFA Partners, eight FIFA World Cup Sponsors +and another six National Supporters. + + +### Wikipedia ([`en.wikipedia.org/wiki/2014_FIFA_World_Cup`](http://en.wikipedia.org/wiki/2014_FIFA_World_Cup)) + +Pro: Best source; open text license or public domain (license-free); +everything available for download (page dumps, etc). + +Cons: Mostly free-form text, that is, no structured data and no web service. + + +# What now? Options + +1) Screen scrap FIFA site with web crawler? Why not? + +2) Try to convert free-form text from Wikipedia into structured data? Why not? + +3) Do-It-Yourself: Build a Wikipedia for structured data? Why not? + + + +# Do-It-Yourself -- Let's Build `football.db` - Open Football Data + + +Q: What Wiki Package to Use? + +MediaWiki? Semantic MediaWiki? MoinMoin? DokuWiki? PeanutButterWiki? Any Others? + + +Q: What Source Format to Use? + +XML, JSON, YAML, SEXPS (S-Expressions), RDF Triplets, +CSV (Comma-Separated Values), TOML (Tom's Obvious, Minimal Language)? SQL? Any Others? + + + + +# Do-It-Yourself -- `github.com/openfootball` (Cont.) + + +Q: What Wiki Package to Use? + +A: Git (and GitHub) + + +Why Git? + +- Distributed is the new centralized (everything is local, any workflow, many backups, and so on) +- Free and open source; small and fast version tracker + +Learn more @ [`git-scm.com`](http://git-scm.com) + + +Why GitHub? + +- Build software data better, together. + +Learn more @ [`github.com`](http://github.com) + + +![](i/github-openfootball-worldcup.png) + + + + +# Do-It-Yourself -- What is CSV (Comma-Separated Values)? + +Q: What Source Format to Use? + +A: Keep it as simple as possible. Hand-crafted not machine-generated source. +Easy-to-read and easy-to-write. + + +XML, JSON, YAML, SEXPS (S-Expressions), +RDF Triplets, SQL, +TOML (Tom's Obvious, Minimal Language), +CSV (Comma-Separated Values) + + +`teams.csv`: + +~~~ +gre, Greece, GRE, gr +ned, Netherlands, NED, nl +ger, Germany, GER, de +por, Portugal, POR, pt +esp, Spain, ESP, es +ita, Italy, ITA, it +cro, Croatia, CRO, hr +eng, England, ENG, en +... +~~~ + + +# Do-It-Yourself --- What's missing in CSV? What's CSV v2? + +What's missing? + +- No comments +- No blank lines +- No multi-line records +- No data types (or text patterns or field markers) +- No unordered fields (that is, fields depend on position) or variable number of fields per record +- No default/inherited values +- And much more + +Let's fix it. Welcome CSV v2 ([`github.com/csv2`](https://github.com/csv2)). + + +[`south-america/br-brazil--stadiums.txt`](https://github.com/openfootball/stadiums/blob/master/south-america/br-brazil--stadiums.txt): + +~~~ +### Stadiums + +[maracana] + Maracanã|Estádio do Maracanã, 1950 + 76_935 + Rio de Janeiro, RJ + en.wikipedia: Estádio_do_Maracanã + + +[corinthians] + Corinthians|Arena Corinthians|Arena de São Paulo, 2014 + 68_000 + São Paulo, SP + en.wikipedia: Arena_Corinthians + +... +~~~ + + +# Do-It-Yourself -- Mini Language for Football Fixtures + +DSL - Domain-Specific Language + +[`world-cup/2014/cup.txt`](https://github.com/openfootball/world-cup/blob/master/2014--brazil/cup.txt): + +~~~ +################################## +# World Cup 2014 Brazil + +# -- Groups + +Group A | Brazil Croatia Mexico Cameroon +Group B | Spain Netherlands Chile Australia +Group C | Colombia Greece Côte d'Ivoire Japan +Group D | Uruguay Costa Rica England Italy +Group E | Switzerland Ecuador France Honduras +Group F | Argentina Bosnia-Herzegovina Iran Nigeria +Group G | Germany Portugal Ghana United States +Group H | Belgium Algeria Russia South Korea + + +# -- Group A + +Matchday 1 / Group A + +(1) Thu Jun/12 17:00 Brazil - Croatia @ Arena de São Paulo, São Paulo (UTC-3) + +Matchday 2 / Group A + +(2) Fri Jun/13 13:00 Mexico - Cameroon @ Estádio das Dunas, Natal (UTC-3) +~~~ + + + +# Ruby, Ruby, Ruby -- `sportdb` Ruby Gem + +Import any fixtures: + +- "Classic" Comma-separated values +- "Modern" Comma-separated values v2 +- Mini language for football + +into any SQL database. Example: + + +Step 1: Get a copy of the data + +~~~ +$ git clone git://github.com/openmundi/world.db.git +$ git clone git://github.com/openfootball/world-cup.git +~~~ + +Step 2: Let's build the `world-cup-2014.db` + +~~~ +$ sportdb --dbname world-cup-2014.db setup --include ./world-cup --worldinclude ./world.db +~~~ + +That's it. + + + +# How to use `football.db` in Ruby - Models + +Event Model + +~~~ +ev = Event.find_by( key: 'world.2014' ) + +ev.title +=> 'World Cup 2014' + +ev.teams.count +=> 32 + +ev.games.count +=> 64 + +ev.rounds.count +=> 20 + +ev.groups.count +=> 8 + +ev.stadiums.count +=> 12 +~~~ + + +# How to use `football.db` in Ruby - Models (Cont.) + +Team Model + +~~~ +bra = Team.find_by( key: 'bra' ) + +bra.title +=> 'Brazil' + +bra.country.continent.title +=> 'South America' + +bra.games.count +=> 3 +~~~ + + +# How to use `football.db` in Ruby - Models (Cont.) + +Game Model + +~~~ +g = Game.find_by( pos: 1 ) + +g.team1.title +=> 'Brazil' + +g.team2.title +=> 'Croatia' + +f.group.title +=> 'Group A' + +f.round.title +=> 'Matchday 1' + +f.stadium.title +=> 'Arena de São Paulo' + +f.stadium.city.title +=> 'São Paulo' +~~~ + + +# How to use `football.db` in Ruby - Models (Cont.) + +More Models + +- Round (e.g. Matchday 1, Round of 16, Final, etc.) +- Group (e.g. Group A, Group B, etc.) +- League (e.g. World Cup, World Cup Quali, World Confed, etc.) +- Season (e.g. 2014, 2018, etc.) +- Person a.k.a. Player (e.g. Lionel Messi, Neymar Jr, etc.) +- Roster a.k.a. Team Squad (e.g. ARG-9 Lionel Messi, BRA-11 Neymar Jr, etc.) +- Ground a.k.a. Stadium (e.g. Estádio do Maracanã) +- And some more + + + +# How to use `football.db` with HTTP JSON(P) API + +~~~ +$ sportdb serve +~~~ + +Use the `football.db` HTTP JSON(P) API - Examples + +List all teams for an event (league+season) `/event/:key/teams` + +- `/event/world.2014/teams` | World Cup 2014 +- `/event/de.2013_14/teams` | Deutsche Bundesliga 2013/14 + +List all rounds for an event (league+season) `/event/:key/rounds` + +- `/event/world.2014/rounds` | World Cup 2014 +- `/event/de.2013_14/rounds` | Deutsche Bundesliga 2013/14 + +List all games in a round for an event (league+season) `/event/:key/round/:pos` + +- `/event/world.2014/round/20` | World Cup 2014 - 20th Round (=> Final) +- `/event/de.2013_14/round/5` | Deutsche Bundesliga 2013/14 - 5th Round + + + +# How to use HTTP JSON API - `GET /event/world.2014/teams` + +List all teams for an event `/event/:key/teams` + +~~~ +GET /event/world.2014/teams + +{ + "event": { + "key": "world.2014", + "title": "World Cup 2014" + }, + "teams": [ + { "key": "gre", "title": "Greece", "code": "GRE" }, + { "key": "rus", "title": "Russia", "code": "RUS" }, + { "key": "ned", "title": "Netherlands", "code": "NED" }, + { "key": "ger", "title": "Germany", "code": "GER" }, + { "key": "por", "title": "Portugal","code": "POR" }, + ... + ] +} +~~~ + +# How to use HTTP JSON API (Cont.) - `GET /event/world.2014/round/1` + +List all games in a round for an event `/event/:key/round/:pos` + +~~~ +GET /event/world.2014/round/1 + +{ + "event": { "key": "world.2014", "title": "World Cup 2014" }, + "round": { "pos": 1, "title": "Matchday 1" }, + "games": [ + { + "team1_key": "bra", + "team1_title": "Brazil", + "team1_code": "BRA", + "team2_key": "cro", + "team2_title": "Croatia", + "team2_code": "CRO", + "play_at": "2014/06/12", + "score1": null, + "score2": null, + "score1ot": null, + "score2ot": null, + "score1p": null, + "score2p": null + } + ] +} +~~~ + + +# More Goodies - Examples Web Apps and Books + +Any Example Web Apps? + +- `sport.db.admim` - Open Source Rails Engine; see [`github.com/geraldb/sport.db.admin`](https://github.com/geraldb/sport.db.admin) + +![](i/sport-db-admin.png) + + +# More Goodies - Examples Web Apps and Books (Cont.) + +Any Example Web Apps? + +- Sportbook - Football Betting (Prediction, Picks) Pool Manager; Open Source Rails Web App; see [`github.com/openbookie`](https://github.com/openbookie) + +![](i/sportbook.png) + + +# More Goodies - Examples Web Apps and Books (Cont.) + +Any Example Web Apps? + +- `football.js` - Open Source JavaScript Matchday Widget - still early stage; see [`github.com/footballjs`](https://github.com/footballjs) +- The Free World Football Almanac - Free public domain e-book - still early stage; see [`github.com/openfootball/book`](https://github.com/openfootball/book) + +Anything Else? + +- Your App Here; Be Bold + + + +# That's it. Thank you. + +### Links + +- [github.com/openfootball](https://github.com/openfootball) + +More Open Data Projects + +- [github.com/openbeer](https://github.com/openbeer) +- [github.com/openwine](https://github.com/openwine) +- [github.com/openmundi](https://github.com/openmundi) + +### Questions? Comments? + + + +# Bonus: License -- What is Public Domain? Why Public Domain? + +## License + +The `football.db` schema, data and scripts are dedicated to the public domain. +Use it as you please with no restrictions whatsoever. + +## What? + +No Copyright. No License. Creative Commons Zero (CC0). Unlicense. + +## Why? + +Keep it simple. + + +# Bonus: Beer? Wine? Alpine Ski? Formula 1? + +## What's `beer.db`? + +A free open public domain beer database n schema +for use in any (programming) language +(e.g. uses plain text fixtures/data sets). Example: + +~~~ +### Brewery + +guinness, St. James's Gate Brewery / Guinness Brewery, 1759, Dublin +~~~ + +~~~ +### Beer + +Guinness|Guinness Draught, 4.2%, irish_dry_stout|dry_stout|stout +~~~ + + +# Bonus: How to use HTTP JSON API - `GET /beer/guinness` + +Get beer by key `/beer/:key` + +~~~ +GET /beer/guinness + +{ + "beer": + { + "key":"guinness", + "title":"Guinness", + "synonyms": "Guinness Draught", + "abv":"4.2", + "srm":null, + "og":null, + "tags":["irish_dry_stout","dry_stout","stout"], + "brewery": + { + "key": "guinness", + "title": "St. James's Gate Brewery / Guinness Brewery" + }, + "country": + { + "key":"ie", + "title":"Irland" + } + } +} +~~~ diff --git a/open_data_world_cup_with_js.md b/open_data_world_cup_with_js.md new file mode 100644 index 0000000..036478c --- /dev/null +++ b/open_data_world_cup_with_js.md @@ -0,0 +1,838 @@ +title: Using Open Football Data - Get Ready for the World Cup in Brazil 2014 w/ JavaScript + +%css + +pre { + padding: 4px 4px 4px 4px; + border-top: #bbb 1px solid; + border-bottom: #bbb 1px solid; + background: #f3f3f3; +} + +%end + + + +# Using Open Football Data - Get Ready for the World Cup in Brazil 2014 w/ JavaScript + +### Agenda + +Let's Build A World Cup Widget in JavaScript + +- Part I: Basics + - World Cup in Brazil 2014 - The World's Biggest (Sport) Event + - Let's Use an HTTP JSON API + - What's `football.db?` + - What's Open Data? - Terms of Use + - Public Domain. No Rights Reserved. vs. © FIFA 2014. All Rights Reserved. + - What's Structured Data? + - Ex. FIFA - Free-Form Text vs. Structured Data + - Ex. Wikipedia - Free-Form Text vs. Structured Data + - Football Match Schedule Mini Language - New Structured Data Format Example +- Part II: Code, Code, Code + - Matchday Widget Example - `footballdb.widget.js` - v1.0 + - Matchday Widget Example - `footballdb.widget.js` - v2.0 + - Web Components Machinery - New Web Standard Building Blocks + - Matchday Widget Example - `` - v3.0 + + +# World Cup in Brazil 2014 - The World's Biggest (Sport) Event + +When: 12 June - 13 July; Starts in: + +## 43 days 3 hours 15 minutes + +What: + +## 32 teams 64 matches 25 matchdays 12 cities + +- 32 teams -- Australia, Iran, Japan, South Korea, + Algeria, Cameroon, Ghana, Ivory Coast, Nigeria, + Costa Rica, Honduras, Mexico, United States, + Argentina, Brazil, Chile, Colombia, Ecuador, + Uruguay, Belgium, Bosnia and Herzegovina, + Croatia, England, France, Germany, + Greece, Italy, Netherlands, Portugal, + Russia, Spain, Switzerland + +- 12 cities -- Rio de Janeiro, São Paulo, Brasília, Fortaleza, + Belo Horizonte, Porto Alegre, Salvador, Recife, + Cuiabá, Manaus, Natal, Curitiba + + +# Let's Build A World Cup Widget in JavaScript + +First let's use an HTTP JSON API. Example: + +~~~ +GET /event/world.2014/teams + +{ + "event": { + "key": "world.2014", "title": "World Cup 2014" + }, + "teams": [ + { "key": "gre", "title": "Greece", "code": "GRE" }, + { "key": "ned", "title": "Netherlands", "code": "NED" }, + { "key": "ger", "title": "Germany", "code": "GER" }, + { "key": "por", "title": "Portugal", "code": "POR" }, + ... + ] +} +~~~ + +Let's ask the intertubes (let's google [`json world cup brazil`](http://www.google.com/search?q=json+world+cup+brazil) +or post a question on the open data +stackexchange ['Any Open Data Sets for the (Football) World Cup (in Brazil 2014)?'](http://opendata.stackexchange.com/questions/1791/any-open-data-sets-for-the-football-world-cup-in-brazil-2014)). + +Nothing. Nada. Nichts. Niente. Zilch. Zero. + + + +# What's `football.db?` + +- Public domain football data sets offering free open football data +for the World Cup in Brazil 2014 and more. + +- Free self-hosted HTTP JSON API service for football data, for example: + - Step 1: Download the `worldcup2014.db` SQLite Database + - Step 2: Serve up teams, rounds, matches, etc. via HTTP JSON API using the + `sportdb` command line tool + +~~~ +$ sportdb serve +~~~ + +Services available include: + +- `/event/world.2014/teams` -- List all teams +- `/event/world.2014/rounds` -- List all rounds (matchdays) +- `/event/world.2014/round/20` -- List all matches in a round e.g. - 20th Round (=> Final) + +~~~ +GET /event/world.2014/round/1 + +{ + "event": { "key": "world.2014", "title": "World Cup 2014" }, + "round": { "pos": 1, "title": "Matchday 1" }, + "games": [ + { + "team1_key": "bra", + "team1_title": "Brazil", + "team1_code": "BRA", + "team2_key": "cro", + "team2_title": "Croatia", + "team2_code": "CRO", + "play_at": "2014/06/12", + "score1": null, + "score2": null, + "score1ot": null, + "score2ot": null, + "score1p": null, + "score2p": null + } + ] +} +~~~ + + +# Basics - What's Open Data? - Terms of Use + +Open (Free) Data <=> Copyright © FIFA 2014. All Rights Reserved. + +Example 1: + +- A Free One-Page Booklet (PDF) Download for the Match Schedule from [`fifa.com`](http://fifa.com/worldcup/matches). + - Copyright © FIFA 2014. All Rights Reserved. + +![](i/fifa-match-schedule-download.png) + + + +# Basics - What's Open Data? - Terms of Use (Cont.) + +Open (Free) Data <=> Copyright © FIFA 2014. All Rights Reserved. + +Example 2: + +- A Free SQLite DB Download for the Match Schedule from [`github.com/openfootball`](https://github.com/openfootball/build/releases). + - Public Domain (No Copyright. No License. No Rights Reserved.) + +![](i/worldcup2014-db-download.png) + +Q: Best "License" for Open Data? + +A: Public Domain¹ (No License. No Copyright. No Rights Reserved.) + +Q: Why? + +A: Keep it simple². + +\____________ +¹ Also sometimes "rebranded" or known as Creative Commons Zero (CC0) or Unlicense. +² Full "License" Text Example: The data, schema n scripts are dedicated to the public domain. Use it as you please with no restrictions whatsoever. + + +# Basics - What's Structured Data? Ex. FIFA Web Page + +Structured Data <=> Free-Style Text + +Example 1: + +- Match Schedule on FIFA Website + +![](i/fifa-match-schedule.png) + + + +# Basics - What's Structured Data? Ex. FIFA Web Page (Cont.) + +Structured Data <=> Free-Style Text + +Example 1: + +- Match Schedule on FIFA Website + - Show Source (Try Screen Scrapping Document Object Model Tree? Why? Why Not?) + +![](i/fifa-match-schedule-inside.png) + + + +# Basics - What's Structured Data? Ex. Wikipedia + +Structured Data <=> Free-Style Text + +Example 2: + +- Match Schedule on Wikipedia + +![](i/wikipedia-worldcup.png) + + + +# Basics - What's Structured Data? Ex. Wikipedia (Cont.) + +Structured Data <=> Free-Style Text + +Example 2: + +- Match Schedule on Wikipedia + - Show Source (Try Scrapping Free-Style Text? Why? Why Not?) + +Cut-n-Paste Text: + +~~~ +12 June 2014 17:00 Brazil Match 1 Croatia Arena de São Paulo, São Paulo +13 June 2014 13:00 Mexico Match 2 Cameroon Arena das Dunas, Natal +17 June 2014 16:00 Brazil Match 17 Mexico Estádio Castelão, Fortaleza +18 June 2014 19:00 Cameroon Match 18 Croatia Arena Amazônia, Manaus +23 June 2014 17:00 Cameroon Match 33 Brazil Estádio Nacional Mané Garrincha, Brasília +23 June 2014 17:00 Croatia Match 34 Mexico Arena Pernambuco, Recife +~~~ + +Wikipedia Source: + +~~~ +===Group A=== +{{{{main|2014 FIFA World Cup Group A}}}} +{{{{Fb cl2 header navbar}}}} +{{{{Fb cl2 team |t={{{{fb|BRA}}}} |w=0 |d=0 |l=0 |gf=0 |ga=0 |bc=}}}} +{{{{Fb cl2 team |t={{{{fb|CRO}}}} |w=0 |d=0 |l=0 |gf=0 |ga=0 |bc=|border=green}}}} +{{{{Fb cl2 team |t={{{{fb|MEX}}}} |w=0 |d=0 |l=0 |gf=0 |ga=0 |bc=}}}} +{{{{Fb cl2 team |t={{{{fb|CMR}}}} |w=0 |d=0 |l=0 |gf=0 |ga=0 |bc=}}}} +|} + +{{{{Football box +|date=12 June 2014 +|time=17:00 +|team1={{{{fb-rt|BRA}}}} +|score=[[2014 FIFA World Cup Group A#Brazil v Croatia|Match 1]] +|report= +|team2={{{{fb|CRO}}}} +|goals1= +|goals2= +|stadium=[[Arena Corinthians|Arena de São Paulo]], [[São Paulo]] +|attendance= +|referee= +}}}} +{{{{Football box +|date=13 June 2014 +|time=13:00 +|team1={{{{fb-rt|MEX}}}} +|score=[[2014 FIFA World Cup Group A#Mexico v Cameroon|Match 2]] +|report= +|team2={{{{fb|CMR}}}} +|goals1= +|goals2= +|stadium=[[Arena das Dunas]], [[Natal, Rio Grande do Norte|Natal]] +|attendance= +|referee= +}}}} +~~~ + + + +# Basics - What's Structured Data? - "Classic" Format Options + +Structured Data <=> Free-Style Text + +"Classic" Structured Data Formats: + +- JSON (Yeah!) +- CSV - Comma-Separated Values +- SQL +- XML +- YAML +- RDF Triplets +- and others + + + +# Basics - What's Structured Data? - "New" Format Options + +Structured Data <=> Free-Style Text + +but also + +"New" Structured Data Formats: + +- DSLs (Domain-Specific Languages), + - that is, Mini Languages for Structured Data + + +Example - Open Football Match Schedule Language: + +~~~ +(1) Thu Jun/12 17:00 Brazil - Croatia @ Arena de São Paulo, São Paulo (UTC-3) +(2) Fri Jun/13 13:00 Mexico - Cameroon @ Estádio das Dunas, Natal (UTC-3) +~~~ + +(Source: [world-cup/2014/cup.txt](https://github.com/openfootball/world-cup/blob/master/2014--brazil/cup.txt)) + +Q: Why? Why invent yet another data format? Why? + +A: Best of both worlds, that is, 1) looks n feels like free-form plain text - easy-to-read and +easy-to-write - 2) but offers a 100-% data accuracy guarantee (when loading +into SQL tables, for example). + + + +# Basics - What's Structured Data? - "New" Format Options + +Mini Languages for Structured Data + +Example - Open Football Match Schedule Language: + +~~~ +############################ +# World Cup 2014 Brazil + +Group A | Brazil Croatia Mexico Cameroon +Group B | Spain Netherlands Chile Australia +Group C | Colombia Greece Côte d'Ivoire Japan +Group D | Uruguay Costa Rica England Italy +Group E | Switzerland Ecuador France Honduras +Group F | Argentina Bosnia-Herzegovina Iran Nigeria +Group G | Germany Portugal Ghana United States +Group H | Belgium Algeria Russia South Korea + + +Matchday 1 | Thu Jun/12 +Matchday 2 | Fri Jun/13 +Matchday 3 | Sat Jun/14 +... + +(16) Round of 16 | Sat Jun/28 - Tue Jul/1 +(17) Quarter-finals | Fri Jul/4 - Sat Jul/5 +(18) Semi-finals | Tue Jul/8 - Wed Jul/9 +(19) Match for third place | Sat Jul/12 +(20) Final | Sun Jul/13 + + +Group A: + +(1) Thu Jun/12 17:00 Brazil - Croatia @ Arena de São Paulo, São Paulo (UTC-3) +(2) Fri Jun/13 13:00 Mexico - Cameroon @ Estádio das Dunas, Natal (UTC-3) + +(17) Tue Jun/17 16:00 Brazil - Mexico @ Estádio Castelão, Fortaleza (UTC-3) +(18) Wed Jun/18 18:00 Cameroon - Croatia @ Arena Amazônia, Manaus (UTC-4) + +(33) Mon Jun/23 17:00 Cameroon - Brazil @ Brasília (UTC-3) +(34) Mon Jun/23 17:00 Croatia - Mexico @ Recife (UTC-3) + + +Group B: + +(3) Fri Jun/13 16:00 Spain - Netherlands @ Arena Fonte Nova, Salvador (UTC-3) +(4) Fri Jun/13 18:00 Chile - Australia @ Arena Pantanal, Cuiabá (UTC-4) + +(19) Wed Jun/18 16:00 Spain - Chile @ Estádio do Maracanã, Rio de Janeiro (UTC-3) +(20) Wed Jun/18 13:00 Australia - Netherlands @ Estádio Beira-Rio, Porto Alegre (UTC-3) + +(35) Mon Jun/23 13:00 Australia - Spain @ Curitiba (UTC-3) +(36) Mon Jun/23 13:00 Netherlands - Chile @ São Paulo (UTC-3) +... +~~~ + +(Source: [world-cup/2014/cup.txt](https://github.com/openfootball/world-cup/blob/master/2014--brazil/cup.txt)) + + + +# More Basics - Terms of Use (Cont.) + +- Web 3.0, 4.0 <=> Web 1.0, 2.0 +- Giant Global Graph (GGG) <=> World Wide Web (WWW) +- Semantic Web <=> Linked Data +- Ontologies <=> Models n Schemas +- Taxonomies <=> Folksonomies +- RDF Triplet Stores <=> SQL DBs +- SPARQL Queries <=> SQL Queries +- Big Data <=> Micro Data + + +## Just Kidding. Let's Dive into Code. Code. Code. + + + +# Matchday Widget Example - `footballdb.widget.js` + +Use like: + +~~~ +
+ + +~~~ + +\_________________________ +¹ - selector id for div +² - event key for world cup in brazil 2014 +³ - round 2 (e.g. matchday 2); round 20 (e.g. final) + + +Results in: + +~~~ +World Cup 2014 - Matchday 2 + +2014/06/13 | Mexico (MEX) - Cameroon (CMR) +2014/06/13 | Spain (ESP) - Netherlands (NED) +2014/06/13 | Chile (CHI) - Australia (AUS) +~~~ + +(Live: [footballjs.github.io/starter](http://footballjs.github.io/starter/matchday.html)) + + + +# Matchday Widget Example - `footballdb.widget.js` - Source + +~~~ +var footballdb_widget_new = function( widget_id, api_path_prefix ) { + + var _api_path_prefix = ''; + var _$widget; + + function _init( widget_id, api_path_prefix ) + { + _api_path_prefix = api_path_prefix; + _$widget = $( widget_id ); + } + + function _update( event_key, round_pos ) + { + var api_link = _api_path_prefix + "/event/" + event_key + "/round/" + round_pos; + + $.getJSON( api_link, function(json) { + + var snippet = ""; // build up a hypertext (html) snippet to add/append + + snippet += "

"; + snippet += json.event.title; + snippet += " - "; + snippet += json.round.title; + snippet += "

"; + + snippet += ""; + + _$widget.html( snippet ); + }); // getJSON + } // fn _update + + // call c'tor/constructor + _init( widget_id, api_path_prefix ); + + // return/export public api + return { + update: _update + } + +} // fn football_widget_new +~~~ + +(Source: [github.com/footballjs/starter](https://github.com/footballjs/starter)) + + +# Matchday Widget Example - `footballdb.widget.js` - v2.0 + +- Let's use templates (w/ `underscore.js`) +- Let's use modules (w/ `require.js`) +- Let's use a `football.db` JSON API module / wrapper + + +# Matchday Widget Example - `footballdb.widget.js` - v2.0 - Templates + +`templates/events.html`: + +~~~ +

+ <%%= event.title %> + - + <%%= round.title %> +

+~~~ + +`templates/games.html`: + +~~~ + + <%% _.each( games, function( game, index ) { %> + + + + + + + + <%% }); %> +
+ <%%= game.play_at %> + + <%%= game.team1_title %> (<%%= game.team1_code %>) + + <%% if( game.score1 != null && game.score2 != null ) { %> + <%% if( game.score1ot != null && game.score2ot != null ) { %> + <%% if ( game.score1p != null && game.score2p != null ) { %> + <%%= game.score1p %> - <%%= game.score2p %> pen / + <%% } %> + <%%= game.score1ot %> - <%%= game.score2ot %> a.e.t. / + <%% } %> + <%%= game.score1 %> - <%%= game.score2 %> + <%% } else { %> + - + <%% } %> + + <%%= game.team2_title %> (<%%= game.team2_code %>) +
+~~~ + + +# Matchday Widget Example - `footballdb.widget.js` - v2.0 - Modules + +Modules w/ `require.js`: + +~~~ +football/api.js +football/widget.js +football/templates/event.html +football/templates/games.html +football/templates/rounds.html +~~~ + +Template Usage in JavaScript (w/ `require.js` and `underscore.js`): + +~~~ +var gamesTpl = require( 'text!football/templates/games.html' ); +var renderGames = _.template( gamesTpl ); // returns a fn for reuse +... +$games.html( renderGames( { games: data.games } ) ); +~~~ + + +`football/widget.js`: + +~~~ +define( function(require) { + + require( 'utils' ); + var Api = require( 'football/api' ); + + var eventTpl = require( 'text!football/templates/event.html' ), + roundsTpl = require( 'text!football/templates/rounds.html' ), + gamesTpl = require( 'text!football/templates/games.html' ); + + var renderEvent = _.template( eventTpl ), + renderRounds = _.template( roundsTpl ), + renderGames = _.template( gamesTpl ); + + var Widget = {}; + +Widget.create = function( id, opts ) { + + var $el, + $event, // used for event header + $rounds, // used for rounds + $games; // used for round details (matches/games) + ... +~~~ + + +# Matchday Widget Example - `footballdb.widget.js` - v2.0 - API Wrapper Module + +`football/api.js`: + +~~~ +define( function() { + + var Api = {}; + +Api.create = function( opts ) { + + var defaults = { baseUrl: 'http://footballdb.herokuapp.com/api/v1' }; + var settings; + + function init( opts ) { + settings = _.extend( {}, defaults, opts ); + } + + function fetch( path, onsuccess ) { + var url = settings.baseUrl + path + '?callback=?'; + $.getJSON( url, onsuccess ); + } + + function fetchRounds( event, onsuccess ) { + fetch( '/event/' + event + '/rounds', onsuccess ); + } + + function fetchRound( event, round, onsuccess ) { + fetch( '/event/' + event + '/round/' + round, onsuccess ); + } + + init( opts ); // call "c'tor/constructor" + + // return/export public api + return { + fetchRound: fetchRound, + fetchRounds: fetchRounds, + } +} // end fn Api.create + + return Api; + +}); // end define +~~~ + + + +# Matchday Widget Example - `` - v3.0 + +- Let's build our own tag / element / web component. Example: `` + +The old way in JavaScript. Usage Example: + +~~~ + + +
+ + +~~~ + +The new way: + +~~~ + + + +~~~ + + +# Web Components Machinery - New Web Standard Building Blocks + +What's X-Tag? What's Polymer? + +- **X-Tag** ([`x-tags.org`](http://www.x-tags.org))- JavaScript library by Mozilla - lets you use and build custom tags for all modern browsers +- **Polymer** ([`polymer-project.org`](http://www.polymer-project.org)) - JavaScript Library by Google - lets you use and build custom tags for all modern browsers + + +New Web Standard Building Blocks + +- **Custom Elements** -- (``) - [W3C Spec](http://www.w3.org/TR/custom-elements/) +- **Shadow DOM** -- (hide DOM subtrees under shadow roots - `createShadowRoot()`) - [W3C Spec](http://www.w3.org/TR/shadow-dom/) +- **HTML Imports** -- (include and reuse HTML documents) - [W3C Spec](http://www.w3.org/TR/html-imports/) +- **HTML Templates** -- (`