Skip to content

Instantly share code, notes, and snippets.

@dmann
Last active January 9, 2019 15:56
Show Gist options
  • Save dmann/23ccb7cbb2518e57b20dbd6fe0f743b1 to your computer and use it in GitHub Desktop.
Save dmann/23ccb7cbb2518e57b20dbd6fe0f743b1 to your computer and use it in GitHub Desktop.
A bookmarklet that compiles steps and minutes active into a single table, which can be to copy/pasted directly into Duke's Get Moving Challenge submission page.

Installation

Copy the raw text from the get_moving_bookmarklet.min.js file. Open the Bookmark Manager in your web browser. Add a new bookmark and paste the minified javascript into the url field.

Usage

Go to the Fitbit website and log in. Once logged in, click your newly created bookmark and a table should show up at the top of the page. While the bookmarklet will work from any page on Fitbit's site, I've found that it looks best when launched from the Food Log page.

Resources

javascript:(function()%7Bvar%20t%3Ddocument.createElement(%22table%22)%2Cheadings%3D%5B%22Get%20Moving!%22%2C%22Steps%22%2C%22Minutes%20Exercised%22%2C%22Very%20Active%22%2C%22Moderately%20Active%22%2C%22Lightly%20Active%22%5D%2Ct_html%3D%22%3Cthead%3E%3Ctr%3E%3Cth%3E%22%2Bheadings.join(%22%3C%2Fth%3E%3Cth%3E%22)%2B%22%3C%2Fth%3E%3C%2Ftr%3E%3C%2Fthead%3E%22%2CstartDate%3Dnew%20Date(2019%2C0%2C7)%2CendDate%3Dnew%20Date%3BendDate.setHours(0)%3Bfor(var%20i%3D0%3Bi%3C70%3Bi%2B%2B)%7Bvar%20curDate%3Dnew%20Date(startDate)%3BcurDate.setDate(startDate.getDate()%2Bi)%3Bvar%20iso%3DcurDate.toISOString().split(%22T%22)%5B0%5D%2Ctds%3DArray(headings.length)%3Btds%5B0%5D%3Diso%2Ci%257%3D%3D0%26%26(t_html%3Dt_html%2B'%3Ctr%3E%3Ctd%20colspan%3D%22'%2Bheadings.length%2B'%22%3EWeek%20'%2B(i%2B7)%2F7%2B%22%3C%2Ftd%3E%3C%2Ftr%3E%22)%2Ct_html%3Dt_html%2B'%3Ctr%20id%3D%22get_moving_'%2Biso%2B'%22%3E%3Ctd%3E'%2Btds.join(%22%3C%2Ftd%3E%3Ctd%3E%22)%2B%22%3C%2Ftd%3E%3C%2Ftr%3E%22%7Dt.innerHTML%3Dt_html%2Cdocument.body.prepend(t)%3Bvar%20dataUrl%3D%22https%3A%2F%2Fwww.fitbit.com%2Fgraph%2FgetNewGraphData%3FapiFormat%3Djson%22%2CstepsUrl%3DdataUrl%2B%22%26type%3Dsteps%26dateFrom%3D%22%2BstartDate.toISOString().split(%22T%22)%5B0%5D%2B%22%26dateTo%3D%22%2BendDate.toISOString().split(%22T%22)%5B0%5D%2CactivityUrl%3DdataUrl%2B%22%26type%3DintradayCaloriesBurned%22%2CxhrCall%3Dfunction(t%2Ce)%7Bvar%20a%3Dnew%20XMLHttpRequest%3Ba.onreadystatechange%3Dfunction()%7Ba.readyState%3D%3DXMLHttpRequest.DONE%26%26e(JSON.parse(a.responseText))%7D%2Ca.open(%22GET%22%2Ct)%2Ca.send()%7D%2CpopulateDay%3Dfunction(t)%7Bvar%20e%3Dnew%20Date(t.dateTime.split(%22%20%22)%5B0%5D).toISOString().split(%22T%22)%5B0%5D%2Ci%3Ddocument.getElementById(%22get_moving_%22%2Be).children%3Bi%5B1%5D.innerText%3Dt.value%2CxhrCall(activityUrl%2B%22%26dateFrom%3D%22%2Be%2B%22%26dateTo%3D%22%2Be%2Cfunction(t)%7Bfor(var%20e%3Dt.graph.dataSets.activity.dataPoints%2Ca%3D%7B%7D%2Cr%3D0%3Br%3Ce.length%3Br%2B%2B)%7Bvar%20n%3De%5Br%5D.activityLevel%3Ba%5Bn%5D%7C%7C(a%5Bn%5D%3D0)%2Ca%5Bn%5D%3Da%5Bn%5D%2B5%7Di%5B2%5D.innerText%3D(a.VERY_ACTIVE%7C%7C0)%2B(a.MODERATELY_ACTIVE%7C%7C0)%2Ci%5B3%5D.innerText%3Da.VERY_ACTIVE%7C%7C%22%22%2Ci%5B4%5D.innerText%3Da.MODERATELY_ACTIVE%7C%7C%22%22%2Ci%5B5%5D.innerText%3Da.LIGHTLY_ACTIVE%7C%7C%22%22%7D)%7D%3BxhrCall(stepsUrl%2Cfunction(t)%7Bfor(var%20e%3Dt.graph.dataSets.activity.dataPoints%2Ca%3D0%3Ba%3Ce.length%3Ba%2B%2B)populateDay(e%5Ba%5D)%7D)%7D)()
var t = document.createElement('table');
var headings = ['Get Moving!','Steps','Minutes Exercised','Very Active','Moderately Active','Lightly Active'];
var t_html = '<thead><tr><th>' + headings.join('</th><th>') + '</th></tr></thead>';
var startDate = new Date(2019, 0, 7);
var endDate = new Date();
endDate.setHours(0);
for ( var i=0; i<70; i++) {
var curDate = new Date(startDate);
curDate.setDate(startDate.getDate() + i);
var iso = curDate.toISOString().split('T')[0];
var tds = Array(headings.length);
tds[0] = iso;
if ( i%7 == 0 ) {
t_html = t_html + '<tr><td colspan="'+headings.length+'">Week '+ ((i+7)/7) +'</td></tr>';
}
t_html = t_html + '<tr id="get_moving_'+iso+'"><td>' +
tds.join('</td><td>') + '</td></tr>';
}
t.innerHTML = t_html;
document.body.prepend(t);
var dataUrl = "https://www.fitbit.com/graph/getNewGraphData?apiFormat=json";
var stepsUrl = dataUrl + '&type=steps&dateFrom=' +
startDate.toISOString().split('T')[0] +
'&dateTo=' + endDate.toISOString().split('T')[0];
var activityUrl = dataUrl + '&type=intradayCaloriesBurned';
var xhrCall = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
callback(JSON.parse(xhr.responseText));
}
}
xhr.open('GET', url);
xhr.send();
}
var populateDay = function(day){
var stepsDate = new Date(day.dateTime.split(' ')[0]);
var iso = stepsDate.toISOString().split('T')[0];
var row = document.getElementById('get_moving_' + iso).children;
row[1].innerText = day.value;
xhrCall(activityUrl + '&dateFrom=' + iso + '&dateTo=' + iso, function(data) {
var activities = data.graph.dataSets.activity.dataPoints;
var levelSum = {};
for ( var i=0; i<activities.length; i++ ) {
var level = activities[i].activityLevel;
if ( !levelSum[level] ) {
levelSum[level] = 0;
}
levelSum[level] = levelSum[level] + 5;
}
row[2].innerText = (levelSum.VERY_ACTIVE || 0)+(levelSum.MODERATELY_ACTIVE || 0);
row[3].innerText = levelSum.VERY_ACTIVE || '';
row[4].innerText = levelSum.MODERATELY_ACTIVE || '';
row[5].innerText = levelSum.LIGHTLY_ACTIVE || '';
});
}
xhrCall(stepsUrl, function(data) {
var days = data.graph.dataSets.activity.dataPoints;
for ( var i=0; i<days.length; i++) {
populateDay(days[i]);
}
});
@dmlond
Copy link

dmlond commented Jan 17, 2017

WOW! Thanks so much @dmann. You sure are a responsive developer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment