/** * Created by Owen Gannon (gannono2) for The Irish Times on 06/01/2015. * * This plugin is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License * http://creativecommons.org/licenses/by-sa/4.0/ */ (function($){ var baseUrl = "/cstatic/static/ni-election-data/"; var templateRoot = "/cstatic/static/ni-election/templates/"; var noResultsText = "Results Pending"; var totalSeats = 158; // By default, the total number of seats for 2016 is 158 var electionCode = "gen2016"; // The code of the election to query the api is gen2016 var totalConstituencies = 40; // By default, the total number of constituencies is 40 var constituencyLookup = []; var jsonName = "results.json"; // By default, the Ceann Comhairle is FG (2016) var ceannComhairle = { party: "FG", name: "Barrett, Seán", constituencyCode: "DLR" }; $.fn.extend({ initNational: function(options, callback){ // Error handling the options if (options.constituencyLookup === undefined || options.constituencyLookup === null) { return callback({err: true, msg: "ERR: The constituency lookup list must be specified in options."}); } constituencyLookup = options.constituencyLookup; if (options.totalConstituencies === undefined || options.totalConstituencies === null) { return callback({err: true, msg: "ERR: Total Constituencies must be specified in options."}); } totalConstituencies = options.totalConstituencies; if (options.totalSeats === undefined || options.totalSeats === null) { return callback({err: true, msg: "ERR: Total Seats must be specified in options."}); } totalSeats = options.totalSeats; if (options.electionCode === undefined || options.electionCode === null) { return callback({err: true, msg: "ERR: Election code must be specified in options."}); } if(!(options.jsonName === undefined || options.jsonName === null)) { jsonName = options.jsonName; } electionCode = options.electionCode; var ts = new Date().getTime(); //var url = "http://qa.irishtimes.com/cstatic/election-api/api/public/v1/elections/" //+ electionCode //+ "/nationalpage.js" //+ "?ts=" + ts; var url = baseUrl + jsonName + '?ts=' + ts; $.getJSON(url, function(json){ if(json["error_msg"]) { return callback({ err: true }); } // Assign the response properties to variables var results = []; var ioFirstPref = 0; var ioSeats = 0; var keys = Object.keys(json["parties"]); for(var i = 0; i < keys.length; i++){ var party = keys[i]; var colourClass = keys[i].toLowerCase(); if(party.toLowerCase() === "ind" || party.toLowerCase() === "oth") { ioFirstPref += json["parties"][keys[i]]["firstpreference"]; ioSeats += json["parties"][keys[i]]["seats"]; } else { results.push({ party: party, firstpreference: json["parties"][keys[i]]["firstpreference"], seats: json["parties"][keys[i]]["seats"], colourClass: colourClass }); } } results.sort(function(a, b){ return b.seats - a.seats; }); var indicators = { seatsFilled: json["seatsfilled"], constituenciesCompleted: json["constituenciescompleted"], firstPreferences: json["firstpreferencescompleted"], turnout: json["nationalTurnout"], showIndicator: json["countingUnderway"] }; return callback({ results: results, indicators: indicators, constituencies: json["constituencies"] }); }).fail(function(){ return {err: true }; }); }, nullState: function(element){ var $this = $(this); if(element === "spread"){ var spread = new EJS({url: templateRoot + 'national-spread.ejs'}).render({err: true, msg: noResultsText}); $this.empty().append(spread); } if(element === "legend"){ var legend = new EJS({url: templateRoot + 'national-legend.ejs'}).render({ err: true }); $this.empty().append(legend); } if(element === "indicators"){ var indicators = { constituenciesCompleted: 0, firstPreferences: 0, seatsFilled: 0, turnout: 0 }; var totals = { totalConstituencies: totalConstituencies, totalSeats: totalSeats }; var indicatorHtml = new EJS({url: templateRoot + 'national-indicators.ejs'}).render({ indicators: indicators, totals: totals }); $this.empty().append(indicatorHtml); } if(element === "cards"){ // Prepare the lookup data //for(var a = 0; a < constituencyLookup.length; a++){ //constituencyLookup[a].elected = []; //constituencyLookup[a].seatsfilled = 0; //constituencyLookup[a].totalseats = constituencyLookup[a].seats; //if(ceannComhairle.constituencyCode.toUpperCase() === constituencyLookup[a].code.toUpperCase()){ //constituencyLookup[a].seatsfilled++; //constituencyLookup[a].elected.push({ //name: ceannComhairle.name, //party: ceannComhairle.party, //firstpreference: "Ceann Comhairle" //}); //} //} var html = new EJS({url: templateRoot + 'national-cards.ejs'}).render({ constituencies: constituencyLookup, showIndicator: false, filtered: false }); $this.empty().append(html); $.fn.cardsToPanels(); } }, drawSpread: function(data){ var $this = $(this); //data.sort(function(a, b) { //return a.seats - b.seats; //}); var html = new EJS({url: templateRoot + 'national-spread.ejs'}).render({ err: false, data: data, totalSeats: totalSeats }); $this.empty().append(html); }, drawLegend: function(data){ var $this = $(this); var html = new EJS({url: templateRoot + 'national-legend.ejs'}).render({ err: false, data: data }); $this.empty().append(html); }, drawIndicators: function(data){ var $this = $(this); // Default var valid = data.constituencies !== undefined; var completed = data.indicators.constituenciesCompleted;//0; var seatsFilled = data.indicators.seatsFilled;//0; var indicators = { constituenciesCompleted: completed, firstPreferences: valid ? data.indicators.firstPreferences : 0, seatsFilled: seatsFilled, turnout: data.indicators.turnout }; var totals = { totalConstituencies: totalConstituencies, totalSeats: totalSeats }; var html = new EJS({url: templateRoot + 'national-indicators.ejs'}).render({ indicators: indicators, totals: totals }); $this.empty().append(html); }, drawCards: function(data){ //// Apply changes from API to master constituencies list var constituencies = data.constituencies; for(var x = 0; x < constituencies.length; x++){ var current = constituencies[x]; current.seatsfilled = current.seatsFilled; if(current.seats === undefined || current.seats === null){ current.totalseats = "6"; }else{ current.totalseats = current.seats; } } var $this = $(this); var html = new EJS({url: templateRoot + 'national-cards.ejs'}).render({ constituencies: data.constituencies, showIndicator: data.indicators.showIndicator,//data.indicators.firstPreferences > 0, filtered: false }); $this.empty().append(html); $.fn.cardsToPanels(); }, cardsToPanels: function(){ // Hiding the panel content. If JS is inactive, content will be displayed $( '.panel-content' ).hide(); // Preparing the DOM // -- Update the markup of accordion container $( '.accordion' ).attr({ role: 'tablist', multiselectable: 'true' }); // -- Adding ID, aria-labelled-by, role and aria-labelledby attributes to panel content $( '.panel-content' ).attr( 'id', function( IDcount ) { return 'panel-' + IDcount; }); $( '.panel-content' ).attr( 'aria-labelledby', function( IDcount ) { return 'control-panel-' + IDcount; }); $( '.panel-content' ).attr( 'aria-hidden' , 'true' ); // ---- Only for accordion, add role tabpanel $( '.accordion .panel-content' ).attr( 'role' , 'tabpanel' ); // -- Wrapping panel title content with a $( '.panel-title' ).each(function(i){ // ---- Need to identify the target, easy it's the immediate brother $target = $(this).next( '.panel-content' )[0].id; // ---- Creating the link with aria and link it to the panel content //if the count is still pendinging, do not allow panel link if($(this).first().attr('countStatus') == 'P'){ $link = $( '', { //'id' : 'control-' + $target }); } else { $link = $( '', { 'href': '#' + $target, 'aria-expanded': 'false', 'aria-controls': $target, 'id' : 'control-' + $target }); } // ---- Output the link $(this).wrapInner($link); }); // Optional : include an icon. Better in JS because without JS it have non-sense. $( '.panel-title a[aria-expanded="false"]' ).append(''); // Now we can play with it $( '.panel-title a[aria-expanded="false"]' ).click(function() { if ($(this).attr( 'aria-expanded' ) == 'false'){ //If aria expanded is false then it's not opened and we want it opened ! // -- Only for accordion effect (2 options) : comment or uncomment the one you want // ---- Option 1 : close only opened panel in the same accordion // search through the current Accordion container for opened panel and close it, remove class and change aria expanded value $(this).parents( '.accordion' ).find( '[aria-expanded=true]' ).attr( 'aria-expanded' , false ).removeClass( 'active' ).parent().next( '.panel-content' ).slideUp(200).attr( 'aria-hidden' , 'true'); // Option 2 : close all opened panels in all accordion container //$('.accordion .panel-title > a').attr('aria-expanded', false).removeClass('active').parent().next('.panel-content').slideUp(200); // Finally we open the panel, set class active for styling purpose on a and aria-expanded to "true" $(this).attr( 'aria-expanded' , true ).addClass( 'active' ).parent().next( '.panel-content' ).slideDown(200).attr( 'aria-hidden' , 'false'); } else { // The current panel is opened and we want to close it $(this).attr( 'aria-expanded' , false ).removeClass( 'active' ).parent().next( '.panel-content' ).slideUp(200).attr( 'aria-hidden' , 'true');; } return false; }); } }); })(jQuery);