/**
* 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 templateRoot = "/cstatic/static/general-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 = [];
// 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.ceannComhairle === undefined || options.ceannComhairle === null) {
return callback({err: true, msg: "ERR: The Ceann Comhairle's party code must be specified in options."});
}
ceannComhairle = options.ceannComhairle;
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."});
}
electionCode = options.electionCode;
var ts = new Date().getTime();
var url = "/cstatic/election-api/api/public/v1/elections/"
+ electionCode
+ "/nationalpage.js"
+ "?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
});
}
}
// Push the independents and others into the results list
results.push({
party: "IO",
firstpreference: ioFirstPref,
seats: ioSeats,
colourClass: "io"
});
results.sort(function(a, b){
return b.firstpreference - a.firstpreference;
});
// Start off with nothing...
var filled = 0;
// Loop through all the constituencies returned by the api
for(var j = 0; j < json.constituencies.length; j++){
// add up the seats filled in each constituency
filled += json.constituencies[j].seatsfilled;
}
var complete = 0;
for(var k = 0; k < json.constituencies.length; k++){
// add up the completed constituencies
if(json.constituencies[k].elected.length === json.constituencies[k].totalseats){
complete++;
}
}
var indicators = {
seatsFilled: filled+1, // Ceann Comhairle
constituenciesCompleted: complete,
firstPreferences: json["firstpreferencescompleted"]
};
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 === "spread-seats"){
var seatsFilled = 0;
var seatsSpread = new EJS({url: templateRoot + 'national-spread-seats.ejs'}).render({
err: true,
ceannComhairle: ceannComhairle,
msg: noResultsText,
totalSeats: seatsFilled,
maxSeats: totalSeats
});
$this.empty().append(seatsSpread);
}
if(element === "legend"){
var legend = new EJS({url: templateRoot + 'national-legend.ejs'}).render({
err: true,
ceannComhairle: ceannComhairle
});
$this.empty().append(legend);
}
if(element === "indicators"){
var indicators = {
constituenciesCompleted: 0,
firstPreferences: 0,
seatsFilled: 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);
var html = new EJS({url: templateRoot + 'national-spread.ejs'}).render({
err: false,
data: data,
ceannComhairle: ceannComhairle
});
$this.empty().append(html);
},
drawSpreadSeats: function(data){
var $this = $(this);
var seatsFilled = 0;
for(var i = 0; i < data.results.length; i++){
seatsFilled += data.results[i].seats;
}
data.results.sort(function(a, b){
return b.seats - a.seats;
});
var html = new EJS({url: templateRoot + 'national-spread-seats.ejs'}).render({
err: false,
data: data,
ceannComhairle: ceannComhairle,
seatsFilled: seatsFilled,
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,
ceannComhairle: ceannComhairle
});
$this.empty().append(html);
},
drawLegendSeats: function(data){
var $this = $(this);
var seatsFilled = 0;
for(var i = 0; i < data.results.length; i++){
seatsFilled += data.results[i].seats;
}
data.results.sort(function(a, b){
return b.seats - a.seats;
});
var html = new EJS({url: templateRoot + 'national-legend-seats.ejs'}).render({
err: false,
data: data,
ceannComhairle: ceannComhairle,
seatsFilled: seatsFilled,
totalSeats: totalSeats
});
$this.empty().append(html);
},
drawIndicators: function(data){
var $this = $(this);
// Default
var valid = data.constituencies !== undefined;
var indicators = {
constituenciesCompleted: valid ? data.indicators.constituenciesCompleted : 0,
firstPreferences: valid ? data.indicators.firstPreferences: 0,
seatsFilled: valid ? data.indicators.seatsFilled : 1
};
var totals = {
totalConstituencies: totalConstituencies,
totalSeats: totalSeats
};
var html = new EJS({url: templateRoot + 'national-indicators.ejs'}).render({
indicators: indicators,
totals: totals
});
$this.empty().append(html);
},
drawFilters: function(callback){
var $this = $(this);
var html = new EJS({url: templateRoot + 'national-cards-filters.ejs'}).render();
$this.empty().append(html);
return callback();
},
drawCards: function(data){
// 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"
});
}
}
// Apply changes from API to master constituencies list
if(data.constituencies !== undefined){
var constituencies = data.constituencies;
for(var x = 0; x < constituencies.length; x++){
var current = constituencies[x];
// Find the current constituency in the lookup
for(var y = 0; y < constituencyLookup.length; y++){
var normalCurrentName = current.name.replace(/\s+/g, '-').toLowerCase();
var normalLookupName = constituencyLookup[y].name.replace(/\s+/g, '-').toLowerCase();
if(normalCurrentName === normalLookupName){
// Found it... apply the changes
constituencyLookup[y].seatsfilled += current.seatsfilled;
constituencyLookup[y].totalSeats = constituencyLookup[y].seats;
if(current.elected.length > 0){
for(var z = 0; z < current.elected.length; z++){
constituencyLookup[y].elected.push(current.elected[z]);
}
}
}
}
}
}
var $this = $(this);
var html = new EJS({url: templateRoot + 'national-cards.ejs'}).render({
constituencies: constituencyLookup,
showIndicator: data.indicators === undefined ? false : data.indicators.firstPreferences > 0,
filtered: false
});
$this.empty().append(html);
$.fn.cardsToPanels();
},
redrawCards: function(data, region){
var $this = $(this);
// Get rid of all the cards...
$(".national-view-card").remove();
if(region !== "*") {
// show only the region selected
region = region.replace(".", "");
var filteredConstituencies = [];
for (var i = 0; i < constituencyLookup.length; i++) {
if (constituencyLookup[i].region.toLowerCase() === region) {
filteredConstituencies.push(constituencyLookup[i]);
}
}
// Prepare the lookup data
for(var a = 0; a < filteredConstituencies.length; a++){
filteredConstituencies[a].elected = [];
filteredConstituencies[a].seatsfilled = 0;
filteredConstituencies[a].totalseats = filteredConstituencies[a].seats;
if(ceannComhairle.constituencyCode.toUpperCase() === filteredConstituencies[a].code.toUpperCase()){
filteredConstituencies[a].seatsfilled++;
filteredConstituencies[a].elected.push({
name: ceannComhairle.name,
party: ceannComhairle.party,
firstpreference: "Ceann Comhairle"
});
}
}
// Apply changes from API to master constituencies list
if(data.constituencies !== undefined) {
var constituencies = data.constituencies;
for (var x = 0; x < constituencies.length; x++) {
var current = constituencies[x];
// We only want constituencies in the desired filter
if(current.region.toLowerCase() !== filteredConstituencies[0].region.toLowerCase()){
continue;
}
// Find the current constituency in the lookup
for (var y = 0; y < filteredConstituencies.length; y++) {
var normalCurrentName = current.name.replace(/\s+/g, '-').toLowerCase();
var normalLookupName = filteredConstituencies[y].name.replace(/\s+/g, '-').toLowerCase();
if(normalCurrentName === normalLookupName){
// Found it... apply the changes
filteredConstituencies[y].seatsfilled += current.seatsfilled;
filteredConstituencies[y].totalSeats = filteredConstituencies[y].seats;
if (current.elected.length > 0) {
for (var z = 0; z < current.elected.length; z++) {
filteredConstituencies[y].elected.push(current.elected[z]);
}
}
}
}
}
}
var html = new EJS({url: templateRoot + 'national-cards.ejs'}).render({
constituencies: filteredConstituencies,
showIndicator: data.indicators === undefined ? false : data.indicators.firstPreferences > 0,
filtered: true
});
$this.empty().append(html);
$.fn.cardsToPanels();
} else {
$this.empty();
$this.drawCards(data);
}
},
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
$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' ).append('');
// Now we can play with it
$( '.panel-title a' ).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);