/** * Created by Owen Gannon (https://github.com/gannono2) for The Irish Times on 04/01/2016. * * 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/file-assets/events/elections/templates/"; var noResultsText = "Results Pending"; var opts = {}; var timeStamp = "?rev=" + new Date().getTime(); var nullStateParties = []; $.fn.extend({ // Hit the API for the constituency results... initConstituency: function(options, callback) { if (options.seats == 'undefined' || options.seats == null) { return callback({ err: true, msg: "ERR: Number of seats must be specified in options." }); } opts.seats = options.seats; if (options.constituencyCode == 'undefined' || options.constituencyCode == null) { return callback({ err: true, msg: "ERR: Constituency code must be specified in options." }); } opts.constituencyCode = options.constituencyCode; if (options.electionCode == 'undefined' || options.electionCode == null) { return callback({ err: true, msg: "ERR: Election code must be specified in options." }); } opts.electionCode = options.electionCode; if (options.ceannComhairle === undefined || options.ceannComhairle === null) { return callback({ err: true, msg: "ERR: The Ceann Comhairle must be specified in options." }); } opts.ceannComhairle = options.ceannComhairle; nullStateParties = typeof options.nullStateParties !== 'undefined' ? options.nullStateParties : []; var ts = new Date().getTime(); var url = "/cstatic/election-api/api/public/v1/elections/" + options.electionCode + "/constituencies/" + options.constituencyCode + "/fulldata.js" + "?ts=" + ts; $.getJSON(url, function(json) { if (json["error_msg"]) { return callback({ err: true }); } if (json['filled'] === undefined && json['meta'].seats === undefined) { return callback({ err: true, msg: "Constituency not complete yet.", counts: json['countresults'] }); } var voteShare = json['voteShare']; var totalValidPoll = json['meta']['totalvalidpoll']; var data = {}; data.results = []; for (var i = 0; i < voteShare.length; i++) { // IO is grouped on the API side, no need to group again if (voteShare[i].party.toLowerCase() === "ind" || voteShare[i].party.toLowerCase() === "oth") { continue; } // Only use parties that have a valid number of votes attached to them if (voteShare[i].votes === undefined || voteShare[i].votes === null) { continue; } var obj = { party: voteShare[i].party, votes: voteShare[i].votes, percentage: ((voteShare[i].votes / totalValidPoll) * 100), colourClass: voteShare[i].party.toLowerCase() }; data.results.push(obj); } data.results.sort(function(a, b) { return b.votes - a.votes; }); data.meta = json["meta"]; data.firstPreferenceCompleted = (json["countresults"].length > 0); data.seatsFilled = json["filled"]; data.counts = []; for (var x = 0; x < json["countresults"].length; x++) { data.counts.push([]); var keys = Object.keys(json["countresults"][x]); for (var y = 0; y < keys.length; y++) { if (keys[y] === y.toString()) { data.counts[x].push(json["countresults"][x][y]); } } } data.eliminated = []; data.notElected = []; var candidate = null; if (data.counts.length !== 0) { for (var a = 0; a < data.counts.length; a++) { for (var b = 0; b < data.counts[a].length; b++) { if (data.counts[a][b].elected === 1) { for (var l = 0; l < data.counts[0].length; l++) { candidate = data.counts[a][b]; if (data.counts[0][l].name === candidate.name) { data.counts[0][l].status = "elected"; } } } else if (data.counts[a][b].eliminated === 1) { candidate = data.counts[a][b]; candidate.count = a + 1; data.eliminated.push(candidate); for (var m = 0; m < data.counts[0].length; m++) { if (data.counts[0][m].name === candidate.name) { data.counts[0][m].status = "eliminated"; } } } else if (a === data.counts.length - 1) { if (data.counts[a][b].elected === 0 && data.counts[a][b].eliminated === 0) { candidate = data.counts[a][b]; candidate.count = a + 1; data.notElected.push(candidate); for (var n = 0; n < data.counts[0].length; n++) { if (data.counts[0][n].name === candidate.name) { data.counts[0][n].status = "notElected"; } } } } } } } else { return callback({ err: true, counts: json['countresults'] }); } data.meta.status = data.seatsFilled.length == data.meta.seats ? "Complete" : "Incomplete"; return callback(data); }).fail(function() { return { err: true }; }); }, nullState: function(element) { var $this = $(this); if (element === "spread") { var filled = 0; if (opts.constituencyCode.toUpperCase() === opts.ceannComhairle.constituencyCode.toUpperCase()) { filled++; } var spread = new EJS({ url: templateRoot + 'constituency-spread.ejs' + timeStamp }).render({ err: true, msg: noResultsText, seatsfilled: filled, totalseats: opts.seats }); $this.empty().append(spread); } if (element === "legend") { var ceannComhairleConstituency = opts.constituencyCode.toUpperCase() === opts.ceannComhairle.constituencyCode.toUpperCase(); var legend = new EJS({ url: templateRoot + 'constituency-legend.ejs' + timeStamp }).render({ err: true, ceannComhairleConstituency: ceannComhairleConstituency, nullStateParties: nullStateParties }); $this.empty().append(legend); } if (element === "meta") { var meta = new EJS({ url: templateRoot + 'constituency-meta.ejs' + timeStamp }).render({ err: true, meta: { code: opts.constituencyCode, seatsFilled: opts.seats }, ceannComhairle: opts.ceannComhairle }); $this.empty().append(meta); } }, nullStateTable: function(data, callback) { var $this = $(this); var container = {}; var counts = []; var count = []; for (var x = 0; x < data.counts.length; x++) { if (data.counts[x].constructor === Array) { count.push(data.counts[x][0]); } else { count.push(data.counts[x][Object.keys(data.counts[x])[0]]); } } counts.push(count); container.counts = counts; var table = new EJS({ url: templateRoot + 'constituency-count-table.ejs' + timeStamp }).render({ err: true, constituency: container }); $this.empty().append(table); return callback(); }, drawSpread: function(data) { var $this = $(this); var filled = data.seatsFilled.length; if (data.meta.code.toUpperCase() === opts.ceannComhairle.constituencyCode.toUpperCase()) { filled++; } var html = new EJS({ url: templateRoot + 'constituency-spread.ejs' + timeStamp }).render({ err: false, data: data, seatsfilled: filled, totalseats: opts.seats }); $this.empty().append(html); }, drawMeta: function(data) { var $this = $(this); var meta = data.meta; meta.seatsFilled = data.seatsFilled; var html = new EJS({ url: templateRoot + 'constituency-meta.ejs' + timeStamp }).render({ err: false, meta: meta, ceannComhairle: opts.ceannComhairle }); $this.empty().append(html); }, drawCountTable: function(data, callback) { var $this = $(this); if (data.counts.length !== 0) { data.counts[0].sort(function(a, b) { return (b["votes"] > a["votes"]) ? 1 : ((b["votes"] < a["votes"]) ? -1 : 0); }); } var html = new EJS({ url: templateRoot + 'constituency-count-table.ejs' + timeStamp }).render({ err: false, constituency: data }); $this.empty().append(html); return callback(); }, drawLegend: function(data) { var $this = $(this); var ceannComhairleConstituency = opts.constituencyCode.toUpperCase() === opts.ceannComhairle.constituencyCode.toUpperCase(); var html = new EJS({ url: templateRoot + 'constituency-legend.ejs' + timeStamp }).render({ err: false, data: data, ceannComhairleConstituency: ceannComhairleConstituency, nullStateParties: nullStateParties }); $this.empty().append(html); } }); })(jQuery);