Skip to content

Commit

Permalink
0.2.0: move 538 controller to separate file, add badge count, add per…
Browse files Browse the repository at this point in the history
…iodic polling, better UI, add Makefile
  • Loading branch information
janssenivo committed Sep 17, 2018
1 parent 1a75126 commit 83bc132
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 73 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
all:
rm *.zip
zip -r dist.zip *

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# FiveThirtyEight forecast extension

* Install this extension in your Chrome browser
* Will retrieve data from FiveThirtyEight project to display congressional races right in your browser
* Install this extension in your Chrome browser ([direct link](https://chrome.google.com/webstore/detail/fivethirtyeight-forecasts/kofogmkpefhpkmoafcmpgmakekmgcnlh))
* Will retrieve data from FiveThirtyEight project to display 2018 congressional forecasts right in your browser


## Author
* Ivo Janssen <[email protected]>
* Ivo Janssen <<[email protected]>>

## License
* Distributed under [CC-By 3.0 license](https://creativecommons.org/licenses/by/3.0/)
Expand Down
30 changes: 28 additions & 2 deletions background.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
// will run on startup
// - initializes local storage
// - periodically update the badge icon every 3 hours

// initialization
chrome.runtime.onInstalled.addListener(function() {
chrome.browserAction.setBadgeBackgroundColor({ color: [0, 0, 255, 255] });
chrome.browserAction.setBadgeText({text: ''});
chrome.storage.local.get("model", function(result) {
if (result === undefined || result.model === undefined) {
chrome.storage.local.set({model: "deluxe"}, function() {
console.log("Initializing: model is now set to deluxe. Nate can sleep");
chrome.storage.local.set({model: "classic"}, function() {
console.log("Initializing: model is now set to classic. Nate can sleep");
});
} else {
console.log("Model currently is " + result.model);
}
getForecast(function(stats) {
chrome.browserAction.setBadgeText({text: stats.badgeprob});
});
});
});

// set alarm to update badge icon every 3 hours
var checkInterval = 180; // minutes
chrome.alarms.create("checkServer", {
delayInMinutes: 1,
periodInMinutes: checkInterval
});

chrome.alarms.onAlarm.addListener(function(alarm) {
if (alarm.name === "checkServer") {
console.log(Date.now()+" updating badge icon periodically");
getForecast(function(stats) {
chrome.browserAction.setBadgeText({text: stats.badgeprob});
});
}
});
32 changes: 32 additions & 0 deletions fivethirtyeight.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// reaches out to projects.fivethirtyeight.com for latest model stats

const getForecast = function (cb) {

chrome.storage.local.get("model", function (result) {
let model = result.model;
console.log("getting data for " + model);

// house forecast
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://projects.fivethirtyeight.com/2018-midterm-election-forecast/house/home.json", true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
let resp = JSON.parse(xhr.responseText);
let stats = resp.nationalTrends;
let rv = {
model: model,
date: stats[0].date,
party1: stats[0].candidate,
party2: stats[1].candidate,
winprob1: parseFloat((stats[0].models[model].winprob)).toFixed(1),
winprob2: parseFloat((stats[1].models[model].winprob)).toFixed(1),
badgeprob: ""+Math.round(stats[0].models[model].winprob)
}
console.log(rv);
return cb(rv);
}
}
xhr.send();
});

}
Binary file modified images/fivethirtyeight-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 25 additions & 25 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
{
"name": "Fivethirtyeight forecasts",
"version": "0.1",
"description": "Chrome extension that displays the 2018 House and Senate forecasts in your browser",
"manifest_version": 2,
"permissions": ["https://projects.fivethirtyeight.com/","activeTab", "storage"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_title": "Fivethirtyeight forecast",
"default_popup": "popup.html",
"default_icon": "images/fivethirtyeight-logo.png"
},
"options_ui": {
"page": "options.html",
"open_in_tab": false
},
"icons": {
"16": "images/fivethirtyeight-logo.png",
"32": "images/fivethirtyeight-logo.png",
"48": "images/fivethirtyeight-logo.png",
"128": "images/fivethirtyeight-logo.png"
}
}
"name": "Fivethirtyeight forecasts",
"version": "0.2.0",
"description": "Chrome extension that displays the 2018 House and Senate forecasts in your browser",
"manifest_version": 2,
"permissions": ["storage", "alarms"],
"background": {
"scripts": ["background.js", "fivethirtyeight.js"],
"persistent": false
},
"browser_action": {
"default_title": "Fivethirtyeight forecast",
"default_popup": "popup.html",
"default_icon": "images/fivethirtyeight-logo.png"
},
"options_ui": {
"page": "options.html",
"open_in_tab": false
},
"icons": {
"16": "images/fivethirtyeight-logo.png",
"32": "images/fivethirtyeight-logo.png",
"48": "images/fivethirtyeight-logo.png",
"128": "images/fivethirtyeight-logo.png"
}
}
7 changes: 4 additions & 3 deletions options.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<style>
button {
height: 30px;
width: 100px;
outline: none;
width: 80px;
outline: 2px;
margin: 10px;
}
</style>
Expand All @@ -15,5 +15,6 @@
<div id="buttonDiv">
</div>
</body>
<script src="options.js"></script>
<script src="fivethirtyeight.js"></script>
<script src="options.js"></script>
</html>
40 changes: 22 additions & 18 deletions options.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
let page = document.getElementById('buttonDiv');
let curModel = "";
chrome.storage.local.get("model", function(result) {
curModel = result.model;
console.log(curModel);
const kButtonModels = ['lite', 'classic', 'deluxe'];
function constructOptions(kButtonModels) {
curModel = result.model;
console.log(curModel);
const kButtonModels = ['lite', 'classic', 'deluxe'];
function constructOptions(kButtonModels) {
for (let item of kButtonModels) {
let button = document.createElement('button');
button.textContent = item;
if (curModel === item) {
button.style.backgroundColor = "#ff0000";
}
button.addEventListener('click', function() {
button.style.backgroundColor = "#ffff00";
chrome.storage.local.set({model: item}, function() {
console.log('forecast is ' + item);
});
let button = document.createElement('button');
button.textContent = item;
if (curModel === item) {
button.style.backgroundColor = "#006cf9";
}
button.addEventListener('click', function() {
button.style.backgroundColor = "#f99500";
chrome.storage.local.set({model: item}, function() {
console.log('forecast is ' + item);
getForecast(function(stats) {
chrome.browserAction.setBadgeText({text: stats.badgeprob});
window.close();
});
});
page.appendChild(button);
});
page.appendChild(button);
}
}
constructOptions(kButtonModels);
});
}
constructOptions(kButtonModels);
});
9 changes: 7 additions & 2 deletions popup.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<script src="fivethirtyeight.js"></script>
<script src="popup.js"></script>
</head>
<body>
<p id="stats">Loading...</p>
<body style="width: 500px">
<p>
<img src="images/fivethirtyeight-logo.png" width="32" height="32" style="float:left">
<h2><a href="https://projects.fivethirtyeight.com/2018-midterm-election-forecast/house/">FiveThirtyEight 2018 forecast</a></h2>
</p>
<p id="stats">loading...</p>
</body>
</html>
32 changes: 12 additions & 20 deletions popup.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
let model = "";
chrome.storage.local.get("model", function(result) {
model = result.model;
console.log("getting data for "+model);
// fires when the extension icon is clicked
// will display the forecast text and update the icon

var xhr = new XMLHttpRequest();
xhr.open("GET", "https://projects.fivethirtyeight.com/2018-midterm-election-forecast/house/home.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
var resp = JSON.parse(xhr.responseText);
let date = resp.nationalTrends[0].date;
let party1 = resp.nationalTrends[0].candidate;
let party2 = resp.nationalTrends[1].candidate;
let winprob1 = resp.nationalTrends[0].models[model].winprob;
let winprob2 = resp.nationalTrends[1].models[model].winprob;
let textBox = document.getElementById('stats');
window.addEventListener('click',function(e){
if(e.target.href!==undefined){
chrome.tabs.create({url:e.target.href})
}
})

let out = "In the "+model+" model, "+party1+" have a chance of "+Math.round(winprob1)+"% to take back the House";
textBox.textContent = out;
}
}
xhr.send();
getForecast(function(stats) {
let textBox = document.getElementById('stats');
let out = "<i>Nate says:</i> in the <b>"+stats.model+"</b> model, "+stats.party1+" have a chance of <b>"+stats.winprob1+"%</b> to take back the House";
textBox.innerHTML = out;
chrome.browserAction.setBadgeText({text: stats.badgeprob});
});

0 comments on commit 83bc132

Please sign in to comment.