Skip to content

Instantly share code, notes, and snippets.

@alanmclean
Last active December 23, 2015 09:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alanmclean/6612248 to your computer and use it in GitHub Desktop.
Save alanmclean/6612248 to your computer and use it in GitHub Desktop.
Prototype
// ##Requires:
// ### jQuery.js
var Ink = (typeof Ink === 'undefined') ? {} : Ink;
Ink.Fixie = function ( el, options ) {
this.$ = window.jQuery || window.$;
this.offsetX = 0;
this.offsetY = 0;
this.preventReflow = false;
this.fixieClassName = 'ink-fixie';
this.fixedClassName = 'ink-is-fixed';
this.isFixed = false;
// should the element stick to the inside of its container
this.constrainToContainer = true;
// random token for namespacing events
this.token = Math.round(Math.random() * 100000);
this.isMobile = ('ontouchstart' in window);
if ( arguments.length > 1 ) {
this.$.extend(this, options);
}
this.$el = this.$(el);
if (this.$el.length > 1) {
throw 'You can only instantiate one fixie at a time';
return;
}
this.$window = this.$(window);
this.$container = ('container' in options) ? this.$(this.container) : this.$el.parent();
this.init();
return this;
};
Ink.Fixie.prototype = {
init : function(){
this.establishLayout();
if ( this.isMobile === true ) {
this.$window.bind('orientationchange.'+this.token, this.$.proxy(this.onReflow, this));
}
this.$window.bind('resize.'+this.token, this.$.proxy(this.onReflow,this));
this.$window.bind('scroll.'+this.token, this.$.proxy(this.evaluate,this));
this.$el.addClass(this.fixieClassName);
return this;
},
// establish page and element dimensions, positions for viewport fixing
establishLayout: function(){
var left, right;
this.containerHeight = this.$container.height();
this.scrollTop = this.$el.offset().top;
this.originalPosition = this.$el.css('position');
this.originalTop = this.$el.css('top');
left = this.$el.css('left');
this.originalLeft = (left === 'auto') ? false : left;
right = this.$el.css('right');
this.originalRight = (right === 'auto') ? false : right;
this.elHeight = this.$el.height();
return this;
},
// Triggered during page reflows to be sure everything is calculated correctly should the page change
onReflow: function(){
this.containerHeight = this.$container.height();
this.scrollTop = this.$el.offset().top;
this.elHeight = this.$el.height();
this.evaluate();
return this;
},
// just an alias for the reflow event
reflow: function(){
this.onReflow();
return this;
},
// evaluate the current window state and position elements accordingly
evaluate: function(){
var windowScrollPosition = this.$window.scrollTop(),
coords = {};
// if you have scrolled to or past the element
if( !this.isFixed ){
if( windowScrollPosition >= this.scrollTop
&&
windowScrollPosition + this.elHeight - this.scrollTop < this.containerHeight) {
if( this.preventReflow === true ) {
this.$el.css('-webkit-transition-duration','.3s');
this.$el.css({ top: (windowScrollPosition - this.$container.offset().top+this.offsetY) +'px', position: 'absolute' });
} else {
this.$el.css({ position: 'fixed', left: this.$el.offset().left+this.offsetX+'px', top: this.offsetY+'px' });
}
// callbacks
this.fix();
return;
}
}
if( this.isFixed ){
// if the current window scroll position is above the element and it is fixed to the viewport, return the element
// to its original position
if(windowScrollPosition <= this.scrollTop){
coords = this.getOriginalCoordinates();
this.$el.css(coords);
this.unFix();
return;
}else if( this.preventReflow === true ){
this.$el.css('-webkit-transition-duration','.3s');
this.$el.css({ top: (windowScrollPosition - this.$container.offset().top+this.offsetY) +'px', position: 'absolute' });
return;
}
// if you have reached the end of the container. This is to prevent fixed position overflow
if( windowScrollPosition + this.elHeight - this.scrollTop >= this.containerHeight
&&
this.constrainToContainer ) {
this.$el.css({ top: (this.containerHeight-(windowScrollPosition + this.elHeight - this.scrollTop))+'px' });
return;
}
}
return;
},
// fired once the element is released from its positioning
unFix: function() {
this.isFixed = false;
this.$container.removeClass(this.fixedClassName);
this.onUnFix();
return this;
},
// fired once the element is set to fixed position
fix: function() {
this.isFixed = true;
this.$container.addClass(this.fixedClassName);
this.onFix();
return this;
},
// return an object with the styles that will set the el to its original state
getOriginalCoordinates: function() {
var coordinates = {
position : this.originalPosition,
top : this.originalTop
};
if(this.originalLeft !== false) {
coordinates.left = this.originalLeft;
}
if(this.originalRight !== false) {
coordinates.right = this.originalRight;
}
return coordinates;
},
// callbacks
onFix : this.$.noop,
onUnFix : this.$.noop,
// destroy the fixie and return it to original state
destroy: function() {
var coords = this.getOriginalCoordinates();
this.$el.css(coords);
this.$el.removeClass(this.fixieClassName);
this.$container.removeClass(this.fixedClassName);
this.$(this.target).unbind('.'+this.token);
}
};
[{"interval":"2013y01w","entry":{"activities":[{"id":35038107,"name":"Post flight NYE family run","workout_type":null,"trainer":0,"start_date":1356997282,"utc_offset":28800,"moving_time":3605,"elapsed_time":3636,"distance":10477,"speed":10463,"elev_gain":264},{"id":35188823,"name":"Great Scotch! New Years run with PD and BR","workout_type":null,"trainer":0,"start_date":1357061128,"utc_offset":28800,"moving_time":4822,"elapsed_time":5540,"distance":15420,"speed":11512,"elev_gain":521},{"id":35348021,"name":"SummitAve-HKEKoo-MtHome-Pipeline","workout_type":null,"trainer":0,"start_date":1357135082,"utc_offset":28800,"moving_time":4233,"elapsed_time":4284,"distance":12189,"speed":10366,"elev_gain":415},{"id":35553949,"name":"Easing into turnover (20 min tempo)","workout_type":null,"trainer":0,"start_date":1357223386,"utc_offset":28800,"moving_time":2890,"elapsed_time":2923,"distance":11149,"speed":13888,"elev_gain":57},{"id":36084579,"name":"Lakes Loop + Bald Mtn Finish w/ Devon and Peter","workout_type":null,"trainer":0,"start_date":1357407485,"utc_offset":28800,"moving_time":6425,"elapsed_time":6788,"distance":20912,"speed":11717,"elev_gain":713},{"id":36400247,"name":"(Almost) all singletrack (almost) all the time (MtTam#01)","workout_type":null,"trainer":0,"start_date":1357506926,"utc_offset":28800,"moving_time":8049,"elapsed_time":8605,"distance":23367,"speed":10451,"elev_gain":995}]},"moving_time":30024,"elapsed_time":31776,"distance":93514,"speed":11213,"elev_gain":2965},{"interval":"2013y02w","entry":{"activities":[{"id":36641675,"name":"Ferry run commute","workout_type":null,"trainer":0,"start_date":1357610941,"utc_offset":28800,"moving_time":2537,"elapsed_time":2537,"distance":8629,"speed":12245,"elev_gain":63},{"id":36935044,"name":"Run commute ","workout_type":null,"trainer":0,"start_date":1357741350,"utc_offset":28800,"moving_time":7664,"elapsed_time":8072,"distance":27597,"speed":12963,"elev_gain":442},{"id":37048421,"name":"Pipeline-MtHome-WPI","workout_type":null,"trainer":0,"start_date":1357826469,"utc_offset":28800,"moving_time":5344,"elapsed_time":5344,"distance":14711,"speed":9910,"elev_gain":506},{"id":37145667,"name":"Bikepath tempo noir (25 min)","workout_type":null,"trainer":0,"start_date":1357911758,"utc_offset":28800,"moving_time":3096,"elapsed_time":3096,"distance":12238,"speed":14230,"elev_gain":60},{"id":37287071,"name":"Another day in paradise - TV to home with PD","workout_type":null,"trainer":0,"start_date":1358011121,"utc_offset":28800,"moving_time":8073,"elapsed_time":8421,"distance":26212,"speed":11688,"elev_gain":908},{"id":37419868,"name":"Sunday Dawn Patroll with Twisted Steel and Trev (MtTam#02)","workout_type":null,"trainer":0,"start_date":1358086726,"utc_offset":28800,"moving_time":9247,"elapsed_time":10430,"distance":27809,"speed":10826,"elev_gain":988}]},"moving_time":35961,"elapsed_time":37900,"distance":117196,"speed":11732,"elev_gain":2967},{"interval":"2013y03w","entry":{"activities":[{"id":37615791,"name":"Warmup, forgot to use interval function","workout_type":null,"trainer":0,"start_date":1358257578,"utc_offset":28800,"moving_time":1146,"elapsed_time":1146,"distance":3752,"speed":11787,"elev_gain":4},{"id":37615793,"name":"4x1 mile (2min rest) + a little turf marking on the pixie","workout_type":null,"trainer":0,"start_date":1358258856,"utc_offset":28800,"moving_time":3377,"elapsed_time":3397,"distance":13787,"speed":14698,"elev_gain":138},{"id":37717633,"name":"Yep, still cold and still dark","workout_type":null,"trainer":0,"start_date":1358344187,"utc_offset":28800,"moving_time":4748,"elapsed_time":4748,"distance":14503,"speed":10996,"elev_gain":378},{"id":37815522,"name":"Run commute (via Oakwood Valley)","workout_type":null,"trainer":0,"start_date":1358432084,"utc_offset":28800,"moving_time":6769,"elapsed_time":6976,"distance":24546,"speed":13054,"elev_gain":397},{"id":37896068,"name":"Recovery + exploring new roads in the dark","workout_type":null,"trainer":0,"start_date":1358515995,"utc_offset":28800,"moving_time":3654,"elapsed_time":3677,"distance":11487,"speed":11317,"elev_gain":313},{"id":38018988,"name":"Northside Loop","workout_type":null,"trainer":0,"start_date":1358615527,"utc_offset":28800,"moving_time":6466,"elapsed_time":6959,"distance":16581,"speed":9231,"elev_gain":559},{"id":38136197,"name":"Blithedale-Railroad-WPI-OldStage-Pantoll-TCC-Troop80-MtHome","workout_type":null,"trainer":0,"start_date":1358697090,"utc_offset":28800,"moving_time":7204,"elapsed_time":7407,"distance":25755,"speed":12870,"elev_gain":666}]},"moving_time":33364,"elapsed_time":34310,"distance":110411,"speed":11913,"elev_gain":2455},{"interval":"2013y04w","entry":{"activities":[{"id":38237088,"name":"Sunrise Plodding + A ZigZag descent","workout_type":null,"trainer":0,"start_date":1358778414,"utc_offset":28800,"moving_time":5217,"elapsed_time":5305,"distance":14388,"speed":9928,"elev_gain":504},{"id":38578112,"name":"01/23/2013 Mill Valley, CA","workout_type":null,"trainer":0,"start_date":1358950184,"utc_offset":28800,"moving_time":1938,"elapsed_time":2349,"distance":5797,"speed":10768,"elev_gain":11},{"id":38578114,"name":"I'd really like to know how that happened.","workout_type":null,"trainer":0,"start_date":1359074148,"utc_offset":28800,"moving_time":2690,"elapsed_time":2825,"distance":11523,"speed":15421,"elev_gain":72},{"id":38727641,"name":"Plodding","workout_type":null,"trainer":0,"start_date":1359122618,"utc_offset":28800,"moving_time":3069,"elapsed_time":3084,"distance":9105,"speed":10680,"elev_gain":75},{"id":38727644,"name":"Tennessee Valley Loop","workout_type":null,"trainer":0,"start_date":1359216685,"utc_offset":28800,"moving_time":5341,"elapsed_time":7044,"distance":17699,"speed":11930,"elev_gain":544},{"id":38843370,"name":"Sunrise on Tam + New Northside Trails (MtTam#04)","workout_type":null,"trainer":0,"start_date":1359294569,"utc_offset":28800,"moving_time":9876,"elapsed_time":12839,"distance":29004,"speed":10572,"elev_gain":1311}]},"moving_time":28131,"elapsed_time":33446,"distance":87516,"speed":11200,"elev_gain":2517},{"interval":"2013y05w","entry":{"activities":[{"id":39006114,"name":"Pipeline - MattyD - BootyJ - Troop80 - SunnyT","workout_type":null,"trainer":0,"start_date":1359416692,"utc_offset":28800,"moving_time":6277,"elapsed_time":6490,"distance":18332,"speed":10513,"elev_gain":696},{"id":39055376,"name":"Progressive Tempo","workout_type":null,"trainer":0,"start_date":1359470563,"utc_offset":28800,"moving_time":3574,"elapsed_time":3574,"distance":14498,"speed":14604,"elev_gain":113},{"id":39233995,"name":"Tenderfoot-Cypress","workout_type":null,"trainer":0,"start_date":1359555613,"utc_offset":28800,"moving_time":3106,"elapsed_time":3152,"distance":8386,"speed":9720,"elev_gain":236},{"id":39233990,"name":"SFRC Opening Night Run","workout_type":null,"trainer":0,"start_date":1359598071,"utc_offset":28800,"moving_time":2774,"elapsed_time":2827,"distance":9870,"speed":12809,"elev_gain":15},{"id":39274122,"name":"Run commute","workout_type":null,"trainer":0,"start_date":1359641127,"utc_offset":28800,"moving_time":5229,"elapsed_time":5621,"distance":17849,"speed":12289,"elev_gain":409},{"id":39495785,"name":"SFRC grand opening / hike with Autumn","workout_type":null,"trainer":0,"start_date":1359823186,"utc_offset":28800,"moving_time":4627,"elapsed_time":5201,"distance":8921,"speed":6941,"elev_gain":119},{"id":39816520,"name":"Full Railroad Grade to MtTam#6","workout_type":null,"trainer":0,"start_date":1359925266,"utc_offset":28800,"moving_time":7428,"elapsed_time":7748,"distance":26084,"speed":12641,"elev_gain":820}]},"moving_time":33015,"elapsed_time":34613,"distance":103940,"speed":11334,"elev_gain":2408},{"interval":"2013y06w","entry":{"activities":[{"id":39749815,"name":"Nobody can accuse me of going too hard on my easy days. ","workout_type":null,"trainer":0,"start_date":1359987569,"utc_offset":28800,"moving_time":2799,"elapsed_time":2799,"distance":7740,"speed":9955,"elev_gain":82},{"id":39858444,"name":"SFRC Tam Tuesday (MtTam#7)","workout_type":null,"trainer":0,"start_date":1360071456,"utc_offset":28800,"moving_time":6389,"elapsed_time":7487,"distance":16098,"speed":9070,"elev_gain":829},{"id":40079685,"name":"Racing flats know how to make a trail guy feel special","workout_type":null,"trainer":0,"start_date":1360245889,"utc_offset":28800,"moving_time":3976,"elapsed_time":4513,"distance":16464,"speed":14907,"elev_gain":81},{"id":40184405,"name":"Run commute (via Sausalito) and UD product testing ","workout_type":null,"trainer":0,"start_date":1360333405,"utc_offset":28800,"moving_time":6999,"elapsed_time":7388,"distance":24251,"speed":12473,"elev_gain":171},{"id":40309653,"name":"SFRC Run to home","workout_type":null,"trainer":0,"start_date":1360426069,"utc_offset":28800,"moving_time":7294,"elapsed_time":7941,"distance":24134,"speed":11911,"elev_gain":774},{"id":40453363,"name":"Widowmaker to Manmaker! (MtTam#8)","workout_type":null,"trainer":0,"start_date":1360507252,"utc_offset":28800,"moving_time":13003,"elapsed_time":14543,"distance":42251,"speed":11697,"elev_gain":1529}]},"moving_time":40460,"elapsed_time":44671,"distance":130938,"speed":11650,"elev_gain":3466},{"interval":"2013y07w","entry":{"activities":[{"id":40545200,"name":"Frosty","workout_type":null,"trainer":0,"start_date":1360591533,"utc_offset":28800,"moving_time":3312,"elapsed_time":3336,"distance":9663,"speed":10503,"elev_gain":110},{"id":40599458,"name":"Special delivery for Brett, Peter and Nathan","workout_type":null,"trainer":0,"start_date":1360628464,"utc_offset":28800,"moving_time":2946,"elapsed_time":3810,"distance":9210,"speed":11255,"elev_gain":49},{"id":40759304,"name":"A gesture of speed while stuck in the sick cave. 8x100s","workout_type":null,"trainer":0,"start_date":1360764386,"utc_offset":28800,"moving_time":3684,"elapsed_time":3684,"distance":12877,"speed":12583,"elev_gain":120},{"id":40861958,"name":"Bay Shore Path Exploring","workout_type":null,"trainer":0,"start_date":1360850690,"utc_offset":28800,"moving_time":4002,"elapsed_time":4047,"distance":14038,"speed":12628,"elev_gain":110},{"id":40890621,"name":"Lunch Run with people who can call it a work run","workout_type":null,"trainer":0,"start_date":1360871193,"utc_offset":28800,"moving_time":3541,"elapsed_time":3714,"distance":11263,"speed":11450,"elev_gain":10},{"id":40969956,"name":"Run commute and the art of packing","workout_type":null,"trainer":0,"start_date":1360936952,"utc_offset":28800,"moving_time":7066,"elapsed_time":7377,"distance":27366,"speed":13942,"elev_gain":448},{"id":41147228,"name":"The standard favorite","workout_type":null,"trainer":0,"start_date":1361045858,"utc_offset":28800,"moving_time":6032,"elapsed_time":6211,"distance":18469,"speed":11022,"elev_gain":598},{"id":41277889,"name":"Now that's a loop! Run around Tam with BR, JM, NY, \u0026 VB","workout_type":null,"trainer":0,"start_date":1361111818,"utc_offset":28800,"moving_time":11534,"elapsed_time":12600,"distance":37027,"speed":11557,"elev_gain":1326}]},"moving_time":42117,"elapsed_time":44779,"distance":139913,"speed":11959,"elev_gain":2771},{"interval":"2013y08w","entry":{"activities":[{"id":41517777,"name":"New kicks, tired legs. Railroad Grade Loop","workout_type":null,"trainer":0,"start_date":1361281704,"utc_offset":28800,"moving_time":4923,"elapsed_time":4970,"distance":14487,"speed":10594,"elev_gain":421},{"id":41630950,"name":"5 x 1 mile, 3 min rest, very cold","workout_type":null,"trainer":0,"start_date":1361368363,"utc_offset":28800,"moving_time":4480,"elapsed_time":4641,"distance":17520,"speed":14079,"elev_gain":75},{"id":41740336,"name":"Dias Ridge, worthy of an out and back","workout_type":null,"trainer":0,"start_date":1361454706,"utc_offset":28800,"moving_time":5141,"elapsed_time":5170,"distance":16096,"speed":11271,"elev_gain":533},{"id":41836553,"name":"Autumn's first year!!! And a tempo.","workout_type":null,"trainer":0,"start_date":1361541305,"utc_offset":28800,"moving_time":3849,"elapsed_time":3849,"distance":14497,"speed":13559,"elev_gain":377},{"id":41952829,"name":"Pre sunrise ascent, MtTam#9","workout_type":null,"trainer":0,"start_date":1361626252,"utc_offset":28800,"moving_time":5423,"elapsed_time":5577,"distance":14469,"speed":9605,"elev_gain":794},{"id":42131300,"name":"Blitzing Mt Tam in sub 7min pace + hanging on for dear life!","workout_type":null,"trainer":0,"start_date":1361723825,"utc_offset":28800,"moving_time":9668,"elapsed_time":10034,"distance":36222,"speed":13487,"elev_gain":1038}]},"moving_time":33484,"elapsed_time":34241,"distance":113291,"speed":12180,"elev_gain":3238},{"interval":"2013y09w","entry":{"activities":[{"id":42378780,"name":"Playing tourist on a lunch run","workout_type":null,"trainer":0,"start_date":1361912578,"utc_offset":28800,"moving_time":4288,"elapsed_time":4411,"distance":14347,"speed":12045,"elev_gain":188},{"id":42513326,"name":"Ferry to SFRC","workout_type":null,"trainer":0,"start_date":1362017375,"utc_offset":28800,"moving_time":2883,"elapsed_time":2908,"distance":9119,"speed":11387,"elev_gain":0},{"id":42627280,"name":"Run commute home (via SCA, Alta, Oakwood)","workout_type":null,"trainer":0,"start_date":1362099176,"utc_offset":28800,"moving_time":6303,"elapsed_time":6722,"distance":24129,"speed":13781,"elev_gain":389},{"id":42733865,"name":"Sol Food pickup and Kristin's 1st day day as a business owner!","workout_type":null,"trainer":0,"start_date":1362188495,"utc_offset":28800,"moving_time":3282,"elapsed_time":3465,"distance":9669,"speed":10605,"elev_gain":76},{"id":43059971,"name":"Sick, with the BOB","workout_type":null,"trainer":0,"start_date":1362356877,"utc_offset":28800,"moving_time":2740,"elapsed_time":2812,"distance":8312,"speed":10921,"elev_gain":51}]},"moving_time":19496,"elapsed_time":20318,"distance":65576,"speed":12109,"elev_gain":704},{"interval":"2013y10w","entry":{"activities":[{"id":43119116,"name":"Scott valley slog (sick)","workout_type":null,"trainer":0,"start_date":1362406631,"utc_offset":28800,"moving_time":2873,"elapsed_time":2938,"distance":8960,"speed":11228,"elev_gain":98},{"id":43324604,"name":"Pixie (sick)","workout_type":null,"trainer":0,"start_date":1362534866,"utc_offset":28800,"moving_time":1330,"elapsed_time":1330,"distance":4057,"speed":10983,"elev_gain":124},{"id":43375677,"name":"Bike path w/ pickups (feeling better...a little)","workout_type":null,"trainer":0,"start_date":1362578466,"utc_offset":28800,"moving_time":3289,"elapsed_time":3313,"distance":11522,"speed":12612,"elev_gain":67},{"id":43491294,"name":"Short bike path (still sick)","workout_type":null,"trainer":0,"start_date":1362665903,"utc_offset":28800,"moving_time":1745,"elapsed_time":1745,"distance":5858,"speed":12087,"elev_gain":52},{"id":43625275,"name":"Here's hoping","workout_type":null,"trainer":0,"start_date":1362773069,"utc_offset":28800,"moving_time":1540,"elapsed_time":1540,"distance":5240,"speed":12250,"elev_gain":156},{"id":43798633,"name":"Way Too Cool 50km - 4th","workout_type":null,"trainer":0,"start_date":1362844758,"utc_offset":28800,"moving_time":12364,"elapsed_time":12364,"distance":48168,"speed":14025,"elev_gain":1283}]},"moving_time":23141,"elapsed_time":23230,"distance":83805,"speed":13037,"elev_gain":1780},{"interval":"2013y11w","entry":{"activities":[{"id":44496078,"name":"Back in the saddle! Mt Tam #11","workout_type":null,"trainer":0,"start_date":1363351227,"utc_offset":25200,"moving_time":5934,"elapsed_time":6427,"distance":14578,"speed":8844,"elev_gain":777},{"id":44645665,"name":"Cheering on Kristin with Autumn and BOB","workout_type":null,"trainer":0,"start_date":1363450790,"utc_offset":25200,"moving_time":3972,"elapsed_time":5775,"distance":11173,"speed":10127,"elev_gain":457},{"id":44796693,"name":"BlithedaleRidge-Widowmaker-MtTam#12-Eldridge-LakeLagunitas-RockSpgs-WPI-MHI-Pipeline","workout_type":null,"trainer":0,"start_date":1363528096,"utc_offset":25200,"moving_time":10412,"elapsed_time":11068,"distance":32900,"speed":11375,"elev_gain":1383}]},"moving_time":20318,"elapsed_time":23270,"distance":58651,"speed":10392,"elev_gain":2617},{"interval":"2013y12w","entry":{"activities":[{"id":44920940,"name":"Canyon shuffle","workout_type":null,"trainer":0,"start_date":1363612464,"utc_offset":25200,"moving_time":2906,"elapsed_time":2927,"distance":8156,"speed":10104,"elev_gain":184},{"id":45126438,"name":"Tempo run commute","workout_type":null,"trainer":0,"start_date":1363741490,"utc_offset":25200,"moving_time":5511,"elapsed_time":6072,"distance":22587,"speed":14754,"elev_gain":123},{"id":45166797,"name":"Easy Gravity Car - Summit Ave","workout_type":null,"trainer":0,"start_date":1363783572,"utc_offset":25200,"moving_time":4420,"elapsed_time":4420,"distance":13175,"speed":10730,"elev_gain":381},{"id":45315881,"name":"Finding freedom on a lunch run. ","workout_type":null,"trainer":0,"start_date":1363890982,"utc_offset":25200,"moving_time":5045,"elapsed_time":5276,"distance":17966,"speed":12820,"elev_gain":193},{"id":45396709,"name":"Cold Dark Tempo (6 mi, 30 min)","workout_type":null,"trainer":0,"start_date":1363956598,"utc_offset":25200,"moving_time":4381,"elapsed_time":4606,"distance":17707,"speed":14551,"elev_gain":63},{"id":45602770,"name":"Run commute via SCA, Alta, Marincello, Miwok","workout_type":null,"trainer":0,"start_date":1364084859,"utc_offset":25200,"moving_time":8264,"elapsed_time":8825,"distance":29781,"speed":12973,"elev_gain":737},{"id":45761722,"name":"Evening run commute. I miss Mt Tam.","workout_type":null,"trainer":0,"start_date":1364170843,"utc_offset":25200,"moving_time":9841,"elapsed_time":10451,"distance":33278,"speed":12173,"elev_gain":893}]},"moving_time":40368,"elapsed_time":42577,"distance":142650,"speed":12721,"elev_gain":2574},{"interval":"2013y13w","entry":{"activities":[{"id":45917154,"name":"One foot in front of the other, barely.","workout_type":null,"trainer":0,"start_date":1364303675,"utc_offset":25200,"moving_time":2454,"elapsed_time":2454,"distance":6874,"speed":10084,"elev_gain":79},{"id":46046378,"name":"Coming up for air, Mt Tam #13.99","workout_type":null,"trainer":0,"start_date":1364388690,"utc_offset":25200,"moving_time":5099,"elapsed_time":5499,"distance":14103,"speed":9957,"elev_gain":734},{"id":46126621,"name":"SFRC group run","workout_type":null,"trainer":0,"start_date":1364433445,"utc_offset":25200,"moving_time":2867,"elapsed_time":2889,"distance":8992,"speed":11292,"elev_gain":0},{"id":46173498,"name":"Miwok Loop","workout_type":null,"trainer":0,"start_date":1364476127,"utc_offset":25200,"moving_time":4780,"elapsed_time":4780,"distance":16221,"speed":12216,"elev_gain":376},{"id":46392350,"name":"Cypress Out-Back. Love the new Strava upload interface!","workout_type":null,"trainer":0,"start_date":1364596406,"utc_offset":25200,"moving_time":2907,"elapsed_time":2956,"distance":9302,"speed":11520,"elev_gain":241},{"id":46481596,"name":"Marin 1/2 Marathon (1:12:47) - tied 1st with Jorge the hammer!!!","workout_type":1,"trainer":0,"start_date":1364655988,"utc_offset":25200,"moving_time":4394,"elapsed_time":4394,"distance":20636,"speed":16907,"elev_gain":215},{"id":46486847,"name":"Cool down","workout_type":null,"trainer":0,"start_date":1364660834,"utc_offset":25200,"moving_time":675,"elapsed_time":1146,"distance":2189,"speed":11675,"elev_gain":26},{"id":46659383,"name":"Mountain loop with the fellas","workout_type":null,"trainer":0,"start_date":1364738355,"utc_offset":25200,"moving_time":9169,"elapsed_time":9833,"distance":26919,"speed":10569,"elev_gain":1119}]},"moving_time":32345,"elapsed_time":33951,"distance":105236,"speed":11713,"elev_gain":2790},{"interval":"2013y14w","entry":{"activities":[{"id":46984128,"name":"Depot-Railroad Grade-WPI-Nora-MattD-Pipeline","workout_type":null,"trainer":0,"start_date":1364928475,"utc_offset":25200,"moving_time":5879,"elapsed_time":6020,"distance":19313,"speed":11826,"elev_gain":551},{"id":47372460,"name":"Crippled by the flu","workout_type":null,"trainer":0,"start_date":1365188812,"utc_offset":25200,"moving_time":2260,"elapsed_time":2517,"distance":4736,"speed":7544,"elev_gain":0},{"id":47991843,"name":"Around the block, sick","workout_type":0,"trainer":0,"start_date":1365253804,"utc_offset":25200,"moving_time":1892,"elapsed_time":1913,"distance":3178,"speed":6047,"elev_gain":73},{"id":47672879,"name":"Pixie trail test ","workout_type":null,"trainer":0,"start_date":1365344573,"utc_offset":25200,"moving_time":785,"elapsed_time":785,"distance":2196,"speed":10073,"elev_gain":57},{"id":47789912,"name":"Tam summit #15 new direct route with Dave","workout_type":null,"trainer":0,"start_date":1365375858,"utc_offset":25200,"moving_time":6508,"elapsed_time":6940,"distance":16494,"speed":9124,"elev_gain":939}]},"moving_time":17324,"elapsed_time":18175,"distance":45917,"speed":9542,"elev_gain":1620},{"interval":"2013y15w","entry":{"activities":[{"id":47895675,"name":"Lunch Run","workout_type":null,"trainer":0,"start_date":1365446377,"utc_offset":25200,"moving_time":4979,"elapsed_time":5007,"distance":17660,"speed":12768,"elev_gain":201},{"id":47991850,"name":"Great loop, lifeless legs. ","workout_type":0,"trainer":0,"start_date":1365511231,"utc_offset":25200,"moving_time":6104,"elapsed_time":6151,"distance":16938,"speed":9989,"elev_gain":651},{"id":48150520,"name":"Tam Taper! Can't resist... #16","workout_type":0,"trainer":0,"start_date":1365598228,"utc_offset":25200,"moving_time":5527,"elapsed_time":6264,"distance":14689,"speed":9568,"elev_gain":767},{"id":48378941,"name":"SFRC Montrail run!","workout_type":null,"trainer":0,"start_date":1365729228,"utc_offset":25200,"moving_time":2263,"elapsed_time":2263,"distance":8774,"speed":13958,"elev_gain":0},{"id":48456181,"name":"Lunch run, staying loose","workout_type":null,"trainer":0,"start_date":1365788475,"utc_offset":25200,"moving_time":2139,"elapsed_time":2139,"distance":6366,"speed":10714,"elev_gain":232},{"id":48798150,"name":"Lake Sonoma 50 Mile - 8th place - awesome day","workout_type":1,"trainer":0,"start_date":1365859806,"utc_offset":25200,"moving_time":23996,"elapsed_time":24132,"distance":78604,"speed":11792,"elev_gain":3257}]},"moving_time":45008,"elapsed_time":45956,"distance":143031,"speed":11440,"elev_gain":5108},{"interval":"2013y16w","entry":{"activities":[{"id":49558459,"name":"Recovery week under the belt - not easy but so key! Great to be back.","workout_type":0,"trainer":0,"start_date":1366376105,"utc_offset":25200,"moving_time":3456,"elapsed_time":3479,"distance":10211,"speed":10636,"elev_gain":320},{"id":49751104,"name":"SFRC Saturday 20 mi - Stellar day on the trails!","workout_type":2,"trainer":0,"start_date":1366470683,"utc_offset":25200,"moving_time":10338,"elapsed_time":10982,"distance":32239,"speed":11226,"elev_gain":1157},{"id":49925726,"name":"Sunday Summit (#17) and some bonus miles","workout_type":0,"trainer":0,"start_date":1366550112,"utc_offset":25200,"moving_time":8482,"elapsed_time":9751,"distance":24148,"speed":10249,"elev_gain":905}]},"moving_time":22276,"elapsed_time":24212,"distance":66598,"speed":10763,"elev_gain":2382},{"interval":"2013y17w","entry":{"activities":[{"id":50091817,"name":"Easy day, looking for hill interval routes","workout_type":0,"trainer":0,"start_date":1366635169,"utc_offset":25200,"moving_time":3788,"elapsed_time":3839,"distance":10029,"speed":9531,"elev_gain":316},{"id":50258926,"name":"Sunrise+Tam#18+Autumn wake up+Coffee with Kristin=Awesome way to start the day! ","workout_type":3,"trainer":0,"start_date":1366720114,"utc_offset":25200,"moving_time":4852,"elapsed_time":5138,"distance":14490,"speed":10751,"elev_gain":784},{"id":50440059,"name":"Blue collar Tam summit #19, high fives on the way down","workout_type":0,"trainer":0,"start_date":1366806759,"utc_offset":25200,"moving_time":5938,"elapsed_time":6991,"distance":16208,"speed":9826,"elev_gain":808},{"id":50731726,"name":"Ferry run commute","workout_type":null,"trainer":0,"start_date":1366939738,"utc_offset":25200,"moving_time":3706,"elapsed_time":3978,"distance":11917,"speed":11576,"elev_gain":368},{"id":50788871,"name":"Run commute via Sausalito","workout_type":null,"trainer":0,"start_date":1366980264,"utc_offset":25200,"moving_time":6881,"elapsed_time":7034,"distance":24273,"speed":12699,"elev_gain":169},{"id":51244917,"name":"Going Coastal (+Tam summit #20) with Rickey ","workout_type":2,"trainer":0,"start_date":1367162725,"utc_offset":25200,"moving_time":13447,"elapsed_time":16190,"distance":40237,"speed":10772,"elev_gain":1883}]},"moving_time":38612,"elapsed_time":43170,"distance":117154,"speed":10923,"elev_gain":4328},{"interval":"2013y18w","entry":{"activities":[{"id":51463990,"name":"Running with beb\u00e9","workout_type":0,"trainer":0,"start_date":1367278283,"utc_offset":25200,"moving_time":3319,"elapsed_time":4388,"distance":9663,"speed":10482,"elev_gain":213},{"id":51519901,"name":"Easing back into turnover + 3 Gomez hill sprints","workout_type":3,"trainer":0,"start_date":1367325345,"utc_offset":25200,"moving_time":3581,"elapsed_time":3592,"distance":13939,"speed":14013,"elev_gain":144},{"id":51723758,"name":"Early Bird Tam Summit #21","workout_type":0,"trainer":0,"start_date":1367411286,"utc_offset":25200,"moving_time":5401,"elapsed_time":5715,"distance":14574,"speed":9714,"elev_gain":779},{"id":52035644,"name":"Ferry -\u003E Sol Food P/U -\u003E Home","workout_type":null,"trainer":0,"start_date":1367547310,"utc_offset":25200,"moving_time":2136,"elapsed_time":2387,"distance":8646,"speed":14573,"elev_gain":53},{"id":52095656,"name":"Friday Tam #22 with Rivers","workout_type":0,"trainer":0,"start_date":1367585335,"utc_offset":25200,"moving_time":5410,"elapsed_time":5687,"distance":14716,"speed":9792,"elev_gain":775},{"id":52269481,"name":"Railroad Grade Tempo (25 min - Blithedale to Hogsback)","workout_type":3,"trainer":0,"start_date":1367672867,"utc_offset":25200,"moving_time":5601,"elapsed_time":5766,"distance":19314,"speed":12413,"elev_gain":569},{"id":52485981,"name":"So much fun to be had, so little time","workout_type":2,"trainer":0,"start_date":1367757027,"utc_offset":25200,"moving_time":7903,"elapsed_time":7973,"distance":25790,"speed":11748,"elev_gain":840}]},"moving_time":33351,"elapsed_time":35508,"distance":106642,"speed":11511,"elev_gain":3373},{"interval":"2013y19w","entry":{"activities":[{"id":53071016,"name":"Exploring","workout_type":0,"trainer":0,"start_date":1367931095,"utc_offset":25200,"moving_time":2807,"elapsed_time":2828,"distance":7732,"speed":9916,"elev_gain":252},{"id":53071014,"name":"Bikepath 2 x 2.4 mi, 2min rest, 4 x gomez hill sprints","workout_type":3,"trainer":0,"start_date":1368017274,"utc_offset":25200,"moving_time":4046,"elapsed_time":4046,"distance":16101,"speed":14326,"elev_gain":195},{"id":53188717,"name":"SFRC Newton Rendezvous Run","workout_type":0,"trainer":0,"start_date":1368059951,"utc_offset":25200,"moving_time":3438,"elapsed_time":3949,"distance":11254,"speed":11785,"elev_gain":46},{"id":53364603,"name":"Larkspur Ferry Run Commute with Epic Bonk","workout_type":0,"trainer":0,"start_date":1368149274,"utc_offset":25200,"moving_time":3584,"elapsed_time":3799,"distance":11834,"speed":11887,"elev_gain":244},{"id":53420956,"name":"County View Hill Intervals: 5 x 800m @ 17% grade","workout_type":3,"trainer":0,"start_date":1368189979,"utc_offset":25200,"moving_time":5116,"elapsed_time":5116,"distance":16096,"speed":11326,"elev_gain":680},{"id":53623813,"name":"Pre Mother's Day family run","workout_type":null,"trainer":0,"start_date":1368290274,"utc_offset":25200,"moving_time":2795,"elapsed_time":2913,"distance":8357,"speed":10764,"elev_gain":96},{"id":53684592,"name":"Midday Tam Summit #23 with Mackey","workout_type":0,"trainer":0,"start_date":1368305828,"utc_offset":25200,"moving_time":6451,"elapsed_time":7072,"distance":17216,"speed":9607,"elev_gain":761},{"id":53815960,"name":"Double Tam: Widowmaker + Temelpa","workout_type":2,"trainer":0,"start_date":1368363314,"utc_offset":25200,"moving_time":10621,"elapsed_time":11419,"distance":27754,"speed":9407,"elev_gain":1529}]},"moving_time":38858,"elapsed_time":41142,"distance":116344,"speed":10779,"elev_gain":3803},{"interval":"2013y20w","entry":{"activities":[{"id":54069323,"name":"Work from home lunch run","workout_type":0,"trainer":0,"start_date":1368471996,"utc_offset":25200,"moving_time":3986,"elapsed_time":4068,"distance":11268,"speed":10177,"elev_gain":311},{"id":54145599,"name":"Exploring Camino Alto Fireroads","workout_type":0,"trainer":0,"start_date":1368535281,"utc_offset":25200,"moving_time":5388,"elapsed_time":5507,"distance":16897,"speed":11290,"elev_gain":422},{"id":54323042,"name":"Seminary Tempo, 30 min","workout_type":3,"trainer":0,"start_date":1368622521,"utc_offset":25200,"moving_time":3906,"elapsed_time":3936,"distance":16094,"speed":14833,"elev_gain":159},{"id":54433532,"name":"Larkspur ferry run","workout_type":null,"trainer":0,"start_date":1368664468,"utc_offset":25200,"moving_time":2786,"elapsed_time":2932,"distance":9389,"speed":12132,"elev_gain":127},{"id":54687605,"name":"1 min on/off fartlek (30 min) + 3 gomez hill sprints","workout_type":3,"trainer":0,"start_date":1368795184,"utc_offset":25200,"moving_time":4106,"elapsed_time":4154,"distance":16090,"speed":14107,"elev_gain":167},{"id":54981138,"name":"My Heart Burns for B2B. ","workout_type":0,"trainer":0,"start_date":1368926296,"utc_offset":25200,"moving_time":2486,"elapsed_time":2850,"distance":8843,"speed":12806,"elev_gain":110},{"id":55135308,"name":"Warmup","workout_type":0,"trainer":0,"start_date":1368970199,"utc_offset":25200,"moving_time":816,"elapsed_time":1033,"distance":2230,"speed":9840,"elev_gain":56},{"id":55135320,"name":"Bay to Breakers 12km - 14th place","workout_type":1,"trainer":0,"start_date":1368972005,"utc_offset":25200,"moving_time":2373,"elapsed_time":2373,"distance":12166,"speed":18456,"elev_gain":94},{"id":55135314,"name":"Cooldown to Rickey's","workout_type":0,"trainer":0,"start_date":1368974670,"utc_offset":0,"moving_time":1246,"elapsed_time":1299,"distance":4251,"speed":12284,"elev_gain":77}]},"moving_time":27093,"elapsed_time":28152,"distance":97228,"speed":12919,"elev_gain":1523},{"interval":"2013y21w","entry":{"activities":[{"id":55293300,"name":"Ahh, back to running slow on the trails","workout_type":0,"trainer":0,"start_date":1369054265,"utc_offset":25200,"moving_time":5131,"elapsed_time":5169,"distance":15029,"speed":10545,"elev_gain":502},{"id":55476295,"name":"Morning miles, with some strides","workout_type":0,"trainer":0,"start_date":1369140680,"utc_offset":25200,"moving_time":2641,"elapsed_time":2798,"distance":8072,"speed":11003,"elev_gain":151},{"id":55582595,"name":"Cardiogram","workout_type":0,"trainer":0,"start_date":1369175031,"utc_offset":25200,"moving_time":5080,"elapsed_time":5103,"distance":17707,"speed":12548,"elev_gain":697},{"id":55667606,"name":"Windy Tam Summit #26","workout_type":0,"trainer":0,"start_date":1369226248,"utc_offset":25200,"moving_time":5740,"elapsed_time":5917,"distance":14652,"speed":9189,"elev_gain":795},{"id":55945163,"name":"Larkspur ferry run commute via blithedale ridge","workout_type":0,"trainer":0,"start_date":1369355513,"utc_offset":25200,"moving_time":4745,"elapsed_time":5095,"distance":14817,"speed":11242,"elev_gain":438},{"id":56001811,"name":"County View Hill Intervals 5 x 800m @ 17%","workout_type":3,"trainer":0,"start_date":1369399567,"utc_offset":25200,"moving_time":5060,"elapsed_time":5060,"distance":15731,"speed":11192,"elev_gain":701},{"id":56185695,"name":"Fire Roads and a Summit (#27)","workout_type":2,"trainer":0,"start_date":1369486999,"utc_offset":25200,"moving_time":9223,"elapsed_time":10219,"distance":28162,"speed":10992,"elev_gain":923},{"id":56496076,"name":"Warmup, drills and strides","workout_type":0,"trainer":0,"start_date":1369614342,"utc_offset":25200,"moving_time":2493,"elapsed_time":2825,"distance":9058,"speed":13080,"elev_gain":140}]},"moving_time":40113,"elapsed_time":42186,"distance":123228,"speed":11059,"elev_gain":4347},{"interval":"2013y22w","entry":{"activities":[{"id":56640335,"name":"Warmup","workout_type":0,"trainer":0,"start_date":1369666857,"utc_offset":25200,"moving_time":1048,"elapsed_time":1425,"distance":3269,"speed":11229,"elev_gain":20},{"id":56640333,"name":"Marin Memorial Day 10k - new PR and 10th place","workout_type":1,"trainer":0,"start_date":1369668604,"utc_offset":25200,"moving_time":1918,"elapsed_time":1920,"distance":10193,"speed":19133,"elev_gain":27},{"id":56640331,"name":"MHBB Cooldown and Milk run with KB, TG, KG and Autumn","workout_type":0,"trainer":0,"start_date":1369672184,"utc_offset":25200,"moving_time":4874,"elapsed_time":8198,"distance":15930,"speed":11766,"elev_gain":104},{"id":56764953,"name":"Pre flight fresh air","workout_type":0,"trainer":0,"start_date":1369745232,"utc_offset":25200,"moving_time":2263,"elapsed_time":2265,"distance":6971,"speed":11090,"elev_gain":88},{"id":57022404,"name":"Shanghai treadmill sessions","workout_type":null,"trainer":0,"start_date":1369867379,"utc_offset":25200,"moving_time":2700,"elapsed_time":2700,"distance":10000,"speed":13333,"elev_gain":0},{"id":57209588,"name":"Exploring Shanghai","workout_type":null,"trainer":0,"start_date":1369952210,"utc_offset":-28800,"moving_time":4472,"elapsed_time":4923,"distance":12675,"speed":10203,"elev_gain":196},{"id":57414854,"name":"Treadmill","workout_type":null,"trainer":0,"start_date":1370048109,"utc_offset":25200,"moving_time":2220,"elapsed_time":2220,"distance":8000,"speed":12972,"elev_gain":0},{"id":57611990,"name":"Lovely family run fueled by MHB\u0026B","workout_type":0,"trainer":0,"start_date":1370127690,"utc_offset":25200,"moving_time":4741,"elapsed_time":5207,"distance":14444,"speed":10968,"elev_gain":365},{"id":57856690,"name":"Dipsea-Cardiac-TCC-Troop80","workout_type":0,"trainer":0,"start_date":1370214497,"utc_offset":25200,"moving_time":5750,"elapsed_time":6086,"distance":17702,"speed":11083,"elev_gain":689}]},"moving_time":29986,"elapsed_time":34944,"distance":99184,"speed":11908,"elev_gain":1489},{"interval":"2013y23w","entry":{"activities":[{"id":57934760,"name":"short and easy","workout_type":0,"trainer":0,"start_date":1370266403,"utc_offset":25200,"moving_time":2106,"elapsed_time":2106,"distance":6453,"speed":11030,"elev_gain":129},{"id":58138887,"name":"Tempo that wasn't to be + 5 x Gomez hill sprints","workout_type":3,"trainer":0,"start_date":1370350509,"utc_offset":25200,"moving_time":4245,"elapsed_time":4245,"distance":16074,"speed":13631,"elev_gain":270},{"id":58370162,"name":"Tam Summit #28, a rare out and back","workout_type":0,"trainer":0,"start_date":1370435757,"utc_offset":25200,"moving_time":5008,"elapsed_time":5501,"distance":15272,"speed":10978,"elev_gain":731},{"id":58731156,"name":"Extraordinarily subordinary ","workout_type":null,"trainer":0,"start_date":1370568575,"utc_offset":25200,"moving_time":2918,"elapsed_time":3017,"distance":9007,"speed":11112,"elev_gain":171},{"id":59331999,"name":"High Sierra Camps ~50 mi Loop","workout_type":2,"trainer":0,"start_date":1370699908,"utc_offset":25200,"moving_time":33677,"elapsed_time":38058,"distance":77381,"speed":8271,"elev_gain":2334},{"id":59376117,"name":"Evening cruise","workout_type":0,"trainer":0,"start_date":1370819924,"utc_offset":25200,"moving_time":4033,"elapsed_time":4130,"distance":11290,"speed":10078,"elev_gain":344}]},"moving_time":51987,"elapsed_time":57057,"distance":135477,"speed":9382,"elev_gain":3979},{"interval":"2013y24w","entry":{"activities":[{"id":60028044,"name":"Strava SFRC Run","workout_type":null,"trainer":0,"start_date":1371086344,"utc_offset":25200,"moving_time":2901,"elapsed_time":2901,"distance":9327,"speed":11574,"elev_gain":0},{"id":60096012,"name":"Recovery week","workout_type":0,"trainer":0,"start_date":1371127102,"utc_offset":25200,"moving_time":2279,"elapsed_time":2279,"distance":6782,"speed":10713,"elev_gain":137},{"id":60277687,"name":"More recovery + drills and strides","workout_type":0,"trainer":0,"start_date":1371213437,"utc_offset":25200,"moving_time":2540,"elapsed_time":2843,"distance":8041,"speed":11397,"elev_gain":138},{"id":60722430,"name":"Pixie Trail Hike","workout_type":0,"trainer":0,"start_date":1371336890,"utc_offset":25200,"moving_time":1149,"elapsed_time":1149,"distance":2318,"speed":7265,"elev_gain":77},{"id":60722447,"name":"Survived the recovery week, finished with a summit #29","workout_type":0,"trainer":0,"start_date":1371389744,"utc_offset":25200,"moving_time":5761,"elapsed_time":6312,"distance":16464,"speed":10288,"elev_gain":750}]},"moving_time":14630,"elapsed_time":15484,"distance":42932,"speed":10564,"elev_gain":1102},{"interval":"2013y25w","entry":{"activities":[{"id":60927696,"name":"Tam:30","workout_type":0,"trainer":0,"start_date":1371472640,"utc_offset":25200,"moving_time":6124,"elapsed_time":6598,"distance":17084,"speed":10043,"elev_gain":738},{"id":61169869,"name":"Ye Olde 30 min Bike Path Tempo + 3 Gomez hills sprints","workout_type":3,"trainer":0,"start_date":1371559759,"utc_offset":25200,"moving_time":3777,"elapsed_time":3813,"distance":15265,"speed":14550,"elev_gain":136},{"id":61425560,"name":"Tam:31","workout_type":0,"trainer":0,"start_date":1371645113,"utc_offset":25200,"moving_time":5383,"elapsed_time":5875,"distance":14555,"speed":9734,"elev_gain":783},{"id":61664741,"name":"Marincello hill repeats (5x)","workout_type":3,"trainer":0,"start_date":1371732245,"utc_offset":25200,"moving_time":4594,"elapsed_time":4620,"distance":16184,"speed":12682,"elev_gain":518},{"id":61878078,"name":"Solstice Summit:32","workout_type":0,"trainer":0,"start_date":1371818294,"utc_offset":25200,"moving_time":5456,"elapsed_time":5614,"distance":15235,"speed":10052,"elev_gain":730},{"id":62106994,"name":"Summit to Sea and #33","workout_type":2,"trainer":0,"start_date":1371907029,"utc_offset":25200,"moving_time":10679,"elapsed_time":10956,"distance":35312,"speed":11904,"elev_gain":1223},{"id":62441980,"name":"Atmospheric","workout_type":0,"trainer":0,"start_date":1372026709,"utc_offset":25200,"moving_time":5084,"elapsed_time":5407,"distance":14538,"speed":10294,"elev_gain":473}]},"moving_time":41097,"elapsed_time":42883,"distance":128173,"speed":11228,"elev_gain":4601},{"interval":"2013y26w","entry":{"activities":[{"id":62533063,"name":"Tam:34","workout_type":0,"trainer":0,"start_date":1372077527,"utc_offset":25200,"moving_time":4904,"elapsed_time":5281,"distance":14462,"speed":10617,"elev_gain":782},{"id":62746013,"name":"Hypothermic run with Russell/Injinji","workout_type":0,"trainer":0,"start_date":1372163667,"utc_offset":25200,"moving_time":5968,"elapsed_time":6112,"distance":14233,"speed":8586,"elev_gain":456},{"id":62887251,"name":"Evening jog with Autumn","workout_type":null,"trainer":0,"start_date":1372208880,"utc_offset":25200,"moving_time":3090,"elapsed_time":3258,"distance":9995,"speed":11645,"elev_gain":106},{"id":62979564,"name":"Marincello hill repeats x 5","workout_type":3,"trainer":0,"start_date":1372250929,"utc_offset":25200,"moving_time":4145,"elapsed_time":4285,"distance":14701,"speed":12768,"elev_gain":491},{"id":63307133,"name":"Ferry run commute","workout_type":null,"trainer":0,"start_date":1372379733,"utc_offset":25200,"moving_time":4913,"elapsed_time":5115,"distance":15706,"speed":11509,"elev_gain":309},{"id":63378320,"name":"Tam:35","workout_type":0,"trainer":0,"start_date":1372423370,"utc_offset":25200,"moving_time":5482,"elapsed_time":6560,"distance":15228,"speed":10000,"elev_gain":720},{"id":63476691,"name":"Yosemite Valley Loop - Family Run","workout_type":0,"trainer":0,"start_date":1372468837,"utc_offset":25200,"moving_time":4242,"elapsed_time":5305,"distance":13900,"speed":11797,"elev_gain":538},{"id":63601496,"name":"Yosemite Falls hike w/ Autumn","workout_type":0,"trainer":0,"start_date":1372512471,"utc_offset":25200,"moving_time":8603,"elapsed_time":13981,"distance":12670,"speed":5302,"elev_gain":1686},{"id":63698043,"name":"Melting on Glacier Point","workout_type":0,"trainer":0,"start_date":1372552947,"utc_offset":25200,"moving_time":6516,"elapsed_time":7008,"distance":16542,"speed":9139,"elev_gain":1036},{"id":63852928,"name":"Clouds Rest from Yosemite Valley","workout_type":2,"trainer":0,"start_date":1372596677,"utc_offset":25200,"moving_time":14360,"elapsed_time":15774,"distance":34736,"speed":8708,"elev_gain":1957}]},"moving_time":62223,"elapsed_time":72679,"distance":162173,"speed":9383,"elev_gain":8081},{"interval":"2013y27w","entry":{"activities":[{"id":64233316,"name":"Tam:36","workout_type":0,"trainer":0,"start_date":1372768013,"utc_offset":25200,"moving_time":5854,"elapsed_time":5945,"distance":14413,"speed":8863,"elev_gain":786},{"id":64451014,"name":"Feeling like a state bird provision + 5 x Mr. Gomez","workout_type":3,"trainer":0,"start_date":1372856054,"utc_offset":25200,"moving_time":3697,"elapsed_time":3863,"distance":14542,"speed":14160,"elev_gain":138},{"id":64672535,"name":"Tam:37 big group!","workout_type":0,"trainer":0,"start_date":1372942255,"utc_offset":25200,"moving_time":6340,"elapsed_time":8148,"distance":17329,"speed":9839,"elev_gain":781},{"id":65010659,"name":"Marincello 10-5-3-2min Ladder ","workout_type":3,"trainer":0,"start_date":1373069920,"utc_offset":25200,"moving_time":4763,"elapsed_time":5146,"distance":18514,"speed":13993,"elev_gain":570},{"id":65222304,"name":"Blackberry picking","workout_type":0,"trainer":0,"start_date":1373146467,"utc_offset":25200,"moving_time":5381,"elapsed_time":5483,"distance":15336,"speed":10260,"elev_gain":440},{"id":65389257,"name":"Slooooow Tam:38, Turnover on the down","workout_type":2,"trainer":0,"start_date":1373205314,"utc_offset":25200,"moving_time":8478,"elapsed_time":8849,"distance":27763,"speed":11789,"elev_gain":880}]},"moving_time":34513,"elapsed_time":37434,"distance":107897,"speed":11255,"elev_gain":3595},{"interval":"2013y28w","entry":{"activities":[{"id":65829037,"name":"1 min on/off fartlek (30 min) + 5x Gomez hill sprints","workout_type":3,"trainer":0,"start_date":1373374273,"utc_offset":25200,"moving_time":3740,"elapsed_time":3986,"distance":14231,"speed":13698,"elev_gain":172},{"id":66087018,"name":"Tam:39 Classic foggy/sunny summer morning","workout_type":0,"trainer":0,"start_date":1373460010,"utc_offset":25200,"moving_time":5733,"elapsed_time":5890,"distance":15112,"speed":9489,"elev_gain":720},{"id":66443637,"name":"Tam:39","workout_type":0,"trainer":0,"start_date":1373582590,"utc_offset":25200,"moving_time":5984,"elapsed_time":6302,"distance":16603,"speed":9988,"elev_gain":774},{"id":66649063,"name":"Tam:40 w/ Mackey","workout_type":0,"trainer":0,"start_date":1373669678,"utc_offset":25200,"moving_time":5746,"elapsed_time":6632,"distance":14783,"speed":9262,"elev_gain":788},{"id":66890076,"name":"Rip Van Sickle! Tahoe sweetness. ","workout_type":null,"trainer":0,"start_date":1373759093,"utc_offset":25200,"moving_time":6254,"elapsed_time":6586,"distance":18076,"speed":10405,"elev_gain":750},{"id":67124164,"name":"Big Day on the TRT! w/ Freel Peak bonus","workout_type":2,"trainer":0,"start_date":1373815997,"utc_offset":25200,"moving_time":14908,"elapsed_time":17682,"distance":42564,"speed":10278,"elev_gain":1736}]},"moving_time":42365,"elapsed_time":47078,"distance":121369,"speed":10313,"elev_gain":4940},{"interval":"2013y29w","entry":{"activities":[{"id":67262369,"name":"Cal-Neva Loop recovery w/ KB \u0026 bear sighting","workout_type":0,"trainer":0,"start_date":1373895729,"utc_offset":25200,"moving_time":2747,"elapsed_time":3094,"distance":7658,"speed":10036,"elev_gain":202},{"id":67557687,"name":"1 min on/off (30 min) + 5x Gomez hill sprints (corrupt GPS file)","workout_type":null,"trainer":0,"start_date":1373995756,"utc_offset":25200,"moving_time":3647,"elapsed_time":3647,"distance":14323,"speed":14138,"elev_gain":0},{"id":67764033,"name":"Tam:41 reprieve from the fog","workout_type":0,"trainer":0,"start_date":1374064254,"utc_offset":25200,"moving_time":5655,"elapsed_time":6297,"distance":14491,"speed":9225,"elev_gain":789},{"id":68151341,"name":"Ferry run commute","workout_type":null,"trainer":0,"start_date":1374198999,"utc_offset":25200,"moving_time":3069,"elapsed_time":3118,"distance":9680,"speed":11355,"elev_gain":110},{"id":68237059,"name":"Marincello Hill Repeats x 5","workout_type":3,"trainer":0,"start_date":1374238870,"utc_offset":25200,"moving_time":3836,"elapsed_time":4063,"distance":13727,"speed":12882,"elev_gain":447},{"id":68605558,"name":"MHBB -\u003E Tam:42 Widowmaker -\u003E Home","workout_type":0,"trainer":0,"start_date":1374366378,"utc_offset":25200,"moving_time":4712,"elapsed_time":5217,"distance":12622,"speed":9643,"elev_gain":816},{"id":68805647,"name":"07/21/2013 Stinson Beach, CA Warmup","workout_type":0,"trainer":0,"start_date":1374419918,"utc_offset":25200,"moving_time":511,"elapsed_time":539,"distance":1575,"speed":11100,"elev_gain":8},{"id":68805665,"name":"ITR Table Rock 25km - Win and 12min CR","workout_type":1,"trainer":0,"start_date":1374420778,"utc_offset":25200,"moving_time":6852,"elapsed_time":6872,"distance":26860,"speed":14112,"elev_gain":1102},{"id":68805641,"name":"07/21/2013 Stinson Beach, CA Cooldown","workout_type":0,"trainer":0,"start_date":1374428704,"utc_offset":25200,"moving_time":716,"elapsed_time":716,"distance":2162,"speed":10872,"elev_gain":15}]},"moving_time":31745,"elapsed_time":33563,"distance":103098,"speed":11692,"elev_gain":3489},{"interval":"2013y30w","entry":{"activities":[{"id":68973195,"name":"Tam:43 with Sir Rivers","workout_type":0,"trainer":0,"start_date":1374496585,"utc_offset":25200,"moving_time":5617,"elapsed_time":5952,"distance":14513,"speed":9301,"elev_gain":827},{"id":69207164,"name":"Progressively tempo-ish","workout_type":3,"trainer":0,"start_date":1374584441,"utc_offset":25200,"moving_time":3528,"elapsed_time":3646,"distance":13989,"speed":14274,"elev_gain":72},{"id":69725800,"name":"Travel hangover","workout_type":0,"trainer":0,"start_date":1374756935,"utc_offset":25200,"moving_time":4598,"elapsed_time":4648,"distance":14540,"speed":11384,"elev_gain":339},{"id":69939004,"name":"Marincello 800m Repeats x 5","workout_type":3,"trainer":0,"start_date":1374843336,"utc_offset":25200,"moving_time":3968,"elapsed_time":4150,"distance":14446,"speed":13107,"elev_gain":470},{"id":70303920,"name":"Tam:44","workout_type":0,"trainer":0,"start_date":1374967252,"utc_offset":25200,"moving_time":5302,"elapsed_time":5415,"distance":14591,"speed":9907,"elev_gain":770},{"id":70470723,"name":"Painting the mountain red, Tam:45 and 46","workout_type":2,"trainer":0,"start_date":1375019417,"utc_offset":25200,"moving_time":11766,"elapsed_time":12030,"distance":35413,"speed":10835,"elev_gain":1534}]},"moving_time":34779,"elapsed_time":35841,"distance":107492,"speed":11127,"elev_gain":4012},{"interval":"2013y31w","entry":{"activities":[{"id":70666539,"name":"Tam:47","workout_type":0,"trainer":0,"start_date":1375102121,"utc_offset":25200,"moving_time":5728,"elapsed_time":5759,"distance":14483,"speed":9103,"elev_gain":747},{"id":70897140,"name":"30 min x 1 min on/off fartlek + Gomez hill sprints","workout_type":3,"trainer":0,"start_date":1375188344,"utc_offset":25200,"moving_time":3781,"elapsed_time":3996,"distance":14725,"speed":14020,"elev_gain":183},{"id":71154562,"name":"Horse Hill and other random roads","workout_type":0,"trainer":0,"start_date":1375275038,"utc_offset":25200,"moving_time":4947,"elapsed_time":5066,"distance":16107,"speed":11721,"elev_gain":432},{"id":71762472,"name":"Friday Fun Tempo from SFRC","workout_type":3,"trainer":0,"start_date":1375488361,"utc_offset":25200,"moving_time":4218,"elapsed_time":4510,"distance":17104,"speed":14598,"elev_gain":554},{"id":71974410,"name":"Tam:48","workout_type":0,"trainer":0,"start_date":1375567531,"utc_offset":25200,"moving_time":5582,"elapsed_time":5712,"distance":14622,"speed":9430,"elev_gain":779},{"id":72151333,"name":"Tam:49 Railroad grade","workout_type":2,"trainer":0,"start_date":1375624162,"utc_offset":25200,"moving_time":7405,"elapsed_time":7661,"distance":25245,"speed":12273,"elev_gain":793}]},"moving_time":31661,"elapsed_time":32704,"distance":102286,"speed":11630,"elev_gain":3488},{"interval":"2013y32w","entry":{"activities":[{"id":72611518,"name":"Strides and a few Gomez sprints","workout_type":0,"trainer":0,"start_date":1375795569,"utc_offset":25200,"moving_time":2941,"elapsed_time":3189,"distance":10165,"speed":12442,"elev_gain":155},{"id":72878747,"name":"Tam:50","workout_type":0,"trainer":0,"start_date":1375878839,"utc_offset":25200,"moving_time":5686,"elapsed_time":6174,"distance":14527,"speed":9197,"elev_gain":797},{"id":73123272,"name":"Bike path with wifey","workout_type":0,"trainer":0,"start_date":1375967656,"utc_offset":25200,"moving_time":3449,"elapsed_time":3484,"distance":11633,"speed":12143,"elev_gain":51},{"id":73352131,"name":"Work hangover, some strides","workout_type":0,"trainer":0,"start_date":1376054285,"utc_offset":25200,"moving_time":2638,"elapsed_time":2762,"distance":9138,"speed":12471,"elev_gain":75},{"id":73730229,"name":"Tam:51 Next stop, the Rockies!","workout_type":0,"trainer":0,"start_date":1376179475,"utc_offset":25200,"moving_time":5022,"elapsed_time":5068,"distance":14378,"speed":10306,"elev_gain":841},{"id":73998305,"name":"Hello Colorado. ","workout_type":0,"trainer":0,"start_date":1376256699,"utc_offset":21600,"moving_time":3900,"elapsed_time":4080,"distance":9154,"speed":8450,"elev_gain":784}]},"moving_time":23636,"elapsed_time":24757,"distance":68995,"speed":10509,"elev_gain":2703},{"interval":"2013y33w","entry":{"activities":[{"id":74619821,"name":"Kohler Mesa sunrise jog","workout_type":0,"trainer":0,"start_date":1376483351,"utc_offset":21600,"moving_time":2089,"elapsed_time":2202,"distance":6873,"speed":11844,"elev_gain":189},{"id":74774334,"name":"Boulder Running Co / Strava fun run","workout_type":null,"trainer":0,"start_date":1376525815,"utc_offset":21600,"moving_time":2558,"elapsed_time":2604,"distance":8873,"speed":12487,"elev_gain":24},{"id":74878011,"name":"Koehler-Mesa-Skunk","workout_type":null,"trainer":0,"start_date":1376573600,"utc_offset":21600,"moving_time":2611,"elapsed_time":2727,"distance":7927,"speed":10930,"elev_gain":287},{"id":75112639,"name":"Fairview drills \u0026 strides. Still huffing and puffing.","workout_type":0,"trainer":0,"start_date":1376658772,"utc_offset":21600,"moving_time":2018,"elapsed_time":2864,"distance":6870,"speed":12255,"elev_gain":40},{"id":75690543,"name":"Pikes Peak Marathon - 4th place! Humbled but stoked to give it my all.","workout_type":1,"trainer":0,"start_date":1376830802,"utc_offset":21600,"moving_time":14111,"elapsed_time":14172,"distance":40953,"speed":10447,"elev_gain":2402}]},"moving_time":23387,"elapsed_time":24569,"distance":71496,"speed":11005,"elev_gain":2942},{"interval":"2013y34w","entry":{"activities":[{"id":77673098,"name":"Taking inventory","workout_type":0,"trainer":0,"start_date":1377376150,"utc_offset":25200,"moving_time":2117,"elapsed_time":2146,"distance":6860,"speed":11666,"elev_gain":127}]},"moving_time":2117,"elapsed_time":2146,"distance":6860,"speed":11666,"elev_gain":127},{"interval":"2013y35w","entry":{"activities":[{"id":77673077,"name":"Working the kinks out","workout_type":0,"trainer":0,"start_date":1377524665,"utc_offset":25200,"moving_time":1862,"elapsed_time":1862,"distance":6178,"speed":11946,"elev_gain":61},{"id":78338732,"name":"Ferry run commute","workout_type":null,"trainer":0,"start_date":1377739397,"utc_offset":25200,"moving_time":2115,"elapsed_time":2186,"distance":8602,"speed":14641,"elev_gain":51},{"id":78500153,"name":"Lunch Run to Coit Tower","workout_type":null,"trainer":0,"start_date":1377800027,"utc_offset":25200,"moving_time":1997,"elapsed_time":2027,"distance":6896,"speed":12432,"elev_gain":88},{"id":79061357,"name":"Struggling","workout_type":0,"trainer":0,"start_date":1377868006,"utc_offset":25200,"moving_time":1964,"elapsed_time":2018,"distance":5851,"speed":10724,"elev_gain":70},{"id":79061359,"name":"Summer time!","workout_type":0,"trainer":0,"start_date":1377994308,"utc_offset":25200,"moving_time":3002,"elapsed_time":3019,"distance":12586,"speed":15094,"elev_gain":137},{"id":79283058,"name":"Cypress","workout_type":0,"trainer":0,"start_date":1378058096,"utc_offset":25200,"moving_time":3255,"elapsed_time":3301,"distance":8918,"speed":9863,"elev_gain":220}]},"moving_time":14195,"elapsed_time":14413,"distance":49031,"speed":12435,"elev_gain":627},{"interval":"2013y36w","entry":{"activities":[{"id":79551533,"name":"Warmup","workout_type":0,"trainer":0,"start_date":1378132405,"utc_offset":25200,"moving_time":594,"elapsed_time":639,"distance":1659,"speed":10059,"elev_gain":26},{"id":79551551,"name":"Mt Tam Hill Climb - 1st Place","workout_type":1,"trainer":0,"start_date":1378134391,"utc_offset":25200,"moving_time":2007,"elapsed_time":2011,"distance":5218,"speed":9360,"elev_gain":733},{"id":79551530,"name":"Cooldown, running down the mountain","workout_type":0,"trainer":0,"start_date":1378138315,"utc_offset":25200,"moving_time":2996,"elapsed_time":3145,"distance":10818,"speed":12999,"elev_gain":6},{"id":79707703,"name":"Canyons","workout_type":null,"trainer":0,"start_date":1378213927,"utc_offset":25200,"moving_time":2705,"elapsed_time":2812,"distance":8966,"speed":11933,"elev_gain":133},{"id":80076758,"name":"Lunch Tour du Jour","workout_type":null,"trainer":0,"start_date":1378319234,"utc_offset":25200,"moving_time":4885,"elapsed_time":5307,"distance":18642,"speed":13738,"elev_gain":232},{"id":80488666,"name":"4 Corners Sunrise Slog","workout_type":0,"trainer":0,"start_date":1378473498,"utc_offset":25200,"moving_time":4004,"elapsed_time":4092,"distance":12214,"speed":10981,"elev_gain":333},{"id":80751567,"name":"First attempt at marathon training","workout_type":2,"trainer":0,"start_date":1378564602,"utc_offset":25200,"moving_time":6771,"elapsed_time":6995,"distance":27727,"speed":14742,"elev_gain":197},{"id":81145696,"name":"Cypress-Tenderfoot-Sun Trail","workout_type":0,"trainer":0,"start_date":1378680795,"utc_offset":25200,"moving_time":4069,"elapsed_time":4169,"distance":12138,"speed":10739,"elev_gain":341}]},"moving_time":28031,"elapsed_time":29170,"distance":97382,"speed":12507,"elev_gain":2001},{"interval":"2013y37w","entry":{"activities":[{"id":81244118,"name":"Anyone know of a good sports PT/chiro/body worker?","workout_type":0,"trainer":0,"start_date":1378732125,"utc_offset":25200,"moving_time":2965,"elapsed_time":2973,"distance":9024,"speed":10957,"elev_gain":193},{"id":81467106,"name":"Moderate cruise intervals 3/2 min x 5","workout_type":3,"trainer":0,"start_date":1378818532,"utc_offset":25200,"moving_time":3297,"elapsed_time":3503,"distance":12878,"speed":14062,"elev_gain":77},{"id":82066594,"name":"Run commute, feeling gimpy","workout_type":null,"trainer":0,"start_date":1379031075,"utc_offset":25200,"moving_time":6997,"elapsed_time":7389,"distance":25004,"speed":12865,"elev_gain":178},{"id":82393247,"name":"09/12/2013 San Francisco, CA","workout_type":null,"trainer":0,"start_date":1379031204,"utc_offset":25200,"moving_time":7182,"elapsed_time":7338,"distance":24117,"speed":12089,"elev_gain":331},{"id":82393415,"name":"Hamstrung","workout_type":0,"trainer":0,"start_date":1379171877,"utc_offset":25200,"moving_time":6154,"elapsed_time":6448,"distance":21616,"speed":12645,"elev_gain":268},{"id":82746672,"name":"Returning to an old favorite (Matt Davis-Troop80)","workout_type":0,"trainer":0,"start_date":1379284723,"utc_offset":25200,"moving_time":4926,"elapsed_time":5151,"distance":16598,"speed":12130,"elev_gain":531}]},"moving_time":31521,"elapsed_time":32802,"distance":109237,"speed":12476,"elev_gain":1578},{"interval":"2013y38w","entry":{"activities":[{"id":83105675,"name":"Middle Green Gulch Onsite ... to borrow from climbers parlance :)","workout_type":3,"trainer":0,"start_date":1379443634,"utc_offset":25200,"moving_time":5899,"elapsed_time":6192,"distance":21155,"speed":12910,"elev_gain":668},{"id":83244847,"name":"Tam:53 with the fellas!","workout_type":0,"trainer":0,"start_date":1379508634,"utc_offset":25200,"moving_time":5758,"elapsed_time":6506,"distance":14521,"speed":9078,"elev_gain":772},{"id":83448680,"name":"Pre-MRI dad's club track work","workout_type":3,"trainer":0,"start_date":1379596939,"utc_offset":25200,"moving_time":2873,"elapsed_time":3015,"distance":11285,"speed":14141,"elev_gain":47},{"id":83645348,"name":"Gift of Insomnia: Moonshine on the Mountain!","workout_type":0,"trainer":0,"start_date":1379677614,"utc_offset":25200,"moving_time":5692,"elapsed_time":5847,"distance":14406,"speed":9111,"elev_gain":720},{"id":83970777,"name":"Longish progression run, too much coffee","workout_type":3,"trainer":0,"start_date":1379795491,"utc_offset":25200,"moving_time":5609,"elapsed_time":5947,"distance":22901,"speed":14698,"elev_gain":236}]},"moving_time":25831,"elapsed_time":27507,"distance":84268,"speed":11744,"elev_gain":2443}]
[{"interval":"2013y01w","entry":{"activities":[{"id":39116559,"name":"12/31/2012","workout_type":null,"trainer":1,"start_date_local":"2012-12-31T00:00:00-08:00","moving_time":15629,"elapsed_time":15629,"distance":0,"speed":0,"elev_gain":0},{"id":39116547,"name":"12/31/2012","workout_type":null,"trainer":1,"start_date_local":"2012-12-31T04:59:07-08:00","moving_time":341,"elapsed_time":341,"distance":0,"speed":0,"elev_gain":0},{"id":53923115,"name":"Across The Years 24hr","workout_type":null,"trainer":0,"start_date_local":"2012-12-31T16:00:00-08:00","moving_time":86400,"elapsed_time":86400,"distance":175418,"speed":7309,"elev_gain":0}]},"moving_time":102370,"elapsed_time":102370,"distance":175418,"speed":6169,"elev_gain":0},{"interval":"2013y02w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y03w","entry":{"activities":[{"id":39116557,"name":"01/14/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-01-14T07:03:16-08:00","moving_time":3285,"elapsed_time":3285,"distance":9408,"speed":10310,"elev_gain":128},{"id":39116545,"name":"01/18/2013","workout_type":null,"trainer":1,"start_date_local":"2013-01-18T11:58:43-08:00","moving_time":2226,"elapsed_time":2226,"distance":0,"speed":0,"elev_gain":0},{"id":39116550,"name":"01/19/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-01-19T08:08:04-08:00","moving_time":3375,"elapsed_time":4875,"distance":10118,"speed":10792,"elev_gain":131},{"id":39116543,"name":"01/20/2013","workout_type":null,"trainer":1,"start_date_local":"2013-01-20T07:01:35-08:00","moving_time":4041,"elapsed_time":4041,"distance":0,"speed":0,"elev_gain":0}]},"moving_time":12927,"elapsed_time":14427,"distance":19526,"speed":5438,"elev_gain":259},{"interval":"2013y04w","entry":{"activities":[{"id":39116555,"name":"01/22/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-01-22T02:00:56-08:00","moving_time":4252,"elapsed_time":4252,"distance":13625,"speed":11536,"elev_gain":150},{"id":39116544,"name":"01/22/2013 Bend, OR","workout_type":0,"trainer":0,"start_date_local":"2013-01-22T04:35:10-08:00","moving_time":1235,"elapsed_time":1276,"distance":4109,"speed":11979,"elev_gain":39},{"id":39116541,"name":"01/22/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-01-22T05:19:35-08:00","moving_time":257,"elapsed_time":672,"distance":1322,"speed":18522,"elev_gain":62},{"id":39116542,"name":"01/22/2013 Bend, OR","workout_type":0,"trainer":0,"start_date_local":"2013-01-22T06:04:42-08:00","moving_time":1263,"elapsed_time":1263,"distance":3999,"speed":11399,"elev_gain":36},{"id":39116546,"name":"01/24/2013 Carlsbad, CA","workout_type":null,"trainer":0,"start_date_local":"2013-01-24T09:32:42-08:00","moving_time":3720,"elapsed_time":3720,"distance":13169,"speed":12744,"elev_gain":91},{"id":39116539,"name":"01/25/2013 Carlsbad, CA","workout_type":null,"trainer":0,"start_date_local":"2013-01-24T22:38:41-08:00","moving_time":3000,"elapsed_time":3525,"distance":8313,"speed":9976,"elev_gain":33},{"id":39116536,"name":"01/26/2013","workout_type":null,"trainer":1,"start_date_local":"2013-01-26T00:19:39-08:00","moving_time":516,"elapsed_time":516,"distance":0,"speed":0,"elev_gain":0},{"id":39116568,"name":"Carlsbad Marathon","workout_type":1,"trainer":0,"start_date_local":"2013-01-26T22:16:15-08:00","moving_time":9811,"elapsed_time":9811,"distance":42409,"speed":15561,"elev_gain":663}]},"moving_time":24054,"elapsed_time":25035,"distance":86946,"speed":13013,"elev_gain":1074},{"interval":"2013y05w","entry":{"activities":[{"id":44876723,"name":"01/29/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-01-29T05:53:19-08:00","moving_time":3428,"elapsed_time":3447,"distance":8447,"speed":8871,"elev_gain":77},{"id":44876724,"name":"01/31/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-01-31T01:32:44-08:00","moving_time":2885,"elapsed_time":2885,"distance":9075,"speed":11324,"elev_gain":180}]},"moving_time":6313,"elapsed_time":6332,"distance":17522,"speed":9992,"elev_gain":257},{"interval":"2013y06w","entry":{"activities":[{"id":44876717,"name":"02/10/2013","workout_type":null,"trainer":1,"start_date_local":"2013-02-10T00:57:43-08:00","moving_time":3,"elapsed_time":3,"distance":0,"speed":0,"elev_gain":0}]},"moving_time":3,"elapsed_time":3,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y07w","entry":{"activities":[{"id":44876735,"name":"02/13/2013 Moyogalpa, Rivas, Nicaragua","workout_type":null,"trainer":0,"start_date_local":"2013-02-13T03:24:38-08:00","moving_time":16846,"elapsed_time":17116,"distance":26145,"speed":5587,"elev_gain":334},{"id":44876715,"name":"02/14/2013 Moyogalpa, Rivas, Nicaragua","workout_type":null,"trainer":0,"start_date_local":"2013-02-14T03:10:43-08:00","moving_time":71,"elapsed_time":71,"distance":270,"speed":13694,"elev_gain":3},{"id":44876733,"name":"02/14/2013 Moyogalpa, Rivas, Nicaragua","workout_type":null,"trainer":0,"start_date_local":"2013-02-14T03:46:05-08:00","moving_time":10744,"elapsed_time":11842,"distance":17462,"speed":5851,"elev_gain":981},{"id":44876710,"name":"02/14/2013 Moyogalpa, Rivas, Nicaragua","workout_type":null,"trainer":0,"start_date_local":"2013-02-14T08:02:29-08:00","moving_time":121,"elapsed_time":121,"distance":406,"speed":12087,"elev_gain":0},{"id":44876713,"name":"02/14/2013 Moyogalpa, Rivas, Nicaragua","workout_type":null,"trainer":0,"start_date_local":"2013-02-14T08:18:53-08:00","moving_time":463,"elapsed_time":1260,"distance":2082,"speed":16195,"elev_gain":50}]},"moving_time":28245,"elapsed_time":30410,"distance":46365,"speed":5910,"elev_gain":1368},{"interval":"2013y08w","entry":{"activities":[{"id":44876716,"name":"02/24/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-02-24T06:21:35-08:00","moving_time":5471,"elapsed_time":5496,"distance":14797,"speed":9737,"elev_gain":389}]},"moving_time":5471,"elapsed_time":5496,"distance":14797,"speed":9737,"elev_gain":389},{"interval":"2013y09w","entry":{"activities":[{"id":44876709,"name":"02/27/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-02-27T02:19:17-08:00","moving_time":2618,"elapsed_time":2660,"distance":8449,"speed":11618,"elev_gain":81},{"id":44876712,"name":"02/28/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-02-28T06:15:40-08:00","moving_time":4945,"elapsed_time":7373,"distance":17325,"speed":12613,"elev_gain":302},{"id":44876725,"name":"03/01/2013 Terrebonne, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-01T04:36:33-08:00","moving_time":12807,"elapsed_time":12954,"distance":33362,"speed":9378,"elev_gain":1552},{"id":44876711,"name":"03/02/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-02T02:50:56-08:00","moving_time":4206,"elapsed_time":5337,"distance":5506,"speed":4713,"elev_gain":196},{"id":44876707,"name":"03/03/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-03T05:04:05-08:00","moving_time":6516,"elapsed_time":9545,"distance":22804,"speed":12599,"elev_gain":398}]},"moving_time":31092,"elapsed_time":37869,"distance":87446,"speed":10125,"elev_gain":2529},{"interval":"2013y10w","entry":{"activities":[{"id":44876697,"name":"03/04/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-04T08:11:10-08:00","moving_time":3146,"elapsed_time":3146,"distance":10032,"speed":11480,"elev_gain":86},{"id":44876689,"name":"03/05/2013","workout_type":null,"trainer":1,"start_date_local":"2013-03-05T04:28:42-08:00","moving_time":2539,"elapsed_time":2539,"distance":0,"speed":0,"elev_gain":0},{"id":44876692,"name":"03/05/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-05T09:52:09-08:00","moving_time":1548,"elapsed_time":1548,"distance":6799,"speed":15812,"elev_gain":64},{"id":44876696,"name":"03/06/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-06T07:28:38-08:00","moving_time":3714,"elapsed_time":3714,"distance":13003,"speed":12604,"elev_gain":276},{"id":44876686,"name":"03/08/2013","workout_type":null,"trainer":1,"start_date_local":"2013-03-08T08:46:08-08:00","moving_time":2617,"elapsed_time":2617,"distance":0,"speed":0,"elev_gain":0},{"id":44876694,"name":"03/09/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-09T07:57:57-08:00","moving_time":3851,"elapsed_time":3851,"distance":13003,"speed":12155,"elev_gain":259},{"id":44876699,"name":"03/10/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-10T09:10:27-07:00","moving_time":5246,"elapsed_time":5246,"distance":18105,"speed":12424,"elev_gain":543}]},"moving_time":22661,"elapsed_time":22661,"distance":60942,"speed":9681,"elev_gain":1228},{"interval":"2013y11w","entry":{"activities":[{"id":44876698,"name":"03/11/2013 Terrebonne, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-11T03:26:46-07:00","moving_time":6603,"elapsed_time":7137,"distance":13525,"speed":7374,"elev_gain":862},{"id":44876688,"name":"03/11/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-11T08:25:52-07:00","moving_time":3825,"elapsed_time":3899,"distance":6577,"speed":6190,"elev_gain":48},{"id":44876690,"name":"03/11/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-11T10:34:20-07:00","moving_time":4447,"elapsed_time":5538,"distance":12897,"speed":10441,"elev_gain":254},{"id":44876684,"name":"03/12/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-12T11:57:28-07:00","moving_time":1671,"elapsed_time":1671,"distance":5441,"speed":11723,"elev_gain":69},{"id":44876687,"name":"03/12/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-12T12:30:09-07:00","moving_time":167,"elapsed_time":3990,"distance":97,"speed":2093,"elev_gain":0},{"id":44876681,"name":"03/12/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-12T13:53:13-07:00","moving_time":1464,"elapsed_time":1504,"distance":4107,"speed":10100,"elev_gain":33},{"id":44876682,"name":"03/13/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-13T03:16:32-07:00","moving_time":3517,"elapsed_time":3517,"distance":11820,"speed":12099,"elev_gain":226},{"id":44876680,"name":"03/13/2013","workout_type":null,"trainer":1,"start_date_local":"2013-03-13T12:44:56-07:00","moving_time":564,"elapsed_time":564,"distance":0,"speed":0,"elev_gain":0},{"id":44876703,"name":"03/15/2013 Terrebonne, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-15T05:43:13-07:00","moving_time":12834,"elapsed_time":13155,"distance":33950,"speed":9523,"elev_gain":1732},{"id":44876678,"name":"03/16/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-16T11:27:48-07:00","moving_time":2871,"elapsed_time":3006,"distance":8472,"speed":10624,"elev_gain":110},{"id":44876679,"name":"03/17/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-17T04:11:56-07:00","moving_time":4910,"elapsed_time":4910,"distance":19323,"speed":14168,"elev_gain":195},{"id":44876677,"name":"03/17/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-17T09:37:43-07:00","moving_time":3255,"elapsed_time":3255,"distance":12881,"speed":14246,"elev_gain":278}]},"moving_time":46128,"elapsed_time":52146,"distance":129090,"speed":10075,"elev_gain":3807},{"interval":"2013y12w","entry":{"activities":[{"id":45604787,"name":"03/19/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-19T05:11:16-07:00","moving_time":4648,"elapsed_time":4648,"distance":14274,"speed":11056,"elev_gain":357},{"id":45604788,"name":"03/20/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-20T11:23:53-07:00","moving_time":5441,"elapsed_time":5512,"distance":16218,"speed":10730,"elev_gain":404},{"id":45604778,"name":"03/21/2013","workout_type":null,"trainer":1,"start_date_local":"2013-03-21T11:42:56-07:00","moving_time":2353,"elapsed_time":2353,"distance":0,"speed":0,"elev_gain":0},{"id":45604781,"name":"03/22/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-22T07:58:54-07:00","moving_time":3043,"elapsed_time":5425,"distance":9573,"speed":11325,"elev_gain":166},{"id":45604802,"name":"03/23/2013 Terrebonne, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-23T03:45:19-07:00","moving_time":13192,"elapsed_time":13382,"distance":33949,"speed":9264,"elev_gain":1786},{"id":46735288,"name":"03/24/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-24T08:33:25-07:00","moving_time":4202,"elapsed_time":4202,"distance":15526,"speed":13302,"elev_gain":380}]},"moving_time":32879,"elapsed_time":35522,"distance":89540,"speed":9804,"elev_gain":3093},{"interval":"2013y13w","entry":{"activities":[{"id":46735283,"name":"03/26/2013","workout_type":null,"trainer":1,"start_date_local":"2013-03-26T13:17:30-07:00","moving_time":2533,"elapsed_time":2533,"distance":0,"speed":0,"elev_gain":0},{"id":46735286,"name":"03/27/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-27T09:34:56-07:00","moving_time":3965,"elapsed_time":4095,"distance":11529,"speed":10468,"elev_gain":235},{"id":46735287,"name":"03/28/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-03-28T06:14:23-07:00","moving_time":6021,"elapsed_time":6108,"distance":19718,"speed":11789,"elev_gain":554},{"id":46735293,"name":"Gorge Waterfalls 50k","workout_type":1,"trainer":0,"start_date_local":"2013-03-30T01:05:26-07:00","moving_time":13052,"elapsed_time":13065,"distance":41649,"speed":11487,"elev_gain":1707}]},"moving_time":25571,"elapsed_time":25801,"distance":72896,"speed":10263,"elev_gain":2496},{"interval":"2013y14w","entry":{"activities":[{"id":47166411,"name":"04/03/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-03T10:39:58-07:00","moving_time":3372,"elapsed_time":3374,"distance":11678,"speed":12467,"elev_gain":230},{"id":47166407,"name":"04/03/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-03T11:58:54-07:00","moving_time":848,"elapsed_time":848,"distance":2796,"speed":11871,"elev_gain":52},{"id":47166405,"name":"04/03/2013","workout_type":null,"trainer":1,"start_date_local":"2013-04-03T12:18:48-07:00","moving_time":1229,"elapsed_time":1229,"distance":0,"speed":0,"elev_gain":0},{"id":58265650,"name":"Bend, OR","workout_type":0,"trainer":0,"start_date_local":"2013-04-06T05:31:12-07:00","moving_time":4042,"elapsed_time":4086,"distance":12994,"speed":11573,"elev_gain":292},{"id":48205439,"name":"04/06/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-06T11:47:03-07:00","moving_time":3469,"elapsed_time":4409,"distance":10213,"speed":10599,"elev_gain":140},{"id":48205442,"name":"Horse Butte 10 Miler","workout_type":1,"trainer":0,"start_date_local":"2013-04-07T02:00:13-07:00","moving_time":3797,"elapsed_time":3801,"distance":15936,"speed":15109,"elev_gain":278}]},"moving_time":16757,"elapsed_time":17747,"distance":53617,"speed":11519,"elev_gain":992},{"interval":"2013y15w","entry":{"activities":[{"id":48205438,"name":"04/08/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-08T02:20:03-07:00","moving_time":3929,"elapsed_time":3933,"distance":11620,"speed":10646,"elev_gain":364},{"id":48205424,"name":"04/09/2013","workout_type":null,"trainer":1,"start_date_local":"2013-04-09T12:23:33-07:00","moving_time":3977,"elapsed_time":3977,"distance":0,"speed":0,"elev_gain":0},{"id":48205431,"name":"04/10/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-10T04:28:33-07:00","moving_time":4079,"elapsed_time":5245,"distance":13102,"speed":11563,"elev_gain":218},{"id":48375289,"name":"04/11/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-11T09:34:59-07:00","moving_time":5167,"elapsed_time":5221,"distance":19349,"speed":13481,"elev_gain":535},{"id":48591552,"name":"04/12/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-12T11:07:00-07:00","moving_time":4824,"elapsed_time":4834,"distance":14903,"speed":11122,"elev_gain":395},{"id":48638897,"name":"04/13/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-13T04:20:42-07:00","moving_time":3370,"elapsed_time":3405,"distance":12055,"speed":12878,"elev_gain":233},{"id":48638895,"name":"04/13/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-13T05:21:19-07:00","moving_time":4194,"elapsed_time":4871,"distance":14321,"speed":12293,"elev_gain":257},{"id":48874594,"name":"04/14/2013 Sisters, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-14T02:08:56-07:00","moving_time":2379,"elapsed_time":2437,"distance":6911,"speed":10458,"elev_gain":19},{"id":48874606,"name":"04/14/2013 Sisters, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-14T02:58:56-07:00","moving_time":17456,"elapsed_time":17459,"distance":42170,"speed":8696,"elev_gain":611}]},"moving_time":49375,"elapsed_time":51382,"distance":134431,"speed":9802,"elev_gain":2632},{"interval":"2013y16w","entry":{"activities":[{"id":48957315,"name":"04/15/2013 Bend, OR","workout_type":null,"trainer":0,"start_date_local":"2013-04-15T00:31:51-07:00","moving_time":1852,"elapsed_time":1905,"distance":5466,"speed":10626,"elev_gain":168},{"id":49631667,"name":"04/18/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-18T04:09:15-07:00","moving_time":2909,"elapsed_time":2909,"distance":8465,"speed":10476,"elev_gain":61},{"id":49631666,"name":"04/19/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-19T09:58:41-07:00","moving_time":3646,"elapsed_time":3738,"distance":12324,"speed":12169,"elev_gain":85},{"id":49780428,"name":"Mt Diablo Trails Challenge 50k","workout_type":1,"trainer":0,"start_date_local":"2013-04-20T00:01:58-07:00","moving_time":15283,"elapsed_time":15314,"distance":50234,"speed":11833,"elev_gain":1967},{"id":49780398,"name":"04/20/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-20T05:57:34-07:00","moving_time":3205,"elapsed_time":3244,"distance":9100,"speed":10221,"elev_gain":21},{"id":50305533,"name":"04/21/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-21T04:17:19-07:00","moving_time":2241,"elapsed_time":2241,"distance":6600,"speed":10603,"elev_gain":59}]},"moving_time":29136,"elapsed_time":29351,"distance":92189,"speed":11391,"elev_gain":2361},{"interval":"2013y17w","entry":{"activities":[{"id":50305530,"name":"04/22/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-22T13:23:44-07:00","moving_time":3532,"elapsed_time":3532,"distance":9368,"speed":9548,"elev_gain":77},{"id":50305526,"name":"04/23/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-23T04:08:45-07:00","moving_time":2123,"elapsed_time":2123,"distance":8287,"speed":14053,"elev_gain":58},{"id":50482584,"name":"04/24/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-24T03:33:14-07:00","moving_time":2795,"elapsed_time":2795,"distance":11269,"speed":14515,"elev_gain":135},{"id":50825645,"name":"04/25/2013","workout_type":0,"trainer":1,"start_date_local":"2013-04-25T03:08:37-07:00","moving_time":2311,"elapsed_time":2311,"distance":0,"speed":0,"elev_gain":0},{"id":50825646,"name":"04/26/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-26T02:39:47-07:00","moving_time":857,"elapsed_time":876,"distance":2427,"speed":10195,"elev_gain":30},{"id":50825651,"name":"04/26/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-26T03:24:59-07:00","moving_time":3164,"elapsed_time":3639,"distance":10039,"speed":11422,"elev_gain":76},{"id":50980776,"name":"04/26/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-26T10:17:50-07:00","moving_time":7695,"elapsed_time":7710,"distance":13366,"speed":6253,"elev_gain":85},{"id":50980773,"name":"04/27/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-27T01:47:24-07:00","moving_time":2656,"elapsed_time":2656,"distance":9129,"speed":12374,"elev_gain":93},{"id":51264182,"name":"Big Sur Marathon, CA","workout_type":1,"trainer":0,"start_date_local":"2013-04-27T23:45:04-07:00","moving_time":9626,"elapsed_time":9626,"distance":42274,"speed":15810,"elev_gain":623}]},"moving_time":34759,"elapsed_time":35268,"distance":106159,"speed":10995,"elev_gain":1177},{"interval":"2013y18w","entry":{"activities":[{"id":51855819,"name":"04/30/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-30T10:58:29-07:00","moving_time":2927,"elapsed_time":2927,"distance":9098,"speed":11189,"elev_gain":100},{"id":51855839,"name":"05/01/2013 Mt Diablo summit hike and jog back down, CA","workout_type":0,"trainer":0,"start_date_local":"2013-05-01T08:56:54-07:00","moving_time":12126,"elapsed_time":12131,"distance":29094,"speed":8637,"elev_gain":1337},{"id":54925391,"name":"Treadmill uphill mile","workout_type":0,"trainer":1,"start_date_local":"2013-05-02T08:00:00-07:00","moving_time":600,"elapsed_time":600,"distance":1609,"speed":9656,"elev_gain":0},{"id":52108752,"name":"05/03/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-05-03T01:11:44-07:00","moving_time":2524,"elapsed_time":2527,"distance":8945,"speed":12759,"elev_gain":107},{"id":52396577,"name":"Treadmill uphill run","workout_type":null,"trainer":0,"start_date_local":"2013-05-03T10:00:00-07:00","moving_time":3600,"elapsed_time":3600,"distance":10460,"speed":10460,"elev_gain":0},{"id":52381885,"name":"Miwok 100k - shortened to 60k, CA","workout_type":1,"trainer":0,"start_date_local":"2013-05-04T01:01:03-07:00","moving_time":18851,"elapsed_time":18915,"distance":61904,"speed":11821,"elev_gain":2349},{"id":53141804,"name":"Recovery treadmill run with hill","workout_type":0,"trainer":1,"start_date_local":"2013-05-05T14:00:00-07:00","moving_time":1500,"elapsed_time":1500,"distance":4023,"speed":9656,"elev_gain":0}]},"moving_time":42128,"elapsed_time":42200,"distance":125133,"speed":10693,"elev_gain":3893},{"interval":"2013y19w","entry":{"activities":[{"id":52795835,"name":"05/06/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-05-06T10:13:26-07:00","moving_time":2817,"elapsed_time":2832,"distance":9099,"speed":11628,"elev_gain":82},{"id":52909767,"name":"05/07/2013 Walnut Creek, CA","workout_type":0,"trainer":0,"start_date_local":"2013-05-07T03:21:48-07:00","moving_time":1238,"elapsed_time":1238,"distance":4782,"speed":13905,"elev_gain":38},{"id":53125654,"name":"05/07/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-05-07T15:36:33-07:00","moving_time":3360,"elapsed_time":3393,"distance":9041,"speed":9687,"elev_gain":79},{"id":53125655,"name":"05/08/2013 Walnut Creek, CA","workout_type":0,"trainer":0,"start_date_local":"2013-05-08T04:08:16-07:00","moving_time":4327,"elapsed_time":4350,"distance":15057,"speed":12527,"elev_gain":222},{"id":53315892,"name":"05/09/2013 Downhill speed session on Mt Diablo","workout_type":null,"trainer":0,"start_date_local":"2013-05-09T04:44:05-07:00","moving_time":4378,"elapsed_time":4378,"distance":16152,"speed":13281,"elev_gain":572},{"id":53355790,"name":"05/09/2013 Walnut Creek, CA","workout_type":null,"trainer":0,"start_date_local":"2013-05-09T10:05:37-07:00","moving_time":3433,"elapsed_time":3459,"distance":11388,"speed":11941,"elev_gain":317},{"id":53521765,"name":"Recovery run to post office","workout_type":0,"trainer":0,"start_date_local":"2013-05-10T05:09:29-07:00","moving_time":3464,"elapsed_time":3606,"distance":10186,"speed":10586,"elev_gain":82},{"id":53521767,"name":"Uphill hard efforts","workout_type":0,"trainer":0,"start_date_local":"2013-05-10T11:11:28-07:00","moving_time":3588,"elapsed_time":3588,"distance":12071,"speed":12112,"elev_gain":371},{"id":53667927,"name":"Cinderella Trail Run 50k CR","workout_type":1,"trainer":0,"start_date_local":"2013-05-11T01:00:05-07:00","moving_time":15224,"elapsed_time":15463,"distance":46550,"speed":11007,"elev_gain":1823},{"id":53698251,"name":"Shake-out run","workout_type":null,"trainer":0,"start_date_local":"2013-05-11T10:56:39-07:00","moving_time":1520,"elapsed_time":1520,"distance":4346,"speed":10293,"elev_gain":29},{"id":53876989,"name":"Recovery hike","workout_type":0,"trainer":0,"start_date_local":"2013-05-12T02:28:21-07:00","moving_time":3439,"elapsed_time":3882,"distance":4187,"speed":4383,"elev_gain":180},{"id":53915507,"name":"Recovery run","workout_type":null,"trainer":0,"start_date_local":"2013-05-12T13:23:13-07:00","moving_time":2680,"elapsed_time":2680,"distance":7296,"speed":9801,"elev_gain":61}]},"moving_time":49468,"elapsed_time":50389,"distance":150155,"speed":10927,"elev_gain":3856},{"interval":"2013y20w","entry":{"activities":[{"id":54084894,"name":"Recovery run","workout_type":null,"trainer":0,"start_date_local":"2013-05-13T10:49:18-07:00","moving_time":2833,"elapsed_time":2881,"distance":7546,"speed":9589,"elev_gain":86},{"id":54176823,"name":"Medium pace flat run with some fast sections thrown in","workout_type":null,"trainer":0,"start_date_local":"2013-05-14T02:41:56-07:00","moving_time":3696,"elapsed_time":3722,"distance":14608,"speed":14228,"elev_gain":175},{"id":54247547,"name":"Pleasant Hill jog","workout_type":null,"trainer":0,"start_date_local":"2013-05-14T09:52:41-07:00","moving_time":3595,"elapsed_time":3665,"distance":11669,"speed":11685,"elev_gain":276},{"id":54355774,"name":"Recovery run plus short speed test - legs felt heavy","workout_type":0,"trainer":0,"start_date_local":"2013-05-15T02:53:28-07:00","moving_time":2780,"elapsed_time":2780,"distance":8507,"speed":11017,"elev_gain":91},{"id":54595025,"name":"Shake-out morning run","workout_type":null,"trainer":0,"start_date_local":"2013-05-16T02:01:48-07:00","moving_time":2864,"elapsed_time":2866,"distance":8080,"speed":10157,"elev_gain":91},{"id":54595012,"name":"Jog","workout_type":null,"trainer":0,"start_date_local":"2013-05-16T03:53:10-07:00","moving_time":686,"elapsed_time":686,"distance":2041,"speed":10715,"elev_gain":4},{"id":54610073,"name":"Jog","workout_type":null,"trainer":0,"start_date_local":"2013-05-16T04:29:36-07:00","moving_time":682,"elapsed_time":712,"distance":1946,"speed":10274,"elev_gain":37},{"id":54595018,"name":"Speed session to top of local hills","workout_type":null,"trainer":0,"start_date_local":"2013-05-16T08:18:57-07:00","moving_time":2845,"elapsed_time":2845,"distance":11785,"speed":14912,"elev_gain":282},{"id":54759637,"name":"Diablo jog/hike","workout_type":null,"trainer":0,"start_date_local":"2013-05-17T04:09:04-07:00","moving_time":13137,"elapsed_time":13297,"distance":29311,"speed":8032,"elev_gain":1254},{"id":54781443,"name":"Shake out run","workout_type":null,"trainer":0,"start_date_local":"2013-05-17T11:25:23-07:00","moving_time":1408,"elapsed_time":1673,"distance":5189,"speed":13268,"elev_gain":39},{"id":54918595,"name":"Mile reps","workout_type":null,"trainer":0,"start_date_local":"2013-05-18T04:42:31-07:00","moving_time":2495,"elapsed_time":2495,"distance":10420,"speed":15035,"elev_gain":130}]},"moving_time":37021,"elapsed_time":37622,"distance":111102,"speed":10804,"elev_gain":2465},{"interval":"2013y21w","entry":{"activities":[{"id":58265656,"name":"Cusco, Cuzco Region, Peru","workout_type":0,"trainer":0,"start_date_local":"2013-05-20T07:17:28-07:00","moving_time":4264,"elapsed_time":4354,"distance":8855,"speed":7476,"elev_gain":361},{"id":58265677,"name":"Machu Picchu","workout_type":0,"trainer":0,"start_date_local":"2013-05-21T23:35:58-07:00","moving_time":17681,"elapsed_time":34125,"distance":22455,"speed":4572,"elev_gain":1291},{"id":58265658,"name":"Aguas Calientes, Cuzco Region, Peru","workout_type":0,"trainer":0,"start_date_local":"2013-05-22T23:51:51-07:00","moving_time":12837,"elapsed_time":16865,"distance":18387,"speed":5156,"elev_gain":1108},{"id":58265639,"name":"Cusco, Cuzco Region, Peru","workout_type":0,"trainer":0,"start_date_local":"2013-05-24T04:33:18-07:00","moving_time":4127,"elapsed_time":4854,"distance":8908,"speed":7771,"elev_gain":455},{"id":58265664,"name":"Jungle Ultra stage 1","workout_type":0,"trainer":0,"start_date_local":"2013-05-26T02:31:55-07:00","moving_time":11298,"elapsed_time":11343,"distance":34270,"speed":10919,"elev_gain":447}]},"moving_time":50207,"elapsed_time":71541,"distance":92875,"speed":6659,"elev_gain":3662},{"interval":"2013y22w","entry":{"activities":[{"id":58264955,"name":"Jungle Ultra stage 2","workout_type":0,"trainer":0,"start_date_local":"2013-05-27T01:32:14-07:00","moving_time":10590,"elapsed_time":10830,"distance":30158,"speed":10252,"elev_gain":751},{"id":58263613,"name":"Jungle Ultra stage 3","workout_type":0,"trainer":0,"start_date_local":"2013-05-28T02:01:05-07:00","moving_time":13748,"elapsed_time":13947,"distance":31813,"speed":8330,"elev_gain":667},{"id":58264943,"name":"Jungle Ultra stage 4","workout_type":0,"trainer":0,"start_date_local":"2013-05-29T00:15:28-07:00","moving_time":13016,"elapsed_time":21191,"distance":18931,"speed":5236,"elev_gain":807},{"id":58263571,"name":"Recovery run in the jungle","workout_type":0,"trainer":0,"start_date_local":"2013-05-30T09:25:55-07:00","moving_time":3644,"elapsed_time":3644,"distance":8845,"speed":8738,"elev_gain":85},{"id":58263566,"name":"Cusco, Cuzco Region, Peru","workout_type":0,"trainer":0,"start_date_local":"2013-06-01T09:35:14-07:00","moving_time":2931,"elapsed_time":3146,"distance":8303,"speed":10198,"elev_gain":354}]},"moving_time":43929,"elapsed_time":52758,"distance":98050,"speed":8035,"elev_gain":2664},{"interval":"2013y23w","entry":{"activities":[{"id":58263579,"name":"Cusco, Cuzco Region, Peru","workout_type":0,"trainer":0,"start_date_local":"2013-06-03T00:04:38-07:00","moving_time":3694,"elapsed_time":4089,"distance":11367,"speed":11077,"elev_gain":425},{"id":58517573,"name":"Shake out run","workout_type":0,"trainer":0,"start_date_local":"2013-06-05T08:17:52-07:00","moving_time":2672,"elapsed_time":2672,"distance":9669,"speed":13027,"elev_gain":122},{"id":58517572,"name":"Pleasant Hill speed session","workout_type":0,"trainer":0,"start_date_local":"2013-06-05T11:55:11-07:00","moving_time":2675,"elapsed_time":2675,"distance":11341,"speed":15263,"elev_gain":294},{"id":58517567,"name":"Recovery jog","workout_type":0,"trainer":0,"start_date_local":"2013-06-05T12:39:55-07:00","moving_time":1009,"elapsed_time":1035,"distance":3316,"speed":11831,"elev_gain":28},{"id":59617122,"name":"Pleasant Hill hike with weight vest","workout_type":0,"trainer":0,"start_date_local":"2013-06-09T12:26:36-07:00","moving_time":7261,"elapsed_time":7293,"distance":12102,"speed":6000,"elev_gain":300}]},"moving_time":17311,"elapsed_time":17764,"distance":47795,"speed":9939,"elev_gain":1169},{"interval":"2013y24w","entry":{"activities":[{"id":59617135,"name":"Diablo hike that turned into a run","workout_type":0,"trainer":0,"start_date_local":"2013-06-10T06:20:08-07:00","moving_time":13238,"elapsed_time":13407,"distance":29314,"speed":7971,"elev_gain":1292},{"id":59823429,"name":"Mt Diablo North and Main Summit Hike","workout_type":0,"trainer":0,"start_date_local":"2013-06-11T05:12:16-07:00","moving_time":15950,"elapsed_time":16431,"distance":25908,"speed":5847,"elev_gain":1366},{"id":60020188,"name":"Pleasant Hill route to test running on a paved surface","workout_type":0,"trainer":0,"start_date_local":"2013-06-12T08:49:59-07:00","moving_time":4743,"elapsed_time":4760,"distance":15133,"speed":11486,"elev_gain":345},{"id":60177683,"name":"Warm-up to Mitchell Canyon parking lot","workout_type":0,"trainer":0,"start_date_local":"2013-06-13T04:37:17-07:00","moving_time":514,"elapsed_time":514,"distance":1637,"speed":11468,"elev_gain":27},{"id":60177694,"name":"Speed attempt to summit and descend Diablo","workout_type":0,"trainer":0,"start_date_local":"2013-06-13T04:49:44-07:00","moving_time":7398,"elapsed_time":7398,"distance":25022,"speed":12176,"elev_gain":1179},{"id":60177679,"name":"Warm down jog back to car","workout_type":0,"trainer":0,"start_date_local":"2013-06-13T06:55:10-07:00","moving_time":496,"elapsed_time":496,"distance":1680,"speed":12195,"elev_gain":19},{"id":60755418,"name":"Walk/jog to pick up race number for SF marathon.","workout_type":0,"trainer":0,"start_date_local":"2013-06-14T07:47:43-07:00","moving_time":4855,"elapsed_time":5433,"distance":7022,"speed":5207,"elev_gain":93},{"id":60755402,"name":"Recovery pace with 100-200m strides to prepare for SF marathon.","workout_type":0,"trainer":0,"start_date_local":"2013-06-15T04:16:53-07:00","moving_time":2811,"elapsed_time":2811,"distance":9168,"speed":11741,"elev_gain":106},{"id":60755392,"name":"Warm-up jog.","workout_type":0,"trainer":0,"start_date_local":"2013-06-15T21:28:16-07:00","moving_time":372,"elapsed_time":372,"distance":990,"speed":9580,"elev_gain":6},{"id":60755494,"name":"San Francisco Marathon","workout_type":1,"trainer":0,"start_date_local":"2013-06-15T22:30:16-07:00","moving_time":9822,"elapsed_time":9939,"distance":42419,"speed":15547,"elev_gain":600}]},"moving_time":60199,"elapsed_time":61561,"distance":158293,"speed":9466,"elev_gain":5033},{"interval":"2013y25w","entry":{"activities":[{"id":61575810,"name":"Recovery jog","workout_type":0,"trainer":0,"start_date_local":"2013-06-18T07:41:58-07:00","moving_time":1927,"elapsed_time":1927,"distance":5606,"speed":10473,"elev_gain":38},{"id":61575812,"name":"Pleasant Hill jog","workout_type":0,"trainer":0,"start_date_local":"2013-06-19T09:48:46-07:00","moving_time":3265,"elapsed_time":3265,"distance":11380,"speed":12548,"elev_gain":240},{"id":61785977,"name":"Warm-up outside then treadmill hill reps and 1 hard mile","workout_type":0,"trainer":0,"start_date_local":"2013-06-20T09:17:42-07:00","moving_time":1048,"elapsed_time":3409,"distance":3527,"speed":12116,"elev_gain":73},{"id":62136435,"name":"Last heat run, dressed like the Michelin man","workout_type":0,"trainer":0,"start_date_local":"2013-06-22T03:01:48-07:00","moving_time":3209,"elapsed_time":3209,"distance":11374,"speed":12760,"elev_gain":108},{"id":63925055,"name":"Untitled","workout_type":null,"trainer":0,"start_date_local":"2013-06-23T04:19:28-07:00","moving_time":11129,"elapsed_time":12164,"distance":16608,"speed":5372,"elev_gain":1063}]},"moving_time":20578,"elapsed_time":23974,"distance":48495,"speed":8484,"elev_gain":1522},{"interval":"2013y26w","entry":{"activities":[{"id":63921438,"name":"Easy jog at Tahoe","workout_type":0,"trainer":0,"start_date_local":"2013-06-25T02:07:29-07:00","moving_time":2534,"elapsed_time":2536,"distance":8848,"speed":12570,"elev_gain":248},{"id":63921439,"name":"Mini hike up to near TRT","workout_type":0,"trainer":0,"start_date_local":"2013-06-25T06:38:51-07:00","moving_time":2084,"elapsed_time":2211,"distance":2935,"speed":5071,"elev_gain":347},{"id":63921441,"name":"Tahoe Rim Trail hike/jog","workout_type":0,"trainer":0,"start_date_local":"2013-06-26T06:40:24-07:00","moving_time":6323,"elapsed_time":6327,"distance":12745,"speed":7256,"elev_gain":486},{"id":63921436,"name":"Hike up Emigrants Pass","workout_type":0,"trainer":0,"start_date_local":"2013-06-27T03:08:05-07:00","moving_time":4836,"elapsed_time":4838,"distance":6179,"speed":4599,"elev_gain":699},{"id":63921494,"name":"Western States 100","workout_type":1,"trainer":0,"start_date_local":"2013-06-28T22:00:01-07:00","moving_time":58828,"elapsed_time":58877,"distance":158639,"speed":9707,"elev_gain":5407}]},"moving_time":74605,"elapsed_time":74789,"distance":189346,"speed":9137,"elev_gain":7187},{"interval":"2013y27w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y28w","entry":{"activities":[{"id":65919199,"name":"Running again","workout_type":0,"trainer":0,"start_date_local":"2013-07-08T10:09:30-07:00","moving_time":3294,"elapsed_time":3297,"distance":9833,"speed":10746,"elev_gain":47},{"id":66548723,"name":"Walk","workout_type":0,"trainer":0,"start_date_local":"2013-07-11T09:06:56-07:00","moving_time":6558,"elapsed_time":6560,"distance":9068,"speed":4978,"elev_gain":72},{"id":66548719,"name":"Sports Basement jog","workout_type":0,"trainer":0,"start_date_local":"2013-07-11T11:53:10-07:00","moving_time":1790,"elapsed_time":1793,"distance":5887,"speed":11840,"elev_gain":61},{"id":66759331,"name":"Pleasant Hill route","workout_type":0,"trainer":0,"start_date_local":"2013-07-12T23:52:59-07:00","moving_time":2945,"elapsed_time":2947,"distance":11297,"speed":13810,"elev_gain":265},{"id":69159262,"name":"Vegas jog","workout_type":0,"trainer":0,"start_date_local":"2013-07-13T23:51:25-07:00","moving_time":3051,"elapsed_time":3081,"distance":8862,"speed":10456,"elev_gain":55}]},"moving_time":17638,"elapsed_time":17678,"distance":44947,"speed":9174,"elev_gain":500},{"interval":"2013y29w","entry":{"activities":[{"id":69091177,"name":"Pacing at Badwater 135","workout_type":0,"trainer":0,"start_date_local":"2013-07-15T06:00:09-07:00","moving_time":9393,"elapsed_time":14323,"distance":20052,"speed":7685,"elev_gain":258},{"id":69091181,"name":"Pacing at Badwater 135","workout_type":0,"trainer":0,"start_date_local":"2013-07-15T18:51:12-07:00","moving_time":11462,"elapsed_time":36000,"distance":22621,"speed":7105,"elev_gain":644},{"id":69091171,"name":"Run up part way to Mt Whitney then back down post BW","workout_type":0,"trainer":0,"start_date_local":"2013-07-16T22:23:05-07:00","moving_time":3712,"elapsed_time":3737,"distance":12081,"speed":11717,"elev_gain":316},{"id":69091167,"name":"Easy jog up in New Hampshire before Vermont 100","workout_type":0,"trainer":0,"start_date_local":"2013-07-18T10:14:17-07:00","moving_time":2770,"elapsed_time":2773,"distance":8857,"speed":11511,"elev_gain":100},{"id":69091265,"name":"Vermont 100","workout_type":1,"trainer":0,"start_date_local":"2013-07-19T20:59:56-07:00","moving_time":57465,"elapsed_time":57517,"distance":159358,"speed":9983,"elev_gain":4682}]},"moving_time":84802,"elapsed_time":114350,"distance":222969,"speed":9465,"elev_gain":6000},{"interval":"2013y30w","entry":{"activities":[{"id":70318745,"name":"First run since Vermont 100","workout_type":0,"trainer":0,"start_date_local":"2013-07-27T12:22:43-07:00","moving_time":3173,"elapsed_time":3176,"distance":9178,"speed":10414,"elev_gain":87}]},"moving_time":3173,"elapsed_time":3176,"distance":9178,"speed":10413,"elev_gain":87},{"interval":"2013y31w","entry":{"activities":[{"id":71300623,"name":"Pleasant Hill test run","workout_type":0,"trainer":0,"start_date_local":"2013-07-31T10:45:11-07:00","moving_time":3208,"elapsed_time":3211,"distance":11374,"speed":12763,"elev_gain":276},{"id":71557202,"name":"Sports Basement jog","workout_type":0,"trainer":0,"start_date_local":"2013-08-01T11:36:13-07:00","moving_time":2624,"elapsed_time":2626,"distance":8268,"speed":11344,"elev_gain":178},{"id":72421755,"name":"Jog in Durango","workout_type":0,"trainer":0,"start_date_local":"2013-08-03T06:43:21-07:00","moving_time":3138,"elapsed_time":3140,"distance":10702,"speed":12278,"elev_gain":142},{"id":72421757,"name":"Hike/jog around Durango and Animas Mt","workout_type":0,"trainer":0,"start_date_local":"2013-08-04T07:42:45-07:00","moving_time":6359,"elapsed_time":6363,"distance":12042,"speed":6817,"elev_gain":404}]},"moving_time":15329,"elapsed_time":15340,"distance":42386,"speed":9954,"elev_gain":1000},{"interval":"2013y32w","entry":{"activities":[{"id":72478429,"name":"Durango hilly run with Meissner","workout_type":0,"trainer":0,"start_date_local":"2013-08-05T08:28:53-07:00","moving_time":3050,"elapsed_time":3281,"distance":8079,"speed":9535,"elev_gain":416},{"id":73235983,"name":"Hiking/jogging in the San Juans","workout_type":0,"trainer":0,"start_date_local":"2013-08-07T05:09:04-07:00","moving_time":17156,"elapsed_time":17163,"distance":20422,"speed":4285,"elev_gain":1118},{"id":73235987,"name":"Hiking/jogging in the San Juans","workout_type":0,"trainer":0,"start_date_local":"2013-08-08T01:47:20-07:00","moving_time":21040,"elapsed_time":21047,"distance":26058,"speed":4458,"elev_gain":1755},{"id":73968842,"name":"Telluride jog with Ellie","workout_type":0,"trainer":0,"start_date_local":"2013-08-10T12:24:04-07:00","moving_time":2710,"elapsed_time":2712,"distance":7782,"speed":10338,"elev_gain":166},{"id":73968862,"name":"Sweeping a section of the Telluride Mt Run course","workout_type":0,"trainer":0,"start_date_local":"2013-08-11T01:45:14-07:00","moving_time":16556,"elapsed_time":16563,"distance":16424,"speed":3571,"elev_gain":1298}]},"moving_time":60512,"elapsed_time":60766,"distance":78765,"speed":4686,"elev_gain":4753},{"interval":"2013y33w","entry":{"activities":[{"id":74238197,"name":"More hiking in the San Juans","workout_type":0,"trainer":0,"start_date_local":"2013-08-12T03:01:24-07:00","moving_time":8780,"elapsed_time":8783,"distance":10396,"speed":4262,"elev_gain":675},{"id":74465613,"name":"Run/hike up Animas Mt, Durango","workout_type":0,"trainer":0,"start_date_local":"2013-08-13T05:31:42-07:00","moving_time":2991,"elapsed_time":3006,"distance":7306,"speed":8794,"elev_gain":488},{"id":74465607,"name":"Walking on top of Animas Mt, Durango","workout_type":0,"trainer":0,"start_date_local":"2013-08-13T06:23:11-07:00","moving_time":803,"elapsed_time":979,"distance":1393,"speed":6248,"elev_gain":39},{"id":74465610,"name":"Jog down Animas Mt, Durango","workout_type":0,"trainer":0,"start_date_local":"2013-08-13T06:53:38-07:00","moving_time":1713,"elapsed_time":1713,"distance":6507,"speed":13676,"elev_gain":19},{"id":74880414,"name":"Gentle last run pre-Leadville","workout_type":0,"trainer":0,"start_date_local":"2013-08-15T00:43:04-07:00","moving_time":2389,"elapsed_time":2391,"distance":7035,"speed":10601,"elev_gain":72},{"id":75597891,"name":"Leadville Trail 100","workout_type":1,"trainer":0,"start_date_local":"2013-08-16T21:00:09-07:00","moving_time":59412,"elapsed_time":59461,"distance":157909,"speed":9568,"elev_gain":4988}]},"moving_time":76088,"elapsed_time":76333,"distance":190546,"speed":9015,"elev_gain":6281},{"interval":"2013y34w","entry":{"activities":[{"id":77178959,"name":"Easy jog, starting with Amy","workout_type":0,"trainer":0,"start_date_local":"2013-08-24T01:59:26-07:00","moving_time":3440,"elapsed_time":3442,"distance":9852,"speed":10310,"elev_gain":109}]},"moving_time":3440,"elapsed_time":3442,"distance":9852,"speed":10310,"elev_gain":109},{"interval":"2013y35w","entry":{"activities":[{"id":77994771,"name":"Pleasant Hills easy jog that became harder","workout_type":0,"trainer":0,"start_date_local":"2013-08-27T04:08:41-07:00","moving_time":3247,"elapsed_time":3251,"distance":11374,"speed":12610,"elev_gain":258},{"id":78582459,"name":"Easy recovery run","workout_type":0,"trainer":0,"start_date_local":"2013-08-29T10:02:43-07:00","moving_time":3298,"elapsed_time":3300,"distance":10239,"speed":11177,"elev_gain":114},{"id":78767193,"name":"Hike up Diablo, run down","workout_type":0,"trainer":0,"start_date_local":"2013-08-30T02:40:36-07:00","moving_time":11042,"elapsed_time":11053,"distance":26707,"speed":8707,"elev_gain":1204},{"id":79780844,"name":"Recovery jog","workout_type":0,"trainer":0,"start_date_local":"2013-09-01T01:48:34-07:00","moving_time":2037,"elapsed_time":2039,"distance":6532,"speed":11544,"elev_gain":85}]},"moving_time":19624,"elapsed_time":19643,"distance":54852,"speed":10063,"elev_gain":1661},{"interval":"2013y36w","entry":{"activities":[{"id":79780846,"name":"Jog then walk with weight vest to Safeway","workout_type":0,"trainer":0,"start_date_local":"2013-09-02T10:45:07-07:00","moving_time":5712,"elapsed_time":5714,"distance":8795,"speed":5543,"elev_gain":83},{"id":79895757,"name":"Pleasant Hill night jog","workout_type":0,"trainer":0,"start_date_local":"2013-09-03T13:51:14-07:00","moving_time":3450,"elapsed_time":3453,"distance":11310,"speed":11801,"elev_gain":261},{"id":81342383,"name":"Wasatch Front 100 (Full)","workout_type":1,"trainer":0,"start_date_local":"2013-09-05T22:00:00-07:00","moving_time":73418,"elapsed_time":75885,"distance":161229,"speed":7905,"elev_gain":7513}]},"moving_time":82580,"elapsed_time":85052,"distance":181334,"speed":7905,"elev_gain":7857},{"interval":"2013y37w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y38w","entry":{"activities":[{"id":83383914,"name":"Pleasant Hill power-hike with weight vest","workout_type":0,"trainer":0,"start_date_local":"2013-09-18T11:58:48-07:00","moving_time":6664,"elapsed_time":6668,"distance":11475,"speed":6199,"elev_gain":215}]},"moving_time":6664,"elapsed_time":6668,"distance":11475,"speed":6199,"elev_gain":215}]
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>demo</title>
<link rel="stylesheet" href="http://necolas.github.io/normalize.css/2.1.3/normalize.css">
<link rel="stylesheet" href="log7.css">
</head>
<body>
<div id="strava-header"></div>
<div id="g-header-overlay"></div>
<div id="g-container">
<!-- <img src="http://dgalywyr863hv.cloudfront.net/pictures/athletes/203495/82115/2/large.jpg" class="g-mug">
<h1 class="g-hed">Billy Robins's Training Log</h1>
<h5 class="g-subHed">San Francisco, CA</h5> -->
<div id="g-volume">
</div>
<div id="g-header">
<ul class="g-days cf">
<li class="g-day g-day-intro" id="row-summary">September</li>
<li class="g-day g-day-0">Mon.</li>
<li class="g-day g-day-1">Tue.</li>
<li class="g-day g-day-2">Wed.</li>
<li class="g-day g-day-3">Thu.</li>
<li class="g-day g-day-4">Fri.</li>
<li class="g-day g-day-5">Sat.</li>
<li class="g-day g-day-6">Sun.</li>
</ul>
<ul class="g-viewToggles cf g-viewToggles-main">
<li class="g-viewToggle" style="padding-right:5px;">Show:&nbsp;
<select onchange="gfx.handleTypeChange();" id="typeToggle">
<option value="distance">Distance</option>
<option value="time">Time</option>
<option value="elev_gain">Elevation Gain</option>
</select>
</li>
<!-- <li class="g-viewToggle selected" id="toggle-distance"><a onclick="gfx.update('distance'); return false;">Distance</a></li>
<li class="g-viewToggle" id="toggle-time" ><a onclick="return false;">Time</a></li>
<li class="g-viewToggle" id="toggle-elevation"><a onclick="gfx.update('elev_gain'); return false;">Elevation</a></li> -->
</ul>
<dl class="g-run-key">
<dt>Run Types</dt>
<dd class="g-run-type-run"><span class="g-chip"></span>Run</dd>
<dd class="g-run-type-workout"><span class="g-chip"></span>Workout</dd>
<dd class="g-run-type-long"><span class="g-chip"></span>Long Run</dd>
<dd class="g-run-type-race"><span class="g-chip"></span>Race</dd>
</dl>
</div>
<section id="g-log">
<div id="g-rows"></div>
</section>
<nav id="g-barNav">
<!-- <ul id="g-timeNav" class="cf">
<li><a href="#">List</a></li>
<li class="selected"><a href="#">Weekly</a></li>
<li><a href="#">Compare</a></li>
</ul>
-->
<div id="g-barNav-chart">
<ul class="g-date-nav cf">
<li class="g-cal-prev"><a href="#prev"><</a></li>
<li class="g-cal-head">September 2013</li>
<li class="g-cal-next"><a href="#next">></a></li>
</ul>
<table class="cf g-cal">
<tr>
<td class="g-last-month">26</td>
<td class="g-last-month">27</td>
<td class="g-last-month">28</td>
<td class="g-last-month">29</td>
<td class="g-last-month">30</td>
<td class="g-last-month">31</td>
<td>&nbsp;1</td>
</tr>
<tr>
<td>&nbsp;2</td>
<td>&nbsp;3</td>
<td>&nbsp;4</td>
<td>&nbsp;5</td>
<td>&nbsp;6</td>
<td>&nbsp;7</td>
<td>&nbsp;8</td>
</tr>
<tr>
<td>&nbsp;9</td>
<td>10</td>
<td>11</td>
<td>12</td>
<td>13</td>
<td>14</td>
<td>15</td>
</tr>
<tr>
<td>16</td>
<td>17</td>
<td>18</td>
<td>19</td>
<td>20</td>
<td>21</td>
<td>22</td>
</tr>
<tr class="g-current-row">
<td>23</td>
<td>24</td>
<td class="g-cal-day-today">25</td>
<td>26</td>
<td>27</td>
<td>28</td>
<td>29</td>
</tr>
<tr>
<td>30</td>
<td class="g-last-month">&nbsp;1</td>
<td class="g-last-month">&nbsp;2</td>
<td class="g-last-month">&nbsp;3</td>
<td class="g-last-month">&nbsp;4</td>
<td class="g-last-month">&nbsp;5</td>
<td class="g-last-month">&nbsp;6</td>
</tr>
</table>
<!-- <ul class="g-viewToggles cf">
<li class="g-toggle-header g-viewToggle">Show:</li>
<li class="g-viewToggle selected" id="toggle-distance"><a onclick="gfx.update('distance'); return false;">Distance</a></li>
<li class="g-viewToggle" id="toggle-time" ><a onclick="gfx.update('time'); return false;">Time</a></li>
<li class="g-viewToggle" id="toggle-elevation"><a onclick="gfx.update('elev_gain'); return false;">Elevation</a></li>
</ul> -->
</div>
</div>
</div>
<div id="g-footer-overlay"></div>
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="moment.min.js"></script>
<script src="tooltip.js"></script>
<script src="fixie.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="log7.js"></script>
</body>
</html>
/*body{
backgro
}*/
.cf:before,
.cf:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.cf:after {
clear: both;
}
/**
* For IE 6/7 only
* Include this rule to trigger hasLayout and contain floats.
*/
.cf {
*zoom: 1;
}
#g-container{
width:870px;
margin: 25px auto;
height: 100%;
padding-top:0px;
position:relative;
}
#g-log{
width:650px;
position: relative;
padding-top:27px;
}
#g-sidebar{
width:250px;
position:absolute;
left: 585px;
top:0;
bottom:0;
display:none;
background:#f7f7f7;
}
/* start top */
#g-header{
margin: 0;
padding: 0;
z-index:1000;
background:#fff;
position:absolute;
left:0;
top:57px;
width:665px;
}
#g-header svg{
}
.ink-is-fixed #g-header{
box-shadow: 0 0 12px -5px rgba(0,0,0,.55);
}
/*.ink-is-fixed #g-header:after{
content: '';
height: 3px;
position: absolute;
left: 0;
right: 0;
bottom: -3px;
-webkit-mask-box-image: -webkit-linear-gradient(left,transparent 0%,rgba(0,0,0,1) 50%,transparent 100%);
background-color: transparent;
background-image: -webkit-linear-gradient(top,rgba(0,0,0, .3),transparent);
background-image: -moz-linear-gradient(top,rgba(0,0,0, .3),transparent);
background-image: -ms-linear-gradient(top,rgba(0,0,0, .3),transparent);
background-image: -o-linear-gradient(top,rgba(0,0,0, .3),transparent);
background-image: linear-gradient(top,rgba(0,0,0, .2),transparent);
z-index: 1001;
}
*/
.g-mug{
float: left;
display: inline;
margin: 0 12px 0 100px;
width: 50px;
height: 50px;
background: #ddd;
position: relative;
}
.g-hed{
font-size: 14px;
font-weight: bold;
line-height: 1.5;
font-family:sans-serif;
color: #333;
padding: 0;
margin: 0;
}
.g-subHed{
font-size: 12px;
font-weight: normal;
line-height: 1.5;
font-family:sans-serif;
color: #666;
margin: 0;
padding: 0;
}
#g-barNav{
width: 201px;
position: relative;
overflow: hidden;
float: left;
position: absolute;
left: 685px;
top: 57px;
padding:0;
z-index:100;
}
.g-viewToggles{
list-style-type: none;
margin: 0;
padding: 0;
text-align: center;
background:#f7f7f7;
}
/*.g-viewToggles a#{
width:71px;
padding:5px;
background: url(images/);
}*/
#toggle-distance {
/*background:url(../images/ruler.png) no-repeat 0 6px;
padding: 3px 0 3px 27px;*/
/*border-radius:2px 0 0 2px;*/
border-right:1px solid #aaa;
}
#toggle-distance a{
padding-left:0;
margin-left:0;
}
#toggle-time {
/* background:url(../images/time.png) no-repeat 1px 3px;
padding: 3px 0 3px 19px;
*/
border-right:1px solid #aaa;
}
#toggle-time a{
margin-left:0;
}
#toggle-elevation{
/* background:url(../images/elevation.png) no-repeat 0 4px;
padding: 3px 0 3px 22px;
*/
}
.g-viewToggle{
margin: 0 0px 0 0;
float: left;
font-size: 11px;
list-style-type: none;
/*
text-transform:uppercase;
background:#ccc;
text-align:center;*/
/*box-shadow: 1px 1px 0 #aaa, 2px 2px 0 #aaa, 3px 3px 0 #aaa;*/
/*box-shadow: 1px 1px 0 #aaa, 2px 2px 0 #ccc, 2px 2px 0 #aaa;
text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.3);
color:#fff;
cursor: pointer;
transition: box-shadow .3s;*/
}
.g-viewToggle a{
color:#007fb6;
font-size:12px;
padding: 7px;
cursor: pointer;
margin-left:5px;
}
.g-toggle-header{
float: none;
display:block;
clear:both;
padding:0 12px 0 0;
text-align:left;
font-size:12px;
margin-bottom:2px;
}
.g-viewToggle a:hover{
color:#333;
text-shadow: none;
}
.g-scaleBy-distance #toggle-distance a,
.g-scaleBy-time #toggle-time a,
.g-scaleBy-elev_gain #toggle-elevation a{
color:#000;
font-weight:bold;
}
.g-days{
list-style-type:none;
margin: 0;
padding: 0;
border:1px solid #ddd;
/*border-right:1px solid #ddd;
border-bottom:1px solid #ddd;*/
}
.g-day{
list-style-type:none;
font-size: 12px;
color:#333;
margin: 0;
padding: 8px 0 6px;
float: left;
text-align:center;
width: 66px;
/*text-transform:uppercase;*/
font-weight: bold;
position:relative;
}
.g-day:after{
content: '';
position: absolute;
right:0;
top:4px;
bottom:4px;
width:1px;
background:#eee;
}
.g-day:last-child:after{
background:#fff;
}
.g-day-intro{
width: 121px;
text-align:center;
color: #fff;
}
/*.g-day-intro:after{
width:0;
}
.g-day-intro:before{
width:154px;
left:-1px;
top:-1px;
box-shadow:inset;
height:28px;
box-shadow: inset 0 0 0 1px rgb(252,76,2);
content: '';
position:absolute;
}*/
/* end top */
/* charts */
.weekBar{
fill: rgb(190,223,231);
shape-rendering:crispEdges;
transition: fill .1s;
cursor:pointer;
}
.weekBar:hover,.weekBar-selected{
fill: rgb(92, 181, 202)
}
#g-rows{
width: 650px;
}
.g-row{
height:100px;
background:#ddd;
margin-bottom:15px;
}
.divider{
stroke: #ccc;
stroke-dasharray: 1,1;
shape-rendering: crispEdges;
}
.run{
transition-property: fill-opacity, fill;
transition-duration: 1s, 1s;
stroke: none;
fill-opacity:.7;
fill: #a5d4e1;
}
.run-depth-0{
fill:#f1f1f1;
stroke-width: 1px;
stroke-opacity: .35;
transition: stroke-width .4s;
fill-opacity: .15;
stroke-dasharray: 1,2;
stroke: #aaa;
}
circle.active{
stroke-width: 2.5px;
stroke: #95d4e1;
fill-opacity:1;
}
/*.active circle.run-depth-0{
stroke-width:4.5px;
stroke;
}*/
text.time,
text.distance,
text.sum{
transition: opacity .7s;
font-size: 13px;
font-family:sans-serif;
fill:#666;
pointer-events: none;
}
.ink-tooltip{
max-width: 200px;
background: rgba(255,255,255,.95);
/*box-shadow: 0px 0px 3px rgba(0,0,0,.1);*/
text-align: center;
padding: 10px;
z-index: 100000;
font-size: 12px;
position:absolute;
color:#333;
pointer-events:none;
border:1px solid #ddd;
transition: width .3s;
/*border-bottom-color:#efefef;
border-right-color:#efefef;*/
}
.ink-tooltip:after{
pointer-events:none;
content: '';
width: 0;
height: 0;
display:inline-block;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid rgba(0,0,0,.8);
margin:100px 0 0;
z-index:10000;
position:absolute;
left:45%;
bottom:-10px;
}
.ink-tooltip:before{
pointer-events:none;
content: '';
width: 0;
height: 0;
display:inline-block;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #fff;
margin:100px 0 0;
z-index:10001;
position:absolute;
left:45%;
bottom:-10px;
}
.ink-tooltip .block{
font-size:14px;
font-weight:bold;
padding-bottom:5px;
text-overflow: ellipsis;
/*width:180px;*/
}
.ink-tooltip .pace{
font-size:12px;
font-weight:normal;
padding-bottom:0;
}
circle.active{
stroke-width: 2.5px;
stroke: #75d4e1;
fill-opacity:1;
}
text.time,
text.distance,
text.sum,
text.rest{
transition: font-size .3s;
font-size: 12px;
font-family:sans-serif;
fill:#333;
fill-opacity:.9;
}
text.activeText{
transition: font-size .3s;
font-size:15px !important;
}
text.rest{
font-size:10px;
fill-opacity:.3;
fill:#999;
cursor:default;
/*text-transform: uppercase;*/
}
text.rest:hover{
fill-opacity:1;
}
.weekTotal{
font-size:18px;
font-weight:bold;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
}
.divider{
stroke: #ccc;
stroke-dasharray: 1,1;
shape-rendering: crispEdges;
}
.text-bg{
fill:#fff;
point-events: none;
}
.text-bg-hidden{
display:none;
}
.dateRange{
font-size:10px;
fill:#999;
text-transform:uppercase;
}
/* .g-scaleBy-elev_gain circle{
fill: #aaa;
}*/
#g-barNav-chart{
background: #f7f7f7;
width: 176px;
padding: 12px;
box-shadow: inset 0 0 2px rgba(0,0,0,.1), 1px 1px 3px rgba(0,0,0,.15);
border-radius: 0 0 4px 4px;
min-height:318px;
}
.domain{
stroke-width: 1px;
fill: #999;
display:none;
}
#g-barNav svg{
/*border-bottom:1px solid #ddd;*/
}
.g-bigBarLabel{
font-size:12px;
fill:#555;
font-weight: bold;
pointer-events: none
}
.g-barLabel{
font-size:11px;
fill:#555;
pointer-events: none;
}
.g-line{
stroke-width:1px;
stroke:#e1e1e1;
shape-rendering:crispEdges;
}
.run-depth-0.run-children-1{
display: none;
}
.run-type-1{
fill:rgb(255, 184, 212);
}
.run-type-2{
fill:rgb(138, 185, 142);
}
.run-type-3{
fill: rgb(250, 198, 87);
}
#g-timeNav{
list-style-type: none;
margin: 0;
padding:0;
}
#g-timeNav li{
list-style-type: none;
margin: 0;
padding:0;
float:left;
}
#g-timeNav li a{
display:block;
background:#fc4c02;
color:#ffded2;
text-align:center;
width:67px;
padding:9px 0;
font-size:12px;
text-decoration: none;
text-shadow: 1px 1px 3px rgba(0,0,0,.3);
position:relative;
transition:background .4s;
}
#g-timeNav li.selected a,
#g-timeNav li a:hover{
box-shadow:inset 0 0 12px rgba(0,0,0,.15);
text-shadow: 1px 1px 3px rgba(0,0,0,.9);
color:rgba(255,255,255,1);
background:#e23c03;
}
#g-timeNav li.selected a:before,
#g-timeNav li a:before:hover{
content: "";
position:absolute;
left:0;
top:0;
bottom:0;
width:1px;
background:rgba(0,0,0,.1);
pointer-events: none;
z-index:100;
}
#g-timeNav li.selected a:after,
#g-timeNav li a:after:hover{
content: "";
position:absolute;
right:0;
top:0;
bottom:0;
width:1px;
background:rgba(0,0,0,.1);
pointer-events: none;
z-index:100;
}
#row-prev,
#row-next{
width:30px;
text-indent:-1000em;
outline:none;
margin: 1px 0 0 1px;
visibility:hidden;
}
#row-prev:hover,
#row-next:hover{
background-color:#f7f7f7;
cursor:pointer;
}
#row-prev{
background: url(up1.png) no-repeat center center;
}
#row-next{
background: url(down1.png) no-repeat center center;
}
#row-next:after{
display:none;
}
#row-summary{
font-size: 15px;
color: #000;
padding-right: 31px;
text-align: right;
width:88px;
padding-top:6px;
}
#g-header-overlay{
position:fixed;
top:0;
left:0;
right:0;
height:30px;
background:#fff;
background: linear-gradient(to top, rgba(255,255,255,0) 0%,rgba(255,255,255,.9) 100%);
pointer-events:none;
z-index:100;
}
#g-footer-overlay{
position:fixed;
bottom:0;
left:0;
right:0;
height:30px;
background:#fff;
background: linear-gradient(to bottom, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%);
pointer-events:none;
}
.g-run-key{
margin:12px 0 0 12px;
padding:0;
font-size:12px;
}
.g-run-key dt{
font-weight:bold;
margin: 0 0 5px;
padding:0;
}
.g-run-key dd{
font-weight:normal;
margin: 0 0 2px;
padding:0;
}
.g-run-key .g-chip{
float:left;
margin:2px 10px 0 0;
width:9px;
height:9px;
background:#ddd;
}
.g-run-type-workout .g-chip{
background:orange;
}
.g-run-type-race .g-chip{
background:rgb(255, 184, 212);
}
.g-run-type-long .g-chip{
background: rgb(138, 185, 142);
}
// ugly get date class hacking
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
}
var gfx = function(){
return{
chartStyles: {
barChart: {
width: 115,
height: 250,
margin: { left: 0, top: 0, bottom: 0, right: 40 }
},
bubbleChart: {
width: 650,
height: 10,
margin: { left: 40, top: 0, bottom: 0, right: 0 }
}
},
shortMonths: [
'Jan.',
'Feb.',
'Mar.',
'Apr.',
'May',
'June',
'July',
'Aug.',
'Sept.',
'Oct.',
'Nov.',
'Dec.'
],
fullMonths: [
'January',
'Febuary',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
],
startWeek: null,
endWeek: null,
hackIntervalIn: true,
minRadius: 1,
maxRadius: 26.2,
rowHeight: 75,
rowsToStart: 10,
dateCounter: 0,
scaleBy: 'distance',
startDate: new Date(2013,08,02),
endDate: new Date(2013,08,08),
init: function(user){
this.setup();
this.getData(user)
this.tooltip = new Ink.Tooltip({ align: 'aboveCenter'});
},
bindEvents: function(){
var months = $('.g-month-title');
this.offsets = [];
var me = this;
months.each(function(d,i){
me.offsets.push({ y: $(this).offset().top -20, title: $(this).text(), interval: $(this).data('interval') })
})
var hs = _.debounce($.proxy(this.handleScroll, this), 0)
$(window).scroll(hs)
},
handleScroll: function(){
var y = $(window).scrollTop()
this.offsets.forEach(function(o,i){
if(y >= o.y && i != gfx.offsets.length - 1){
if(y < gfx.offsets[i+1].y){
$('#row-summary').text(o.title)
return;
}
}
})
},
setup: function(){
this.barChart = d3.select("#g-barNav-chart").append("svg")
.attr("width", this.chartStyles.barChart.width + this.chartStyles.barChart.margin.left + this.chartStyles.barChart.margin.right)
.attr("height", this.chartStyles.barChart.height + this.chartStyles.barChart.margin.top + this.chartStyles.barChart.margin.bottom)
.append("g")
.attr("transform", "translate(" + this.chartStyles.barChart.margin.left + "," + this.chartStyles.barChart.margin.top + ")");
},
getData: function(user){
var me = this;
d3.json(user+'.json',function(data){
me.handleData(data)
});
},
getDatesFromInterval: function(interval){
},
handleData: function(data){
var me = this;
this.formatDate = d3.time.format("%Y-%m-%dT%H:%M:%S-%H:%M");
this.formatDate2 = d3.time.format("%Y-%m-%dT%H:%M:%SZ");
this.intervalDate = d3.time.format("%Y\y%W\w");
data.forEach(function(d){
d.entry.structured_activities = [
[],
[],
[],
[],
[],
[],
[]
];
if(d.entry.activities.length > 0){
d.entry.activities.forEach(function(activity,n){
activity.formattedDate = gfx.formatDate.parse(activity.start_date_local);
activity.dayOfWeek = activity.formattedDate.getDay()
activity.week = activity.formattedDate.getWeek()
d.week = activity.week;
activity.month_year = activity.formattedDate.getMonth()+'_'+activity.formattedDate.getFullYear()
d.entry.structured_activities[activity.dayOfWeek].push(activity);
})
}
});
// //if(this.hackIntervalIn === true){
// c = this.startWeek;
// data.forEach(function(d, i){
// data[i].week = c;
// data[i].distance = 0
// data[i].moving_time = 0
// data[i].elev_gain = 0
// data[i].activities = [
// [], //0
// [], //1
// [], //2
// [], //3
// [], //4
// [], //5
// [] //6
// ]
// c++;
// if(d.length > 0){
// d.forEach(function(_d){
// _d.formattedDate = gfx.formatDate2.parse(_d.start_date_local);
// _d.dayOfWeek = _d.formattedDate.getDay();
// _d.week = _d.formattedDate.getWeek();
// data[i].formattedDate = _d.formattedDate.getMonth()
// data[i].activities[_d.dayOfWeek].push(_d);
// // add it all up
// data[i].distance += _d.distance;
// data[i].moving_time += _d.moving_time;
// data[i].elev_gain += _d.elev_gain;
// });
// }
// });
// }
// console.log(_.pluck(data, 'week'))
this.data = data.reverse();
var activities = _.map(this.data, function(d){ return d.entry.activities; });
this.activities = _.flatten(activities);
this.activities = _.reject(this.activities, function(activity){ return activity.formattedDate.getFullYear() === 2012 })
this.months = _.toArray(d3.nest()
.key(function(d){ return d.month_year })
.map(this.activities))
this.setScales();
this.render();
},
setScales: function(){
var me = this;
var intervals = _.pluck(this.data, 'interval')
$('#g-container').attr('class','g-scaleBy-'+gfx.scaleBy);
this.barYScale = d3.scale.ordinal()
.rangeBands([30, this.chartStyles.barChart.height])
.domain(intervals)
this.barXScale = d3.scale.linear()
.range([0, this.chartStyles.barChart.width-this.chartStyles.barChart.margin.left])
.domain(d3.extent(this.data, function(d){ return d[gfx.scaleBy] }));
this.bubbleXScale = d3.scale.ordinal()
.rangeBands([me.chartStyles.bubbleChart.margin.left, me.chartStyles.bubbleChart.width])
.domain([8,1,2,3,4,5,6,0])
ext = d3.extent(this.activities, function(d){ return d[gfx.scaleBy] })
if(this.scaleBy === 'distance'){
this.runScale = d3.scale.sqrt()
.range([this.minRadius, 26])
.domain([5, d3.max(this.activities, function(d){ return d[gfx.scaleBy] })])
}else{
this.runScale = d3.scale.sqrt()
.range([this.minRadius, 26.2])
.domain([1, d3.max(this.activities, function(d){ return d[gfx.scaleBy] })]);
}
},
format_distance_value: function(val){
return this.getMile(val).toFixed(1)
},
format_time_value: function(val){
// var totalSec = new Date().getTime() / 1000;
var totalSec = val
var hours = parseInt( totalSec / 3600 ) % 24;
var minutes = parseInt( totalSec / 60 ) % 60;
var seconds = totalSec % 60;
var result = (hours < 10 ? hours+'hr' : hours+'hr') + " " + (minutes < 10 ? "0" + minutes+'min' : minutes+'min');
return result
},
format_elev_gain_value: function(val){
return val.toString().replace('.0','')
},
elev_gain_suffix: function(){ return 'ft' },
distance_suffix: function(){ return 'mi' },
time_suffix: function(){ return '' },
getMile: function(distance){
return distance * 0.000621371
},
getMeter: function(){
},
updateScales: function(){
this.setScales();
},
update: function(scaleBy){
var me = this;
this.scaleBy = scaleBy;
this.setScales()
this.barChart.selectAll('.weekBar')
.transition()
.duration(700)
.attr('width', function(d){ return me.barXScale(d[gfx.scaleBy]) })
var days = d3.selectAll('.dayWrap')
d3.selectAll('.weekTotal').text(function(d){ if(d[gfx.scaleBy]) { return me['format_'+gfx.scaleBy+'_value'](d[gfx.scaleBy])+gfx[gfx.scaleBy+'_suffix']() }})
days.each(function(d,n){
if(d.length > 0){
var total = _(d).pluck(gfx.scaleBy).reduce(function(d1,d2){ return d1 + d2})
}else{
var total = 0;
}
var packSize = [me.runScale(total), me.runScale(total)];
// d3.select(this)
// .attr('transform',function(__d){ return 'translate('+(me.bubbleXScale(n)-(packSize[0]/2))+','+(me.rowHeight - packSize[0] / 2) +')' })
if(total > 0){
pack = d3.layout.pack()
.sort(d3.descending)
.size(packSize)
.value(function(__d){ if(gfx.scaleBy in __d){ return __d[gfx.scaleBy];} else{ return 0 } })
.children(
function(__d,i){
return __d;
}
)
.radius(function(__d){
return me.runScale(__d)
})
var runs = d3.select(this).selectAll('.run')
.data(pack.nodes)
d3.select(this).select('.sum.no-rest')
.transition()
.attr('transform', function(d){ return 'translate('+packSize[0]/2+','+(packSize[0] / 2) +')' })
.text(function(__d){
if(gfx.scaleBy === 'distance'){
var t = me.getMile(total).toFixed(1).toString()
t = (t.indexOf('.0') > 0) ? t.replace('.0','') : t;
return t
}else{
return me['format_'+gfx.scaleBy+'_value'](__d.value)+gfx[gfx.scaleBy+'_suffix']()
}
})
runs.transition()
.attr("transform", function(__d) { return "translate(" + __d.x + "," + (__d.y)+ ")"; })
.attr("r", function(__d){
return __d.r
})
}else{
}
});
// if(d.length > 0){
// var total = _(d).pluck(gfx.scaleBy).reduce(function(d1,d2){ return d1 + d2})
// }else{
// var total = 0;
// }
// var packSize = [me.runScale(total), me.runScale(total)];
// // d3.select(this)
// // .attr('transform',function(__d){ return 'translate('+(me.bubbleXScale(n)-(packSize[0]/2))+','+(me.rowHeight - packSize[0] / 2) +')' })
// // d3.select(this)
// // .append('rect')
// // .attr('class',function(d){ return (total === 0) ? 'text-bg' : 'text-bg-hidden' })
// // .attr('width',40)
// // .attr('height', 30)
// // .attr('transform', function(d){ return 'translate(-18,-10)' })
// // .style('opacity',0)
// if(total > 0){
// pack = d3.layout.pack()
// .sort(d3.ascending)
// .size(packSize)
// .value(function(__d){ if(gfx.scaleBy in __d){ return __d[gfx.scaleBy];} else{ return 0 } })
// .children(
// function(__d,i){
// return __d;
// }
// )
// .radius(function(__d){
// return me.runScale(__d)
// })
// d3.selectAll('.sum')
// .text(function(){
// if (total > 0){
// if(scaleBy === 'elev_gain'){
// return total+'ft.'
// }else{
// var t = me.getMile(total).toFixed(1).toString()
// t = (t.indexOf('.0') > 0) ? t.replace('.0','') : t;
// return t
// }
// }else{
// return 'Rest'
// }
// })
// .attr('text-anchor', 'middle')
// .attr('dy','4px')
// .attr('transform', function(d){ return 'translate('+packSize[0]/2+','+(packSize[0] / 2) +')' })
// // .style('font-size',0)
// // .style('opacity',0)
// // text
// d3.select(this).selectAll('.run')
// .data(pack.nodes)
// .enter()
// .append('circle')
// .attr('class', function(d){ return 'run run-depth-'+d.depth+' run-type-'+d.workout_type })
// .attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
// .attr("r", 0)
// transition = me.bubbleChart.transition().duration(700).delay(0)
// transition.selectAll('.run')
// .transition()
// .attr("r", function(d,i){
// return d.r;
// })
// .attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
// }
// })
//
//
// d3.select(this).selectAll('.run')
// .data(pack.nodes)
// .enter()
// .append('circle')
// .attr('class', function(d){ return 'run run-depth-'+d.depth })
// .attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
// .attr("r", 0)
// });
// transition = this.bubbleChart.transition().duration(1000).delay(0)
// transition.selectAll('.run')
// .update()
// .transition()
// .attr("r", function(d,i){
// return d.r;
// })
},
render: function(){
this.renderBarChart();
// rows = $('#g-rows');
var bubble = this.chartStyles.bubbleChart;
// this.bubbleChart = d3.select('#g-rows').append('svg')
// .attr("width", bubble.width + bubble.margin.left + bubble.margin.right)
// .attr("height", (this.rowHeight * this.data.length) + bubble.margin.top + bubble.margin.bottom)
// .append("g")
// .attr("transform", "translate(" + bubble.margin.left + "," + bubble.margin.top + ")");
// this.renderRows();
this.renderMonthRows();
this.bindEvents();
this.fixie = new Ink.Fixie('#g-header', {offsetY: 5})
this.navFixie = new Ink.Fixie('#g-barNav', {offsetY: 5})
},
renderMonthRows: function(){
var bubble = this.chartStyles.bubbleChart;
var me = this;
var rows = d3.select('#g-rows').selectAll('.g-row')
.data(this.months)
.enter()
.append('div')
.attr('class','g-row')
rows.append('h3')
.attr('class','g-month-title')
.html(function(d,i){
return gfx.fullMonths[d[i].formattedDate.getMonth()]
})
.attr('data-interval',function(d){ return d[0].formattedDate.getMonth() })
var bubbleCharts = rows.append('svg')
.attr('class','g-bubble-chart')
.attr('width', bubble.width + bubble.margin.left + bubble.margin.right)
.attr("height", gfx.rowHeight*5.5)
.append('g')
.attr('transform',"translate(" + bubble.margin.left + "," + bubble.margin.top + ")");
var groups = bubbleCharts.selectAll('.week')
.data(function(d){
// // _.select(gfx.data, )
var weeks = _.pluck(d, 'week')
return _.filter(gfx.data, function(_d){ return _.contains(weeks,_d.week) })
// return _.toArray(d3.nest().key(function(_d){ return _d.week }).map(d))
})
.enter()
.append('g')
.attr('class', 'week')
.attr('transform',function(d,i){
return 'translate(0,'+(i*gfx.rowHeight)+')';
});
var dividers = groups.selectAll('.divider')
.data(function(d){ return [ { distance: d[gfx.scaleBy] }] })
.enter()
.append('line')
.attr('class', 'divider')
.attr('x1', this.chartStyles.bubbleChart.margin.left +10)
.attr('y1', me.rowHeight - 1)
.attr('x2', 0)
.attr('y2', me.rowHeight - 1)
// .style('opacity', 0)
.transition()
.duration(1000)
.delay(function(d, i){ return i / me.data.length * 1000 })
.attr('x2',this.bubbleXScale(0))
var totals = groups.selectAll('.weekTotals')
.data(function(d){ return [ { interval: d['interval'], distance: d['distance'], time: d['moving_time'], elev_gain: d['elev_gain'] }]})
.enter()
.append('g')
.attr('class','weekTotals')
.attr('transform',function(d,i){
return 'translate(-20,'+(i*me.rowHeight+(me.rowHeight + 5))+')';
})
totals.append('text')
.attr('class', 'weekTotal')
.text(function(d){ if(d[gfx.scaleBy]) { return me['format_'+gfx.scaleBy+'_value'](d[gfx.scaleBy])+gfx[gfx.scaleBy+'_suffix']() }})
var dformat1 = d3.time.format("%b. %e")
var dformat2 = d3.time.format("%-e")
var months = [
'Jan.',
'Feb.',
'Mar.',
'Apr.',
'May',
'June',
'July',
'Aug.',
'Sept.',
'Oct.',
'Nov.',
'Dec.'
]
var dateRanges = totals.append('text')
.attr('class','dateRange')
.attr('transform',function(d,i){
if(d[gfx.scaleBy] > 0){
return 'translate(0,-22)';
}else{
return 'translate(0,-2)';
}
})
.text(function(d){
_start = new Date(),
start = new Date(),
_end = new Date(),
end = new Date();
year = parseInt(d.interval.substr(0,4),10)
week = parseInt(d.interval.substr(5,2),10)
_start.setFullYear(year)
_start.setMonth(0)
_start.setDate(1)
_end.setFullYear(year)
_end.setMonth(0)
_end.setDate((week * 7))
moment_start = moment(_start).add('days',(week*7))
moment_end = moment(_end).add('days',7)
if(moment_start.month() === moment_end.month()){
return moment_start.format('MMM. D')+'-'+moment_end.format('D')
}else{
return moment_start.format('MMM. D')+'-'+moment_end.format('MMM. D')
}
})
// .attr('text-anchor','end')
var days = groups.selectAll('.dayWrap')
.data(function(d){ return d.entry.structured_activities })
.enter()
.append('g')
.attr('class', 'dayWrap')
days.each(function(d,n){
if(d.length > 0){
var total = _(d).pluck(gfx.scaleBy).reduce(function(d1,d2){ return d1 + d2})
}else{
var total = 0;
}
var packSize = [me.runScale(total), me.runScale(total)];
d3.select(this)
.attr('transform',function(__d){ return 'translate('+(me.bubbleXScale(n)-(packSize[0]/2))+','+(me.rowHeight - packSize[0] / 2) +')' })
if(total > 0){
pack = d3.layout.pack()
.sort(d3.descending)
.size(packSize)
.value(function(__d){ if(gfx.scaleBy in __d){ return __d[gfx.scaleBy];} else{ return 0 } })
.children(
function(__d,i){
return __d;
}
)
.radius(function(__d){
return me.runScale(__d)
})
d3.select(this).selectAll('.run')
.data(pack.nodes)
.enter()
.append('circle')
.attr('class', function(d){
var childLength = ('children' in d) ? d.children.length : 0;
return 'run run-depth-'+d.depth+' run-children-'+childLength+' run-type-'+d.workout_type
})
.attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
.attr("r", 0)
// .style('opacity', 0)
.on('mouseover', function(d,i){
// if (true) {};
if(d.depth === 0){
var parent = this.parentNode;
d3.select(parent).classed('active', true)
return
}
var parent = this.parentNode;
d3.select(parent).classed('active', true)
d3.select(this).classed('active', true)
m = d3.mouse(this)
// p = d.avg_pace.split(':')[0]+':'+d.avg_pace.split(':')[1]
me.tooltip.content('<div class="block block-title">'+d.name+'</div><div class="block pace"><b>Distance:</b> '+gfx.getMile(d.distance).toFixed(1)+'mi.</div><div class="block pace"><b>Moving Time:</b> '+gfx.format_time_value(d.moving_time)+'</div><div class="block pace"><b>Avg Pace:</b> '+d.speed+'/mi</div>')
x = event.pageX - m[0] - (me.tooltip.$el.width() / 2) - 10
y = event.pageY - m[1] - gfx.tooltip.$el.height() - 50
gfx.tooltip.position({ left: x, top: y }).show()
d3.select(this).classed('active', true)
// console.log('day: ', d.dayOfWeek)
})
.on('mouseout', function(){
me.tooltip.hide();
var parent = this.parentNode;
d3.select(this).classed('active', false)
d3.select(parent).classed('active', false)
d3.select(parent).select('.sum').classed('activeText',false)
})
}
// .padding(-2)
// blocks
d3.select(this)
.append('rect')
.attr('class',function(d){ return (total === 0) ? 'text-bg' : 'text-bg-hidden' })
.attr('width',40)
.attr('height', 30)
.attr('transform', function(d){ return 'translate(-18,-10)' })
.style('opacity',0)
d3.select(this)
.append('text')
.attr('class', function(d){
if(total === 0){
return 'sum rest'
}else{
return 'sum no-rest'
}
})
.text(function(){
if (total > 0){
var t = me.getMile(total).toFixed(1).toString()
t = (t.indexOf('.0') > 0) ? t.replace('.0','') : t;
return t
}else{
return 'rest'
}
})
.attr('text-anchor', 'middle')
.attr('dy','4px')
.attr('transform', function(d){ return 'translate('+packSize[0]/2+','+(packSize[0] / 2) +')' })
.style('font-size',0)
.style('opacity',0)
// text
});
revealTransition = d3.transition().duration(1000)
.delay(function(d, i) { return i / 11 * 1000; })
revealTransition.selectAll('.run')
.attr("r", function(d,i){
return d.r;
})
.style("opacity", 1)
revealTransition.selectAll('.text-bg').style('opacity',1)
revealTransition.selectAll('.sum').style('font-size','13px').style('opacity',1)
revealTransition.transition()
},
renderRows: function(){
var me = this
var groups = this.bubbleChart.selectAll('.week')
.data(this.data)
.enter()
.append('g')
.attr('class', 'week')
.attr('transform',function(d,i){
return 'translate(0,'+(i*me.rowHeight)+')';
});
var dividers = groups.selectAll('.divider')
.data(function(d){ return [ { distance: d[gfx.scaleBy] }] })
.enter()
.append('line')
.attr('class', 'divider')
.attr('x1', this.chartStyles.bubbleChart.margin.left +10)
.attr('y1', me.rowHeight - 1)
.attr('x2', 0)
.attr('y2', me.rowHeight - 1)
// .style('opacity', 0)
.transition()
.duration(1000)
.delay(function(d, i){ return i / me.data.length * 1000 })
.attr('x2',this.bubbleXScale(0))
var totals = groups.selectAll('.weekTotals')
.data(function(d){ return [ { interval: d['interval'], distance: d['distance'], time: d['moving_time'], elev_gain: d['elev_gain'] }]})
.enter()
.append('g')
.attr('class','weekTotals')
.attr('transform',function(d,i){
return 'translate(-20,'+(i*me.rowHeight+(me.rowHeight + 5))+')';
})
totals.append('text')
.attr('class', 'weekTotal')
.text(function(d){ if(d[gfx.scaleBy]) { return me['format_'+gfx.scaleBy+'_value'](d[gfx.scaleBy])+gfx[gfx.scaleBy+'_suffix']() }})
// .attr('text-anchor','end')
var dformat1 = d3.time.format("%b. %e")
var dformat2 = d3.time.format("%-e")
var months = [
'Jan.',
'Feb.',
'Mar.',
'Apr.',
'May',
'June',
'July',
'Aug.',
'Sept.',
'Oct.',
'Nov.',
'Dec.'
]
var dateRanges = totals.append('text')
.attr('class','dateRange')
.attr('transform',function(d,i){
if(d[gfx.scaleBy] > 0){
return 'translate(0,-22)';
}else{
return 'translate(0,-2)';
}
})
.text(function(d){
_start = new Date(),
start = new Date(),
_end = new Date(),
end = new Date();
year = parseInt(d.interval.substr(0,4),10)
week = parseInt(d.interval.substr(5,2),10)
_start.setFullYear(year)
_start.setMonth(0)
_start.setDate(1)
_end.setFullYear(year)
_end.setMonth(0)
_end.setDate((week * 7))
moment_start = moment(_start).add('days',(week*7))
moment_end = moment(_end).add('days',7)
//var dateStartEnd = new Date().setDate(new Date().setFullYear(year).getDate() + (week * 7))
// if(start.getMonth() === end.getMonth()){
// dt = months[start.getMonth()]+' '+start.getDate()+'-'+end.getDate();
// }else{
// dt = months[start.getMonth()]+' '+start.getDate()+'-'+months[end.getMonth()]+' '+end.getDate();
// }
//dt = dformat1(dateStart)
// nextWeekStart = new Date()
// nextWeekEnd = new Date();
// gfx.dateCounter = gfx.dateCounter + 7
// nextWeekStart.setDate(me.startDate.getDate()-gfx.dateCounter)
// nextWeekEnd.setDate(me.endDate.getDate()-gfx.dateCounter)
// me.startDate = nextWeekStart
// me.endDate = nextWeekEnd
if(moment_start.month() === moment_end.month()){
return moment_start.format('MMM. D')+'-'+moment_end.format('D')
}else{
return moment_start.format('MMM. D')+'-'+moment_end.format('MMM. D')
}
})
// .attr('text-anchor','end')
var days = groups.selectAll('.dayWrap')
.data(function(d){ return d.entry.structured_activities })
.enter()
.append('g')
.attr('class', 'dayWrap')
days.each(function(d,n){
if(d.length > 0){
var total = _(d).pluck(gfx.scaleBy).reduce(function(d1,d2){ return d1 + d2})
}else{
var total = 0;
}
var packSize = [me.runScale(total), me.runScale(total)];
d3.select(this)
.attr('transform',function(__d){ return 'translate('+(me.bubbleXScale(n)-(packSize[0]/2))+','+(me.rowHeight - packSize[0] / 2) +')' })
if(total > 0){
pack = d3.layout.pack()
.sort(d3.descending)
.size(packSize)
.value(function(__d){ if(gfx.scaleBy in __d){ return __d[gfx.scaleBy];} else{ return 0 } })
.children(
function(__d,i){
return __d;
}
)
.radius(function(__d){
return me.runScale(__d)
})
d3.select(this).selectAll('.run')
.data(pack.nodes)
.enter()
.append('circle')
.attr('class', function(d){
var childLength = ('children' in d) ? d.children.length : 0;
return 'run run-depth-'+d.depth+' run-children-'+childLength+' run-type-'+d.workout_type
})
.attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
.attr("r", 0)
// .style('opacity', 0)
.on('mouseover', function(d,i){
// if (true) {};
if(d.depth === 0){
var parent = this.parentNode;
d3.select(parent).select('.sum').classed('activeText',true)
return
}
// var parent = this.parentNode;
d3.select(this).classed('active', true)
m = d3.mouse(this)
// p = d.avg_pace.split(':')[0]+':'+d.avg_pace.split(':')[1]
me.tooltip.content('<div class="block">'+d.name+'</div><div class="block pace">Distance: '+gfx.getMile(d.distance).toFixed(1)+'mi.</div><div class="block pace">Moving Time: '+gfx.format_time_value(d.moving_time)+'</div>')
x = event.pageX - m[0] - (me.tooltip.$el.width() / 2) - 10
y = event.pageY - m[1] - gfx.tooltip.$el.height() - 50
gfx.tooltip.position({ left: x, top: y }).show()
d3.select(this).classed('active', true)
// console.log('day: ', d.dayOfWeek)
})
.on('mouseout', function(){
me.tooltip.hide();
var parent = this.parentNode;
d3.select(this).classed('active', false)
d3.select(parent).select('.sum').classed('activeText',false)
})
}
// .padding(-2)
// blocks
d3.select(this)
.append('rect')
.attr('class',function(d){ return (total === 0) ? 'text-bg' : 'text-bg-hidden' })
.attr('width',40)
.attr('height', 30)
.attr('transform', function(d){ return 'translate(-18,-10)' })
.style('opacity',0)
d3.select(this)
.append('text')
.attr('class', function(d){
if(total === 0){
return 'sum rest'
}else{
return 'sum no-rest'
}
})
.text(function(){
if (total > 0){
var t = me.getMile(total).toFixed(1).toString()
t = (t.indexOf('.0') > 0) ? t.replace('.0','') : t;
return t
}else{
return 'Rest'
}
})
.attr('text-anchor', 'middle')
.attr('dy','4px')
.attr('transform', function(d){ return 'translate('+packSize[0]/2+','+(packSize[0] / 2) +')' })
.style('font-size',0)
.style('opacity',0)
// text
});
revealTransition = d3.transition().duration(1000)
.delay(function(d, i) { return i / 11 * 1000; })
revealTransition.selectAll('.run')
.attr("r", function(d,i){
return d.r;
})
.style("opacity", 1)
revealTransition.selectAll('.text-bg').style('opacity',1)
revealTransition.selectAll('.sum').style('font-size','13px').style('opacity',1)
revealTransition.transition()
},
renderRow: function(){
},
renderBarChart: function(){
var me = this;
this.barChart.selectAll('.weekBar')
.data(this.data).enter()
.append('rect')
.attr('class','weekBar')
.attr('x', 1 )
.attr('y', function(d){ return me.barYScale(d.interval) })
.attr('width', 0)
.attr('height', me.barYScale.rangeBand())
.on('click', function(d){
d3.selectAll('.weekBar').classed('weekBar-selected', false)
d3.select(this).classed('weekBar-selected', true)
var offset = $('#g-rows').offset().top
var set = me.data
set.forEach(function(s,i){
if(s.week === d.week){
console.log(d)
var offset = $('.g-month-title[data-interval="'+d.entry.activities[0].formattedDate.getMonth()+'"]').offset().top
$('html,body').animate({ scrollTop: offset }, 700)
return
}
})
})
.on('mouseover', function(d){
weekStart = d.entry.activities[0].formattedDate
x = 120
x2 = me.barXScale(d[gfx.scaleBy]);
y = me.barYScale(d.interval)
t = gfx.shortMonths[weekStart.getMonth()]
me.barChart.append('text')
.attr('class','g-barLabel')
.text(function(){ return t })
.attr('transform',function(_d){ return 'translate('+x+','+y+')' })
// .attr('text-anchor','end')
.attr('dy','5')
.attr('dx','0')
})
.on('mouseout', function(d){
me.barChart.select('.g-barLabel').remove()
})
.style('opacity',0)
.transition()
.duration(700)
.delay(function(d, i) { return i / 38 * 700; })
.style('opacity',1)
.attr('width',function(d){ return me.barXScale(d[gfx.scaleBy]) })
this.barYAxis = d3.svg.axis()
.scale(me.barYScale)
.tickValues(['2013y01w','2013y12w','2013y24w','2013y36w'])
.tickSize(-me.chartStyles.barChart.width+1)
.orient('right')
.tickPadding([6])
.tickFormat(function(d){
var a = _.find(gfx.activities, function(activity){ return activity.week === parseInt(d.substr(5,2),10) })
return gfx.shortMonths[a.formattedDate.getMonth()]
})
this.barChart.append('text')
.attr('transform','translate(0,19)' )
.attr('class','g-bigBarLabel')
.text('Jan. 2013 - Sept. 2013')
this.barChart.append('line')
.attr('class','g-line')
.attr('x1','0' )
.attr('x2','0' )
.attr('y1', 25 )
.attr('y2',me.chartStyles.barChart.height )
this.barChart.append('g').attr('class','y axis')
.attr('transform','translate('+me.chartStyles.barChart.width+',-3)')
.call(this.barYAxis)
},
getTime: function(v){
var mins = (v / 60).toFixed()
var hours = (mins / 60).toFixed()
return hours+':'+mins;
},
getDistance: function(){
}
}
}();
gfx.init('galen_2013y38w')
body{
background:#f7f7f7;
overflow-x:hidden;
}
.cf:before,
.cf:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.cf:after {
clear: both;
}
/**
* For IE 6/7 only
* Include this rule to trigger hasLayout and contain floats.
*/
.cf {
*zoom: 1;
}
#g-container{
width:920px;
margin: 25px auto;
height: 100%;
padding-top:0px;
position:relative;
}
#g-log{
width:650px;
position: relative;
padding-top:15px;
}
#g-sidebar{
width:250px;
position:absolute;
left: 585px;
top:0;
bottom:0;
display:none;
background:#f7f7f7;
}
/* start top */
#g-header{
margin: 0;
padding: 0;
z-index:1000;
background: rgba(247,247,247,.85);
position:absolute;
left:0;
top:77px;
width:665px;
}
.ink-is-fixed #g-header{
box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
#g-header svg{
}
/*.ink-is-fixed #g-header{
box-shadow: 0 0 12px -5px rgba(0,0,0,.55);
}*/
/*.ink-is-fixed #g-header:after{
content: '';
height: 3px;
position: absolute;
left: 0;
right: 0;
bottom: -3px;
-webkit-mask-box-image: -webkit-linear-gradient(left,transparent 0%,rgba(0,0,0,1) 50%,transparent 100%);
background-color: transparent;
background-image: -webkit-linear-gradient(top,rgba(0,0,0, .3),transparent);
background-image: -moz-linear-gradient(top,rgba(0,0,0, .3),transparent);
background-image: -ms-linear-gradient(top,rgba(0,0,0, .3),transparent);
background-image: -o-linear-gradient(top,rgba(0,0,0, .3),transparent);
background-image: linear-gradient(top,rgba(0,0,0, .2),transparent);
z-index: 1001;
}
*/
.g-mug{
float: left;
display: inline;
margin: 0 12px 0 20px;
width: 50px;
height: 50px;
background: #ddd;
position: relative;
}
.g-hed{
font-size: 14px;
font-weight: bold;
line-height: 1.5;
font-family:sans-serif;
color: #333;
padding: 5px 0 0;
margin: 0;
}
.g-subHed{
font-size: 12px;
font-weight: normal;
line-height: 1.5;
font-family:sans-serif;
color: #666;
margin: 0;
padding: 0;
}
#g-barNav{
width: 1002px;
/*box-shadow: -2px 0 15px -5px rgba(0,0,0,.1);*/
position: relative;
margin: -24px 0 0;
/*background:rgba(255,255,255,1);*/
position: absolute;
left: 685px;
top: 0;
padding:80px 0 0;
z-index:10006;
bottom:0;
}
.g-viewToggles{
list-style-type: none;
margin: 0 0 10px;
padding: 0;
text-align: center;
/*background:#f7f7f7; */
}
/*.g-viewToggles a#{
width:71px;
padding:5px;
background: url(images/);
}*/
#toggle-distance {
/*background:url(../images/ruler.png) no-repeat 0 6px;
padding: 3px 0 3px 27px;*/
/*border-radius:2px 0 0 2px;*/
/*border-right:1px solid #aaa;*/
}
#toggle-distance a{
padding-left:0;
margin-left:0;
}
#toggle-time {
/* background:url(../images/time.png) no-repeat 1px 3px;
padding: 3px 0 3px 19px;
*/
/*border-right:1px solid #aaa;*/
}
#toggle-time a{
margin-left:0;
}
#toggle-elevation{
/* background:url(../images/elevation.png) no-repeat 0 4px;
padding: 3px 0 3px 22px;
*/
}
.g-viewToggle{
margin: 0 0px 0 0;
float: left;
font-size: 11px;
list-style-type: none;
/*
text-transform:uppercase;
background:#ccc;
text-align:center;*/
/*box-shadow: 1px 1px 0 #aaa, 2px 2px 0 #aaa, 3px 3px 0 #aaa;*/
/*box-shadow: 1px 1px 0 #aaa, 2px 2px 0 #ccc, 2px 2px 0 #aaa;
text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.3);
color:#fff;
cursor: pointer;
transition: box-shadow .3s;*/
}
.g-viewToggle a{
color:#007fb6;
font-size:11px;
padding: 7px;
cursor: pointer;
margin-left:5px;
}
.g-toggle-header{
float: none;
display:block;
clear:both;
padding:0 12px 0 0;
text-align:left;
font-size:12px;
margin-bottom:2px;
}
.g-viewToggle a:hover{
color:#333;
text-shadow: none;
}
.g-scaleBy-distance #toggle-distance a,
.g-scaleBy-time #toggle-time a,
.g-scaleBy-elev_gain #toggle-elevation a{
color:#000;
font-weight:bold;
}
.g-days{
list-style-type: none;
margin: 0;
padding: 0;
/*border: 1px solid #ddd;*/
box-shadow: 1px 1px 1px #ddd;
background: #fff;
}
.ink-is-fixed .g-days{
border-top: 1px solid #fff;
box-shadow:none;
}
.g-day{
list-style-type:none;
font-size: 11px;
color:#999;
margin: 0;
padding: 8px 0 6px;
float: left;
text-align:center;
width: 76px;
/*text-transform:uppercase;*/
font-weight: normal;
position:relative;
}
.g-day:after{
content: '';
position: absolute;
right:0;
top:6px;
bottom:6px;
width:1px;
background:#eee;
}
.g-day:last-child:after{
background:#fff;
}
.g-day-intro{
width: 121px;
text-align:center;
color: #fff;
}
/*.g-day-intro:after{
width:0;
}
.g-day-intro:before{
width:154px;
left:-1px;
top:-1px;
box-shadow:inset;
height:28px;
box-shadow: inset 0 0 0 1px rgb(252,76,2);
content: '';
position:absolute;
}*/
/* end top */
/* charts */
.weekBar{
fill: rgb(168, 213, 224);
shape-rendering:crispEdges;
transition: fill .1s;
cursor:pointer;
}
.weekBar:hover,.weekBar-selected{
fill: rgb(92, 181, 202)
}
#g-rows{
width: 670px;
padding-top:30px;
}
.g-row{
margin-bottom:15px;
}
.divider{
stroke: #ccc;
stroke-dasharray: 1,1;
shape-rendering: crispEdges;
}
.run{
transition-property: fill-opacity, fill;
transition-duration: 1s, 1s;
stroke: none;
fill-opacity:.7;
fill: #a5d4e1;
}
.run-depth-0{
fill: #f1f1f1;
stroke-width: 1px;
stroke-opacity: .85;
transition: stroke-width .4s;
fill-opacity: .35;
stroke-dasharray: 1,2;
stroke: #aaa;
}
circle.active{
stroke-width: 2.5px;
stroke: #333;
fill-opacity:1;
}
/*.active circle.run-depth-0{
stroke-width:4.5px;
stroke;
}*/
text.time,
text.distance,
text.sum{
transition: opacity .7s;
font-size: 13px;
font-family:sans-serif;
fill:#666;
pointer-events: none;
}
.ink-tooltip{
max-width: 280px;
background: rgba(255,255,255,.95);
box-shadow: 0px 1px 3px rgba(0,0,0,.1);
text-align: left;
padding: 10px;
z-index: 100000;
font-size: 12px;
position:absolute;
color:#333;
/*pointer-events:none;*/
border:1px solid #ddd;
transition: width .3s;
/*border-bottom-color:#efefef;
border-right-color:#efefef;*/
}
.ink-tooltip:after{
/*pointer-events:none;*/
content: '';
width: 0;
height: 0;
display:inline-block;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid rgba(0,0,0,.8);
margin:100px 0 0;
z-index:10000;
position:absolute;
left:45%;
bottom:-10px;
}
.ink-tooltip:before{
/*pointer-events:none;*/
content: '';
width: 0;
height: 0;
display:inline-block;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #fff;
margin:100px 0 0;
z-index:10001;
position:absolute;
left:45%;
bottom:-10px;
}
.ink-tooltip .block{
font-size:14px;
font-weight:bold;
padding-bottom:8px;
text-overflow: ellipsis;
margin: 0 0 2px;
/*text-align:center;*/
/*width:180px;*/
}
.ink-tooltip .block-type{
font-size:11px;
text-transform:uppercase;
color:#999;
margin: 0;
padding-bottom:3px;
font-weight:normal;
}
.block b{
display:inline-block;
width:86px;
}
.ink-tooltip .pace{
font-size:12px;
font-weight:normal;
padding-bottom:0;
}
circle.active{
stroke-width: 2.5px;
stroke: #999;
fill-opacity:1;
stroke-opacity:.5;
}
text.time,
text.distance,
text.sum,
text.rest{
transition: font-size .3s;
font-size: 12px;
font-family:sans-serif;
fill:#666;
fill-opacity:1;
}
text.rest{
}
text.activeText{
transition: font-size .3s;
font-size:15px !important;
}
text.rest{
font-size:10px;
fill-opacity:.4;
fill:#333;
cursor:default;
/*text-transform: uppercase;*/
}
text.rest:hover{
fill-opacity:1;
}
.weekTotal{
font-size:18px;
font-weight:bold;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
}
.weekTotal-time{
font-size:11px;
font-weight:normal;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
fill:#999;
}
.weekTotal-elev{
font-size:11px;
font-weight:normal;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
fill:#999;
}
.divider{
stroke: #ccc;
stroke-dasharray: 1,1;
shape-rendering: crispEdges;
}
.text-bg{
fill:#f7f7f7;
point-events: none;
}
.text-bg-hidden{
display:none;
}
.dateRange{
font-size:10px;
fill:#999;
text-transform:uppercase;
}
/* .g-scaleBy-elev_gain circle{
fill: #aaa;
}*/
#g-barNav-chart{
background: #fff;
width: 200px;
padding: 4px 11px 12px 0;
box-shadow: 1px 1px 0px #ddd, 2px 2px 0px #ddd;
border-radius: 4px;
/*min-height:300px;*/
/*display: none;*/
}
#g-barNav-chart .domain{
stroke-width: 1px;
fill: #999;
display:none;
}
#g-barNav svg{
/*border-bottom:1px solid #ddd;*/
}
.g-bigBarLabel{
font-size:13px;
fill:#333;
font-weight:bold;
pointer-events: none
}
.g-smallBarLabel{
font-size:11px;
fill:#555;
font-weight:normal;
pointer-events: none
}
.g-barLabel{
font-size:11px;
fill:#555;
pointer-events: none;
}
.g-line{
stroke-width:1px;
stroke:#fff;
shape-rendering:crispEdges;
}
.run-depth-0.run-children-1{
display: none;
}
.run-type-0{
cursor:pointer;
}
.run-type-1{
fill:rgb(255, 184, 212);
cursor:pointer;
}
.run-type-2{
fill:rgb(138, 185, 142);
cursor:pointer;
}
.run-type-3{
fill: rgb(250, 198, 87);
cursor:pointer;
}
#g-timeNav{
list-style-type: none;
margin: 0;
padding:0;
box-shadow:1px 1px 0px #fc4c02, 2px 2px 0px #fc4c02;
width:201px;
border-radius: 0 5px 0 0;
}
#g-timeNav li{
list-style-type: none;
margin: 0;
padding:0;
float:left;
}
#g-timeNav li:first-child a{
border-radius: 4px 0 0 0;
overflow:hidden;
}
#g-timeNav li:last-child a{
border-radius: 0 4px 0 0;
overflow:hidden;
}
#g-timeNav li a{
display:block;
background:#fc4c02;
color:#ffded2;
text-align:center;
width:67px;
padding:9px 0;
font-size:12px;
text-decoration: none;
text-shadow: 1px 1px 3px rgba(0,0,0,.3);
position:relative;
transition:background .4s;
}
#g-timeNav li.selected a,
#g-timeNav li a:hover{
box-shadow:inset 0 0 12px rgba(0,0,0,.15);
text-shadow: 1px 1px 3px rgba(0,0,0,.9);
color:rgba(255,255,255,1);
background:#e23c03;
}
#g-timeNav li.selected a:before,
#g-timeNav li a:before:hover{
content: "";
position:absolute;
left:0;
top:0;
bottom:0;
width:1px;
background:rgba(0,0,0,.1);
pointer-events: none;
z-index:100;
}
#g-timeNav li.selected a:after,
#g-timeNav li a:after:hover{
content: "";
position:absolute;
right:0;
top:0;
bottom:0;
width:1px;
background:rgba(0,0,0,.1);
pointer-events: none;
z-index:100;
}
#row-prev,
#row-next{
width:30px;
text-indent:-1000em;
outline:none;
margin: 1px 0 0 1px;
visibility:hidden;
}
#row-prev:hover,
#row-next:hover{
background-color:#f7f7f7;
cursor:pointer;
}
#row-prev{
background: url(up1.png) no-repeat center center;
}
#row-next{
background: url(down1.png) no-repeat center center;
}
#row-next:after{
display:none;
}
#row-summary{
text-shadow: px 1px 0px rgba(0,0,0,.1);
font-size: 14px;
color: #555;
padding-right: 7px;
padding-left: 18px;
text-align: left;
width: 94px;
padding-top: 6px;
font-weight:bold;
}
#row-summary:after{
background:#fff;
}
#g-header-overlay{
position:fixed;
top:63px;
left:0;
right:0;
height:18px;
background:#fff;
background: linear-gradient(to top, rgba(248,248,248,0) 0%,rgba(248,248,248,.9) 100%);
pointer-events:none;
z-index:100;
display:none;
}
.ink-is-fixed #g-header-overlay{
display:block;
}
#g-footer-overlay{
position:fixed;
bottom:0;
left:0;
right:0;
height:30px;
background:#fff;
background: linear-gradient(to bottom, rgba(248,248,248,0) 0%,rgba(248,248,248,1) 100%);
pointer-events:none;
}
.g-run-key{
margin: 8px 0 0 12px;
padding:0;
font-size:12px;
float:right;
}
.g-run-key dt{
font-weight:bold;
margin: 0;
padding:0;
float:left;
display:none;
}
.g-run-key dd{
font-weight:normal;
margin: 0 15px 0 0;
padding:0;
float:left;
font-size:11px;
}
.g-run-key .g-chip{
float:left;
margin:2px 5px 0 0;
width:9px;
height:9px;
background:#ddd;
border-radius:9px;
box-shadow: inset 0 0 0 1px rgba(0,0,0,.2);
}
.g-run-type-workout .g-chip{
background:orange;
}
.g-run-type-run .g-chip{
background: rgb(187,226,236);
}
.g-run-type-race .g-chip{
background:rgb(255, 184, 212);
}
.g-run-type-long .g-chip{
background: rgb(138, 185, 142);
}
.g-month-title{
font-size: 14px;
color: #555;
padding: 7px 18px 7px 10px;
margin: 0 7px 0 7px;
/*background: #fff;*/
border: 1px solid #f7f7f7;
box-shadow: 1px 2px 1px -2px rgba(0,0,0,.18);
}
.g-row:first-child .g-month-title{
visibility:hidden;
height:1px;
margin:0;
padding:0;
}
.y.axis text{
font-size:11px;
pointer-events:none;
fill:#999;
}
.y.axis line{
stroke-width:1px;
stroke:#999;
pointer-events:none;
shape-rendering:crispEdges;
}
.active .sum.no-rest{
fill-opacity:0;
transition: fill-opacity .3s;
}
.dayWrap-children-1.active .sum.no-rest{
fill-opacity:1;
}
.block-title{
font-size:16px !important;
font-weight:normal !important;
}
.g-viewToggles-main{
padding: 7px 15px 7px 12px;
margin: 0 0 0 7px;
/*width: 635px;*/
border-radius: 0 0 3px 3px;
/*background: #f7f7f7;*/
float:left;
position: relative;
/*border-left: 1px solid #dadada;
border-right: 1px solid #dadada;
border-bottom: 1px solid #dadada;*/
text-align: center;
}
.race-event{
fill:red;
shape-rendering:crispEdges;
}
.race-event-title{
font-size:11px;
color:#900;
font-weight:bold;
}
#g-volume{
width:666px;
height:77px;
background:#f7f7f7;
}
.g-key-goal-line{
stroke:#ccc;
shape-rendering:crispEdges;
stroke-width:5px;
}
.g-key-recorded-line{
stroke:rgb(168, 213, 224);
shape-rendering:crispEdges;
stroke-width:5px;
}
.g-goal-line{
fill:#ddd;
shape-rendering:crispEdges;
}
.g-goal-line-exceeded{
fill:#6F7188;
shape-rendering:crispEdges;
fill-opacity:.5;
}
.y.axis .domain{
stroke-width:1px;
stroke:#999;
shape-rendering:crispEdges;
fill:none;
}
.y.axis .tick:first-child{
display:none;
}
.day-total-depth-0{
display:none;
}
.day-total-depth-1{
display:none;
}
.day-total{
opacity:0;
font-size:10px;
pointer-events: none;
}
.active .day-total{
opacity:1;
transition: opacity .5s;
}
.g-bubble-chart{
margin-top:-20px;
}
#typeToggle:focus{
/*box-shadow: 0 0 5px rgba(0,0,0,.3);
outline:none;*/
}
.g-race-collection{
margin:0 0 20px 15px;
padding:0;
list-style-type:none;
font-size:13px;
}
.g-month-head{
text-transform:uppercase;
font-size:11px;
color:#888;
margin: 0 0 0;
padding-bottom:2px;
}
.g-month-head a{
font-weight:bold;
color:#666;
text-decoration:none;
font-family:arial,sans-serif;
}
.g-month-head a:hover{
text-decoration:underline;
}
.g-race{
margin: 0 0 5px 0;
padding: 0 0 5px;
border-bottom:1px dotted #ddd;
/*line-height:1.5;*/
}
.g-race:last-child{
border-bottom:none;
margin-bottom: 0;
padding-bottom: 0;
}
.g-race a{
text-decoration:none;
font-size:11px;
color:#007fb6;
width:170px;
text-overflow:ellipsis;
display:inline-block;
}
.g-race a:hover{
text-decoration:underline;
}
.g-race-history-hed{
margin: 0 0 10px 15px;
padding: 15px 0 5px;
font-size:14px;
color:#333;
border-bottom:1px solid #000;
}
#strava-header{
height:38px;
background:#fff;
box-shadow:0 1px 3px -1px rgba(0,0,0,0.05);
}
/* calendar */
.g-cal{
padding:0;
margin: 0 15px 15px;
list-style-type: none;
border-collapse: collapse;
width:180px;
}
.g-cal td{
cursor:pointer;
text-align:center;
list-style-type: none;
padding:5px 0;
font-size:11px;
transition:background .2s;
background:#fff;
}
.g-cal tr:hover td,
.g-cal tr.g-current-row td{
background:#FCFCD1;
}
.g-cal-day-row-3:first-child{
color:#0f0;
}
.g-row-break{
clear:left;
}
.g-last-month{
color:#999;
}
.g-cal-day-today{
box-shadow : inset 0 0 0 2px orange;
font-weight:bold;
}
.g-cal-head{
font-weight:bold;
margin:0;
padding:0 0 0;
text-align:center;
font-size:14px;
width:150px;
line-height:1.8;
}
.g-date-nav{
width: 180px;
margin: 0 0 5px 13px;
padding: 10px 0 5px;
list-style-type:none;
/*border-bottom:1px solid #ddd;*/
}
.g-date-nav li{
float:left;
}
.g-cal-prev,
.g-cal-next{
width:15px;
text-align:center;
}
.g-cal-prev a,
.g-cal-next a{
font-size:11px;
color:orange;
text-decoration:none;
font-weight:bold;
}
// ugly get date class hacking
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
}
var gfx = function(){
return{
chartStyles: {
barChart: {
width: 666 - 110 - 5,
height: 77 - 20,
margin: { left: 110, top: 20, bottom: 0, right: 5 }
},
timeChart: {
width: 200,
height: 650,
margin: { left: 0, top: 0, bottom: 0, right: 0 }
},
bubbleChart: {
width: 650,
height: 10,
margin: { left: 40, top: 0, bottom: 0, right: 0 }
}
},
shortMonths: [
'Jan.',
'Feb.',
'Mar.',
'Apr.',
'May',
'June',
'July',
'Aug.',
'Sept.',
'Oct.',
'Nov.',
'Dec.'
],
fullMonths: [
'January',
'Febuary',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
],
startWeek: null,
endWeek: null,
hackIntervalIn: true,
minRadius: 1,
maxRadius: 26.2,
rowHeight: 90,
rowsToStart: 10,
dateCounter: 0,
scaleBy: 'distance',
startDate: new Date(2013,08,02),
endDate: new Date(2013,08,08),
init: function(user){
this.setup();
this.getData(user)
this.tooltip = new Ink.Tooltip({ align: 'aboveCenter'});
},
bindEvents: function(){
var months = $('.g-month-title');
this.offsets = [];
var me = this;
months.each(function(d,i){
me.offsets.push({ y: $(this).offset().top -20, title: $(this).text(), interval: $(this).data('interval') })
})
var hs = _.debounce($.proxy(this.handleScroll, this), 0)
$(window).scroll(hs)
},
handleScroll: function(){
var y = $(window).scrollTop()
this.offsets.forEach(function(o,i){
if(y >= o.y && i != gfx.offsets.length - 1){
if(y < gfx.offsets[i+1].y){
$('#row-summary').text(o.title)
return;
}
}
})
},
setup: function(){
// this.timeChart= d3.select("#g-barNav-chart").append("svg")
// .attr("width", this.chartStyles.timeChart.width + this.chartStyles.timeChart.margin.left + this.chartStyles.timeChart.margin.right)
// .attr("height", this.chartStyles.timeChart.height + this.chartStyles.timeChart.margin.top + this.chartStyles.timeChart.margin.bottom)
// .append("g")
// .attr("transform", "translate(" + this.chartStyles.timeChart.margin.left + "," + this.chartStyles.timeChart.margin.top + ")");
this.barChart = d3.select("#g-volume").append("svg")
.attr("width", this.chartStyles.barChart.width + this.chartStyles.barChart.margin.left + this.chartStyles.barChart.margin.right)
.attr("height", this.chartStyles.barChart.height + this.chartStyles.barChart.margin.top + this.chartStyles.barChart.margin.bottom)
.append("g")
.attr("transform", "translate(" + this.chartStyles.barChart.margin.left + "," + this.chartStyles.barChart.margin.top + ")");
},
getData: function(user){
var me = this;
d3.json(user+'.json',function(data){
me.handleData(data)
});
},
getDatesFromInterval: function(interval){
},
handleData: function(data){
var me = this;
// this.formatDate = d3.time.format("%Y-%m-%dT%H:%M:%S-%H:%M");
this.formatDate = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%L+00:00");
this.intervalDate = d3.time.format("%Y\y%W\w");
data.forEach(function(d){
d.entry.structured_activities = [
[],
[],
[],
[],
[],
[],
[]
];
if(d.entry.activities.length > 0){
d.entry.activities.forEach(function(activity,n){
activity.formattedDate = new Date(0);
activity.formattedDate.setUTCSeconds(activity.start_date - activity.utc_offset)
activity.dayOfWeek = activity.formattedDate.getDay()
activity.week = activity.formattedDate.getWeek()
d.week = activity.week;
activity.month_year = activity.formattedDate.getMonth()+'_'+activity.formattedDate.getFullYear()
d.entry.structured_activities[activity.dayOfWeek].push(activity);
})
}
});
// //if(this.hackIntervalIn === true){
// c = this.startWeek;
// data.forEach(function(d, i){
// data[i].week = c;
// data[i].distance = 0
// data[i].moving_time = 0
// data[i].elev_gain = 0
// data[i].activities = [
// [], //0
// [], //1
// [], //2
// [], //3
// [], //4
// [], //5
// [] //6
// ]
// c++;
// if(d.length > 0){
// d.forEach(function(_d){
// _d.formattedDate = gfx.formatDate2.parse(_d.start_date_local);
// _d.dayOfWeek = _d.formattedDate.getDay();
// _d.week = _d.formattedDate.getWeek();
// data[i].formattedDate = _d.formattedDate.getMonth()
// data[i].activities[_d.dayOfWeek].push(_d);
// // add it all up
// data[i].distance += _d.distance;
// data[i].moving_time += _d.moving_time;
// data[i].elev_gain += _d.elev_gain;
// });
// }
// });
// }
// console.log(_.pluck(data, 'week'))
this.data = data.reverse();
var activities = _.map(this.data, function(d){ return d.entry.activities; });
this.activities = _.flatten(activities);
this.activities = _.reject(this.activities, function(activity){ return activity.formattedDate.getFullYear() === 2012 })
this.dates = _.map(this.activities, function(d){ return d.formattedDate })
this.months = _.toArray(d3.nest()
.key(function(d){ return d.month_year })
.map(this.activities))
this.races = _.toArray(d3.nest()
.key(function(d){ return d.month_year })
.key(function(d){ return d.workout_type })
.map(_.select(this.activities, function(a){ return a.workout_type === 1 })))
this.setScales();
this.render();
},
setScales: function(){
var me = this;
var intervals = _.pluck(this.data, 'interval')
$('body').attr('class','g-scaleBy-'+gfx.scaleBy);
this.timeYScale = d3.time.scale()
.range([0, this.chartStyles.timeChart.height])
.domain(d3.extent(this.dates).reverse())
this.barXScale = d3.scale.ordinal()
.rangeBands([this.chartStyles.barChart.margin.left, this.chartStyles.barChart.width])
.domain(intervals)
this.barYScale = d3.scale.linear()
.range([0,this.chartStyles.barChart.height])
.domain(d3.extent(this.data, function(d){ return d.distance }))
.nice()
this.barYAxisScale = d3.scale.linear()
.range([this.chartStyles.barChart.height,0])
.domain(d3.extent(this.data, function(d){ return d.distance }))
.nice()
this.bubbleXScale = d3.scale.ordinal()
.rangeBands([me.chartStyles.bubbleChart.margin.left, me.chartStyles.bubbleChart.width])
.domain([8,1,2,3,4,5,6,0])
ext = d3.extent(this.activities, function(d){ return d[gfx.scaleBy] })
if(this.scaleBy === 'distance'){
this.runScale = d3.scale.sqrt()
.range([5, 26])
.domain([5, d3.max(this.activities, function(d){ return d[gfx.scaleBy] })])
}else{
this.runScale = d3.scale.sqrt()
.range([this.minRadius, 26.2])
.domain([1, d3.max(this.activities, function(d){ return d[gfx.scaleBy] })]);
}
},
format_distance_value: function(val){
return this.getMile(val).toFixed(1)
},
format_time_value: function(val){
// var totalSec = new Date().getTime() / 1000;
var totalSec = val
var hours = parseInt( totalSec / 3600 ) % 24;
var minutes = parseInt( totalSec / 60 ) % 60;
var seconds = totalSec % 60;
var result = (hours < 10 ? hours+'hr' : hours+'hr') + " " + (minutes < 10 ? "0" + minutes+'min' : minutes+'min');
return result
},
format_elev_gain_value: function(val){
return val.toString().replace('.0','')
},
elev_gain_suffix: function(){ return 'ft' },
distance_suffix: function(){ return 'mi' },
time_suffix: function(){ return '' },
getMile: function(distance){
return distance * 0.000621371
},
getMeter: function(){
},
updateScales: function(){
this.setScales();
},
update: function(scaleBy){
var me = this;
this.scaleBy = scaleBy;
this.setScales()
// this.barChart.selectAll('.weekBar')
// .transition()
// .duration(700)
// .attr('width', function(d){ return me.barXScale(d[gfx.scaleBy]) })
var days = d3.selectAll('.dayWrap')
d3.selectAll('.weekTotal').text(function(d){ if(d[gfx.scaleBy]) { return me['format_'+gfx.scaleBy+'_value'](d[gfx.scaleBy])+gfx[gfx.scaleBy+'_suffix']() }})
days.each(function(d,n){
if(d.length > 0){
var total = _(d).pluck(gfx.scaleBy).reduce(function(d1,d2){ return d1 + d2})
}else{
var total = 0;
}
var packSize = [me.runScale(total), me.runScale(total)];
// d3.select(this)
// .attr('transform',function(__d){ return 'translate('+(me.bubbleXScale(n)-(packSize[0]/2))+','+(me.rowHeight - packSize[0] / 2) +')' })
if(total > 0){
pack = d3.layout.pack()
.sort(d3.descending)
.size(packSize)
.value(function(__d){ if(gfx.scaleBy in __d){ return __d[gfx.scaleBy];} else{ return 0 } })
.children(
function(__d,i){
return __d;
}
)
.radius(function(__d){
return me.runScale(__d)
})
var runs = d3.select(this).selectAll('.run')
.data(pack.nodes)
d3.select(this).select('.sum.no-rest')
.transition()
.attr('transform', function(d){ return 'translate('+packSize[0]/2+','+(packSize[0] / 2) +')' })
.text(function(__d){
if(gfx.scaleBy === 'distance'){
var t = me.getMile(total).toFixed(1).toString()
t = (t.indexOf('.0') > 0) ? t.replace('.0','') : t;
return t
}else{
return me['format_'+gfx.scaleBy+'_value'](__d.value)+gfx[gfx.scaleBy+'_suffix']()
}
})
runs.transition()
.attr("transform", function(__d) { return "translate(" + __d.x + "," + (__d.y)+ ")"; })
.attr("r", function(__d){
return __d.r
})
}else{
}
});
// if(d.length > 0){
// var total = _(d).pluck(gfx.scaleBy).reduce(function(d1,d2){ return d1 + d2})
// }else{
// var total = 0;
// }
// var packSize = [me.runScale(total), me.runScale(total)];
// // d3.select(this)
// // .attr('transform',function(__d){ return 'translate('+(me.bubbleXScale(n)-(packSize[0]/2))+','+(me.rowHeight - packSize[0] / 2) +')' })
// // d3.select(this)
// // .append('rect')
// // .attr('class',function(d){ return (total === 0) ? 'text-bg' : 'text-bg-hidden' })
// // .attr('width',40)
// // .attr('height', 30)
// // .attr('transform', function(d){ return 'translate(-18,-10)' })
// // .style('opacity',0)
// if(total > 0){
// pack = d3.layout.pack()
// .sort(d3.ascending)
// .size(packSize)
// .value(function(__d){ if(gfx.scaleBy in __d){ return __d[gfx.scaleBy];} else{ return 0 } })
// .children(
// function(__d,i){
// return __d;
// }
// )
// .radius(function(__d){
// return me.runScale(__d)
// })
// d3.selectAll('.sum')
// .text(function(){
// if (total > 0){
// if(scaleBy === 'elev_gain'){
// return total+'ft.'
// }else{
// var t = me.getMile(total).toFixed(1).toString()
// t = (t.indexOf('.0') > 0) ? t.replace('.0','') : t;
// return t
// }
// }else{
// return 'Rest'
// }
// })
// .attr('text-anchor', 'middle')
// .attr('dy','4px')
// .attr('transform', function(d){ return 'translate('+packSize[0]/2+','+(packSize[0] / 2) +')' })
// // .style('font-size',0)
// // .style('opacity',0)
// // text
// d3.select(this).selectAll('.run')
// .data(pack.nodes)
// .enter()
// .append('circle')
// .attr('class', function(d){ return 'run run-depth-'+d.depth+' run-type-'+d.workout_type })
// .attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
// .attr("r", 0)
// transition = me.bubbleChart.transition().duration(700).delay(0)
// transition.selectAll('.run')
// .transition()
// .attr("r", function(d,i){
// return d.r;
// })
// .attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
// }
// })
//
//
// d3.select(this).selectAll('.run')
// .data(pack.nodes)
// .enter()
// .append('circle')
// .attr('class', function(d){ return 'run run-depth-'+d.depth })
// .attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
// .attr("r", 0)
// });
// transition = this.bubbleChart.transition().duration(1000).delay(0)
// transition.selectAll('.run')
// .update()
// .transition()
// .attr("r", function(d,i){
// return d.r;
// })
},
render: function(){
this.renderBarChart();
this.renderTimeChart();
// rows = $('#g-rows');
var bubble = this.chartStyles.bubbleChart;
// this.bubbleChart = d3.select('#g-rows').append('svg')
// .attr("width", bubble.width + bubble.margin.left + bubble.margin.right)
// .attr("height", (this.rowHeight * this.data.length) + bubble.margin.top + bubble.margin.bottom)
// .append("g")
// .attr("transform", "translate(" + bubble.margin.left + "," + bubble.margin.top + ")");
// this.renderRows();
this.renderMonthRows();
this.bindEvents();
this.fixie = new Ink.Fixie('#g-header', {offsetY: 0})
this.navFixie = new Ink.Fixie('#g-barNav', {offsetY: 0})
this.navFixie2 = new Ink.Fixie('#g-barNav-chart', {offsetY: 0})
},
workout_types: [
'Run',
'Race',
'Long Run',
'Workout'
],
renderMonthRows: function(){
var bubble = this.chartStyles.bubbleChart;
var me = this;
var rows = d3.select('#g-rows').selectAll('.g-row')
.data(this.months)
.enter()
.append('div')
.attr('class','g-row')
rows.append('h3')
.attr('class','g-month-title')
.html(function(d,i){
if(d[i]){
return gfx.fullMonths[d[i].formattedDate.getMonth()]
}
})
.attr('data-interval',function(d){ return d[0].formattedDate.getMonth() })
var bubbleCharts = rows.append('svg')
.attr('class','g-bubble-chart')
.attr('width', bubble.width + bubble.margin.left + bubble.margin.right)
.attr("height", gfx.rowHeight*4.5)
.append('g')
.attr('transform',"translate(" + bubble.margin.left + "," + bubble.margin.top + ")");
var groups = bubbleCharts.selectAll('.week')
.data(function(d){
// // _.select(gfx.data, )
var weeks = _.pluck(d, 'week')
return _.filter(gfx.data, function(_d){ return _.contains(weeks,_d.week) })
// return _.toArray(d3.nest().key(function(_d){ return _d.week }).map(d))
})
.enter()
.append('g')
.attr('class', 'week')
.attr('transform',function(d,i){
return 'translate(0,'+(i*gfx.rowHeight)+')';
});
var dividers = groups.selectAll('.divider')
.data(function(d){ return [ { distance: d[gfx.scaleBy] }] })
.enter()
.append('line')
.attr('class', 'divider')
.attr('x1', this.chartStyles.bubbleChart.margin.left +10)
.attr('y1', me.rowHeight - 1)
.attr('x2', 0)
.attr('y2', me.rowHeight - 1)
// .style('opacity', 0)
.transition()
.duration(1000)
.delay(function(d, i){ return i / me.data.length * 1000 })
.attr('x2',this.bubbleXScale(0))
var totals = groups.selectAll('.weekTotals')
.data(function(d){ return [ { interval: d['interval'], distance: d['distance'], time: d['moving_time'], elev_gain: d['elev_gain'] }]})
.enter()
.append('g')
.attr('class','weekTotals')
.attr('transform',function(d,i){
return 'translate(45,91)';
})
.attr('text-anchor','end')
totals.append('text')
.attr('class', 'weekTotal')
.text(function(d){ if(d[gfx.scaleBy]) { return me['format_'+gfx.scaleBy+'_value'](d[gfx.scaleBy])+gfx[gfx.scaleBy+'_suffix']() }})
.attr('text-anchor','end')
totals.append('text')
.attr('class', 'weekTotal-time')
.text(function(d){ if(d[gfx.scaleBy]) {
return me['format_time_value'](d.time)+gfx.time_suffix()
}})
.attr('transform','translate(0,17)')
.attr('text-anchor','end')
totals.append('text')
.attr('class', 'weekTotal-elev')
.text(function(d){ if(d[gfx.scaleBy]) {
return me['format_elev_gain_value'](d.elev_gain)+gfx.elev_gain_suffix()
}})
.attr('transform','translate(0,32)')
.attr('text-anchor','end')
var dformat1 = d3.time.format("%b. %e")
var dformat2 = d3.time.format("%-e")
var months = [
'Jan.',
'Feb.',
'Mar.',
'Apr.',
'May',
'June',
'July',
'Aug.',
'Sept.',
'Oct.',
'Nov.',
'Dec.'
]
var dateRanges = totals.append('text')
.attr('class','dateRange')
.attr('transform',function(d,i){
if(d[gfx.scaleBy] > 0){
return 'translate(0,-22)';
}else{
return 'translate(0,-2)';
}
})
.text(function(d){
_start = new Date(),
start = new Date(),
_end = new Date(),
end = new Date();
year = parseInt(d.interval.substr(0,4),10)
week = parseInt(d.interval.substr(5,2),10)
_start.setFullYear(year)
_start.setMonth(0)
_start.setDate(1)
_end.setFullYear(year)
_end.setMonth(0)
_end.setDate((week * 7))
moment_start = moment(_start).add('days',(week*7))
moment_end = moment(_end).add('days',7)
if(moment_start.month() === moment_end.month()){
return moment_start.format('MMM. D')+'-'+moment_end.format('D')
}else{
return moment_start.format('MMM. D')+'-'+moment_end.format('MMM. D')
}
})
// .attr('text-anchor','end')
var days = groups.selectAll('.dayWrap')
.data(function(d){ return d.entry.structured_activities })
.enter()
.append('g')
.attr('class', function(d){ return 'dayWrap'+' dayWrap-children-'+d.length })
days.each(function(d,n){
if(d.length > 0){
var total = _(d).pluck(gfx.scaleBy).reduce(function(d1,d2){ return d1 + d2})
}else{
var total = 0;
}
var packSize = [me.runScale(total), me.runScale(total)];
d3.select(this)
.attr('transform',function(__d){ return 'translate('+(me.bubbleXScale(n)-(packSize[0]/2))+','+(me.rowHeight - packSize[0] / 2) +')' })
if(total > 0){
pack = d3.layout.pack()
.sort(d3.descending)
.size(packSize)
.value(function(__d){ if(gfx.scaleBy in __d){ return __d[gfx.scaleBy];} else{ return 0 } })
.children(
function(__d,i){
return __d;
}
)
.radius(function(__d){
return me.runScale(__d)
})
d3.select(this).selectAll('.run')
.data(pack.nodes)
.enter()
.append('circle')
.attr('class', function(d){
var childLength = ('children' in d) ? d.children.length : 0;
return 'run run-depth-'+d.depth+' run-children-'+childLength+' run-type-'+d.workout_type
})
.attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
.attr("r", 0)
// .style('opacity', 0)
.on('mouseover', function(d,i){
// if (true) {};
if(d.depth === 0){
var parent = this.parentNode;
d3.select(parent).classed('active', true)
return
}
var parent = this.parentNode;
d3.select(parent).classed('active', true)
d3.select(this).classed('active', true)
m = d3.mouse(this)
// p = d.avg_pace.split(':')[0]+':'+d.avg_pace.split(':')[1]
me.tooltip.content('<div class="block block-type">'+gfx.workout_types[d.workout_type]+'</div><div class="block block-title">'+d.name+'</div><div class="block pace"><b>Distance:</b> '+gfx.getMile(d.distance).toFixed(1)+'mi.</div><div class="block pace"><b>Moving Time:</b> '+gfx.format_time_value(d.moving_time)+'</div><div class="block pace"><b>Avg Pace:</b> '+d.speed+'/mi</div>')
x = event.pageX - m[0] - (me.tooltip.$el.width() / 2) - 10
y = event.pageY - m[1] - gfx.tooltip.$el.height() - 50
gfx.tooltip.position({ left: x, top: y }).show()
d3.select(this).classed('active', true)
// console.log('day: ', d.dayOfWeek)
})
.on('mouseout', function(){
me.tooltip.hide();
var parent = this.parentNode;
d3.select(this).classed('active', false)
d3.select(parent).classed('active', false)
d3.select(parent).select('.sum').classed('activeText',false)
})
d3.select(this).selectAll('.day-total')
.data(pack.nodes)
.enter()
.append('text')
.attr('class',function(d){
var depth = ('parent' in d) ? d.parent.length : 0;
return 'day-total day-total-depth-'+depth+' day-total-value-'+d.value
})
.text(function(d){
var t = me.getMile(d.distance).toFixed(1).toString()
t = (t.indexOf('.0') > 0) ? t.replace('.0','') : t;
return t
})
// .style('font-size', function(d){
// return '100%'
// })
.attr('transform',function(d){
return 'translate('+d.x+','+d.y+')'
})
.attr('text-anchor', 'middle')
.attr('dy','4px')
}
// .padding(-2)
// blocks
d3.select(this)
.append('rect')
.attr('class',function(d){ return (total === 0) ? 'text-bg' : 'text-bg-hidden' })
.attr('width',40)
.attr('height', 30)
.attr('transform', function(d){ return 'translate(-18,-10)' })
.style('opacity',0)
d3.select(this)
.append('text')
.attr('class', function(d){
if(total === 0){
return 'sum rest'
}else{
return 'sum no-rest'
}
})
.text(function(){
if (total > 0){
var t = me.getMile(total).toFixed(1).toString()
t = (t.indexOf('.0') > 0) ? t.replace('.0','') : t;
return t
}else{
return 'rest'
}
})
.attr('text-anchor', 'middle')
.attr('dy','4px')
.attr('transform', function(d){ return 'translate('+packSize[0]/2+','+(packSize[0] / 2) +')' })
.style('font-size',0)
.style('opacity',0)
// text
});
revealTransition = d3.transition().duration(1000)
.delay(function(d, i) { return i / 11 * 1000; })
revealTransition.selectAll('.run')
.attr("r", function(d,i){
return d.r;
})
.style("opacity", 1)
revealTransition.selectAll('.text-bg').style('opacity',1)
revealTransition.selectAll('.sum').style('font-size','13px').style('opacity',1)
revealTransition.transition()
},
renderRows: function(){
var me = this
var groups = this.bubbleChart.selectAll('.week')
.data(this.data)
.enter()
.append('g')
.attr('class', 'week')
.attr('transform',function(d,i){
return 'translate(0,'+(i*me.rowHeight)+')';
});
var dividers = groups.selectAll('.divider')
.data(function(d){ return [ { distance: d[gfx.scaleBy] }] })
.enter()
.append('line')
.attr('class', 'divider')
.attr('x1', this.chartStyles.bubbleChart.margin.left +10)
.attr('y1', me.rowHeight - 1)
.attr('x2', 0)
.attr('y2', me.rowHeight - 1)
// .style('opacity', 0)
.transition()
.duration(1000)
.delay(function(d, i){ return i / me.data.length * 1000 })
.attr('x2',this.bubbleXScale(0))
var totals = groups.selectAll('.weekTotals')
.data(function(d){ return [ { interval: d['interval'], distance: d['distance'], time: d['moving_time'], elev_gain: d['elev_gain'] }]})
.enter()
.append('g')
.attr('class','weekTotals')
.attr('transform',function(d,i){
return 'translate(-20,'+(i*me.rowHeight+(me.rowHeight + 5))+')';
})
totals.append('text')
.attr('class', 'weekTotal')
.text(function(d){ if(d[gfx.scaleBy]) { return me['format_'+gfx.scaleBy+'_value'](d[gfx.scaleBy])+gfx[gfx.scaleBy+'_suffix']() }})
// .attr('text-anchor','end')
var dformat1 = d3.time.format("%b. %e")
var dformat2 = d3.time.format("%-e")
var months = [
'Jan.',
'Feb.',
'Mar.',
'Apr.',
'May',
'June',
'July',
'Aug.',
'Sept.',
'Oct.',
'Nov.',
'Dec.'
]
var dateRanges = totals.append('text')
.attr('class','dateRange')
.attr('transform',function(d,i){
if(d[gfx.scaleBy] > 0){
return 'translate(0,-22)';
}else{
return 'translate(0,-2)';
}
})
.text(function(d){
_start = new Date(),
start = new Date(),
_end = new Date(),
end = new Date();
year = parseInt(d.interval.substr(0,4),10)
week = parseInt(d.interval.substr(5,2),10)
_start.setFullYear(year)
_start.setMonth(0)
_start.setDate(1)
_end.setFullYear(year)
_end.setMonth(0)
_end.setDate((week * 7))
moment_start = moment(_start).add('days',(week*7))
moment_end = moment(_end).add('days',7)
//var dateStartEnd = new Date().setDate(new Date().setFullYear(year).getDate() + (week * 7))
// if(start.getMonth() === end.getMonth()){
// dt = months[start.getMonth()]+' '+start.getDate()+'-'+end.getDate();
// }else{
// dt = months[start.getMonth()]+' '+start.getDate()+'-'+months[end.getMonth()]+' '+end.getDate();
// }
//dt = dformat1(dateStart)
// nextWeekStart = new Date()
// nextWeekEnd = new Date();
// gfx.dateCounter = gfx.dateCounter + 7
// nextWeekStart.setDate(me.startDate.getDate()-gfx.dateCounter)
// nextWeekEnd.setDate(me.endDate.getDate()-gfx.dateCounter)
// me.startDate = nextWeekStart
// me.endDate = nextWeekEnd
if(moment_start.month() === moment_end.month()){
return moment_start.format('MMM. D')+'-'+moment_end.format('D')
}else{
return moment_start.format('MMM. D')+'-'+moment_end.format('MMM. D')
}
})
// .attr('text-anchor','end')
var days = groups.selectAll('.dayWrap')
.data(function(d){ return d.entry.structured_activities })
.enter()
.append('g')
.attr('class', 'dayWrap')
days.each(function(d,n){
if(d.length > 0){
var total = _(d).pluck(gfx.scaleBy).reduce(function(d1,d2){ return d1 + d2})
}else{
var total = 0;
}
var packSize = [me.runScale(total), me.runScale(total)];
d3.select(this)
.attr('transform',function(__d){ return 'translate('+(me.bubbleXScale(n)-(packSize[0]/2))+','+(me.rowHeight - packSize[0] / 2) +')' })
if(total > 0){
pack = d3.layout.pack()
.sort(d3.descending)
.size(packSize)
.value(function(__d){ if(gfx.scaleBy in __d){ return __d[gfx.scaleBy];} else{ return 0 } })
.children(
function(__d,i){
return __d;
}
)
.radius(function(__d){
return me.runScale(__d)
})
d3.select(this).selectAll('.run')
.data(pack.nodes)
.enter()
.append('circle')
.attr('class', function(d){
var childLength = ('children' in d) ? d.children.length : 0;
return 'run run-depth-'+d.depth+' run-children-'+childLength+' run-type-'+d.workout_type
})
.attr("transform", function(d) { return "translate(" + d.x + "," + (d.y)+ ")"; })
.attr("r", 0)
// .style('opacity', 0)
.on('mouseover', function(d,i){
// if (true) {};
if(d.depth === 0){
var parent = this.parentNode;
d3.select(parent).select('.sum').classed('activeText',true)
return
}
// var parent = this.parentNode;
d3.select(this).classed('active', true)
m = d3.mouse(this)
// p = d.avg_pace.split(':')[0]+':'+d.avg_pace.split(':')[1]
me.tooltip.content('<div class="block">'+d.name+'</div><div class="block pace">Distance: '+gfx.getMile(d.distance).toFixed(1)+'mi.</div><div class="block pace">Moving Time: '+gfx.format_time_value(d.moving_time)+'</div>')
x = event.pageX - m[0] - (me.tooltip.$el.width() / 2) - 10
y = event.pageY - m[1] - gfx.tooltip.$el.height() - 50
gfx.tooltip.position({ left: x, top: y }).show()
d3.select(this).classed('active', true)
// console.log('day: ', d.dayOfWeek)
})
.on('mouseout', function(){
me.tooltip.hide();
var parent = this.parentNode;
d3.select(this).classed('active', false)
d3.select(parent).select('.sum').classed('activeText',false)
})
}
// .padding(-2)
// blocks
d3.select(this)
.append('rect')
.attr('class',function(d){ return (total === 0) ? 'text-bg' : 'text-bg-hidden' })
.attr('width',40)
.attr('height', 30)
.attr('transform', function(d){ return 'translate(-18,-10)' })
.style('opacity',0)
d3.select(this)
.append('text')
.attr('class', function(d){
if(total === 0){
return 'sum rest'
}else{
return 'sum no-rest'
}
})
.text(function(){
if (total > 0){
var t = me.getMile(total).toFixed(1).toString()
t = (t.indexOf('.0') > 0) ? t.replace('.0','') : t;
return t
}else{
return 'Rest'
}
})
.attr('text-anchor', 'middle')
.attr('dy','4px')
.attr('transform', function(d){ return 'translate('+packSize[0]/2+','+(packSize[0] / 2) +')' })
.style('font-size',0)
.style('opacity',0)
// text
});
revealTransition = d3.transition().duration(1000)
.delay(function(d, i) { return i / 11 * 1000; })
revealTransition.selectAll('.run')
.attr("r", function(d,i){
return d.r;
})
.style("opacity", 1)
revealTransition.selectAll('.text-bg').style('opacity',1)
revealTransition.selectAll('.sum').style('font-size','13px').style('opacity',1)
revealTransition.transition()
},
renderRow: function(){
},
renderTimeChart: function(){
var me = this;
var sidebarStuff = ['<h3 class="g-race-history-hed">2013 Race History</h3>']
if(gfx.races.length > 0){
gfx.races.forEach(function(race_set, i){
race_set = _.flatten(_.toArray(race_set))
console.log(race_set)
sidebarStuff.push('<ul class="g-race-collection"><li class="g-month-head"><a href="#">'+gfx.fullMonths[race_set[0].formattedDate.getMonth()]+'&nbsp;&raquo;</a></li>')
_.each(race_set, function(race,n){
sidebarStuff.push('<li class="g-race"><a href="#">'+race.name+'</a></li>')
})
sidebarStuff.push('</ul>')
});
$('#g-barNav-chart').append(sidebarStuff.join(''))
}
// this.timeYAxis = d3.svg.axis()
// .scale(me.timeYScale)
// .ticks(12)
// .tickSize(-me.chartStyles.barChart.width+1)
// .orient('right')
// .tickPadding([6])
// var events = this.timeChart.selectAll('.race-event')
// .data(races)
// .enter()
// .append('g')
// .attr('class','race-event')
// .attr('transform',function(d){ return 'translate(0,'+me.timeYScale(d.formattedDate)+')' })
// events.append('rect')
// .attr('class','race-event')
// .attr('width',5)
// .attr('height',2)
// events.append('text')
// .attr('class','race-event-title')
// .text(function(d){ return d.name })
// .attr('dy',5)
// .attr('dx',12)
// this.timeChart.append('g').attr('class','y axis')
// .attr('transform','translate('+me.chartStyles.barChart.width+',-3)')
// .call(this.timeYAxis)
// this.timeChart.append('text')
// .attr('transform','translate(10,19)' )
// .attr('class','g-bigBarLabel')
// .text('Races - Jan-Sept 2013')
},
renderBarChart: function(){
var me = this;
var goalDistance = 103098 / 2
this.barChart.selectAll('.g-goal-line')
.data(this.data).enter()
.append('rect')
.attr('class','g-goal-line')
.attr('x', function(d){ return me.barXScale(d.interval) })
.attr('y', function(d){ return Math.round(me.chartStyles.barChart.height) })
.attr('width', function(d){ return me.barXScale.rangeBand()-1 })
.attr('height', function(d){ return (me.barYScale(goalDistance)) })
.transition()
.duration(700)
.delay(function(d, i) { return i / 38 * 700; })
.attr('y', function(d){ return Math.round(me.chartStyles.barChart.height)-me.barYScale(goalDistance) })
this.barChart.selectAll('.weekBar')
.data(this.data).enter()
.append('rect')
.attr('class','weekBar')
.attr('x', function(d){ return me.barXScale(d.interval) })
.attr('y', function(d){ return me.chartStyles.barChart.height })
.attr('width', me.barXScale.rangeBand()-1)
.attr('height', function(d){ return (me.barYScale(d.distance)) })
.on('click', function(d){
d3.selectAll('.weekBar').classed('weekBar-selected', false)
d3.select(this).classed('weekBar-selected', true)
var offset = $('#g-rows').offset().top
var set = me.data
set.forEach(function(s,i){
if(s.week === d.week){
console.log(d)
var offset = $('.g-month-title[data-interval="'+d.entry.activities[0].formattedDate.getMonth()+'"]').offset().top
$('html,body').animate({ scrollTop: offset }, 700)
return
}
})
})
.on('mouseover', function(d){
weekStart = d.entry.activities[0].formattedDate
x = me.barXScale(d.interval);
y = me.barYAxisScale(d[gfx.scaleBy])
if(d.entry.activities.length > 0){
var t = gfx.shortMonths[d.entry.activities[0].formattedDate.getMonth()] +' '+d.entry.activities[0].formattedDate.getDate()+'-'
t = t + gfx.shortMonths[d.entry.activities[d.entry.activities.length-1].formattedDate.getMonth()]+' '
t = t + d.entry.activities[d.entry.activities.length-1].formattedDate.getDate()+', '
t = t + gfx.format_distance_value(d.distance)+'mi'
}else{
t = ''
}
me.barChart.append('text')
.attr('class','g-barLabel')
.text(function(d){ return t })
.attr('transform',function(_d){ return 'translate('+x+','+y+')' })
.attr('text-anchor','middle')
.attr('dy','-5')
.attr('dx','4')
})
.on('mouseout', function(d){
me.barChart.select('.g-barLabel').remove()
})
.style('opacity',0)
.transition()
.duration(700)
.delay(function(d, i) { return i / 38 * 700; })
.style('opacity',1)
.attr('y', function(d){ return me.chartStyles.barChart.height - me.barYScale(d.distance) })
var exceededGoalWeeks = _.select(this.data, function(d){
return d.distance > goalDistance
});
this.barChart.selectAll('.g-goal-line-exceeded')
.data(exceededGoalWeeks).enter()
.append('rect')
.attr('class','g-goal-line-exceeded')
.attr('x', function(d){ return me.barXScale(d.interval) })
.attr('y', function(d){ return Math.round(me.chartStyles.barChart.height)-me.barYScale(goalDistance) })
.attr('width', function(d){ return me.barXScale.rangeBand()-1 })
.attr('height', 1)
.style('opacity',0)
.transition()
.duration(1000)
.delay(function(d, i) { return i / 38 * 1000; })
.style('opacity',1)
var maxVal = d3.max(this.data, function(d){ return d.distance })
this.barYAxis = d3.svg.axis()
.scale(me.barYAxisScale)
.ticks(3)
// .tickValues([maxVal/3, maxVal])
// .tickSize(-me.chartStyles.barChart.width+1)
.orient('left')
.tickPadding([6])
.tickSize([4])
.tickFormat(function(d){
return (d*0.000621371).toFixed(0)+'mi'
})
var key = this.barChart.append('g')
.attr('transform','translate(-92,5)')
key.append('text')
.attr('transform','translate(0,0)' )
.attr('class','g-bigBarLabel')
.text('2013 Running Volume')
key.append('line')
.attr('class','g-key-goal-line')
.attr('x1','0' )
.attr('x2','17' )
.attr('y1', 16 )
.attr('y2',16)
key.append('text')
.attr('transform','translate(25,20)' )
.attr('class','g-smallBarLabel')
.text('Weekly Goal')
key.append('line')
.attr('class','g-key-recorded-line')
.attr('x1','0' )
.attr('x2','17' )
.attr('y1', 32 )
.attr('y2',32)
// key.append('text')
// .attr('transform','translate(5,35)' )
// .attr('class','g-smallBarLabel')
// .text('✓')
key.append('text')
.attr('transform','translate(25,35)' )
.attr('class','g-smallBarLabel')
.text('Run Mileage/Time')
this.barChart.append('g').attr('class','y axis')
.attr('transform','translate('+me.chartStyles.barChart.margin.left+',0)')
.call(this.barYAxis)
},
getTime: function(v){
var mins = (v / 60).toFixed()
var hours = (mins / 60).toFixed()
return hours+':'+mins;
},
getDistance: function(){
},
handleTypeChange: function(){
var type = $('#typeToggle').val();
this.update(type);
}
}
}();
gfx.init('galen__2013y38w')
//! moment.js
//! version : 2.2.1
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
(function(a){function b(a,b){return function(c){return i(a.call(this,c),b)}}function c(a,b){return function(c){return this.lang().ordinal(a.call(this,c),b)}}function d(){}function e(a){g(this,a)}function f(a){var b=a.years||a.year||a.y||0,c=a.months||a.month||a.M||0,d=a.weeks||a.week||a.w||0,e=a.days||a.day||a.d||0,f=a.hours||a.hour||a.h||0,g=a.minutes||a.minute||a.m||0,h=a.seconds||a.second||a.s||0,i=a.milliseconds||a.millisecond||a.ms||0;this._input=a,this._milliseconds=+i+1e3*h+6e4*g+36e5*f,this._days=+e+7*d,this._months=+c+12*b,this._data={},this._bubble()}function g(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function h(a){return 0>a?Math.ceil(a):Math.floor(a)}function i(a,b){for(var c=a+"";c.length<b;)c="0"+c;return c}function j(a,b,c,d){var e,f,g=b._milliseconds,h=b._days,i=b._months;g&&a._d.setTime(+a._d+g*c),(h||i)&&(e=a.minute(),f=a.hour()),h&&a.date(a.date()+h*c),i&&a.month(a.month()+i*c),g&&!d&&L.updateOffset(a),(h||i)&&(a.minute(e),a.hour(f))}function k(a){return"[object Array]"===Object.prototype.toString.call(a)}function l(a,b){var c,d=Math.min(a.length,b.length),e=Math.abs(a.length-b.length),f=0;for(c=0;d>c;c++)~~a[c]!==~~b[c]&&f++;return f+e}function m(a){return a?ib[a]||a.toLowerCase().replace(/(.)s$/,"$1"):a}function n(a,b){return b.abbr=a,P[a]||(P[a]=new d),P[a].set(b),P[a]}function o(a){delete P[a]}function p(a){if(!a)return L.fn._lang;if(!P[a]&&Q)try{require("./lang/"+a)}catch(b){return L.fn._lang}return P[a]||L.fn._lang}function q(a){return a.match(/\[.*\]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function r(a){var b,c,d=a.match(T);for(b=0,c=d.length;c>b;b++)d[b]=mb[d[b]]?mb[d[b]]:q(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function s(a,b){return b=t(b,a.lang()),jb[b]||(jb[b]=r(b)),jb[b](a)}function t(a,b){function c(a){return b.longDateFormat(a)||a}for(var d=5;d--&&(U.lastIndex=0,U.test(a));)a=a.replace(U,c);return a}function u(a,b){switch(a){case"DDDD":return X;case"YYYY":return Y;case"YYYYY":return Z;case"S":case"SS":case"SSS":case"DDD":return W;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return $;case"a":case"A":return p(b._l)._meridiemParse;case"X":return bb;case"Z":case"ZZ":return _;case"T":return ab;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return V;default:return new RegExp(a.replace("\\",""))}}function v(a){var b=(_.exec(a)||[])[0],c=(b+"").match(fb)||["-",0,0],d=+(60*c[1])+~~c[2];return"+"===c[0]?-d:d}function w(a,b,c){var d,e=c._a;switch(a){case"M":case"MM":null!=b&&(e[1]=~~b-1);break;case"MMM":case"MMMM":d=p(c._l).monthsParse(b),null!=d?e[1]=d:c._isValid=!1;break;case"D":case"DD":null!=b&&(e[2]=~~b);break;case"DDD":case"DDDD":null!=b&&(e[1]=0,e[2]=~~b);break;case"YY":e[0]=~~b+(~~b>68?1900:2e3);break;case"YYYY":case"YYYYY":e[0]=~~b;break;case"a":case"A":c._isPm=p(c._l).isPM(b);break;case"H":case"HH":case"h":case"hh":e[3]=~~b;break;case"m":case"mm":e[4]=~~b;break;case"s":case"ss":e[5]=~~b;break;case"S":case"SS":case"SSS":e[6]=~~(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=v(b)}null==b&&(c._isValid=!1)}function x(a){var b,c,d,e=[];if(!a._d){for(d=z(a),b=0;3>b&&null==a._a[b];++b)a._a[b]=e[b]=d[b];for(;7>b;b++)a._a[b]=e[b]=null==a._a[b]?2===b?1:0:a._a[b];e[3]+=~~((a._tzm||0)/60),e[4]+=~~((a._tzm||0)%60),c=new Date(0),a._useUTC?(c.setUTCFullYear(e[0],e[1],e[2]),c.setUTCHours(e[3],e[4],e[5],e[6])):(c.setFullYear(e[0],e[1],e[2]),c.setHours(e[3],e[4],e[5],e[6])),a._d=c}}function y(a){var b=a._i;a._d||(a._a=[b.years||b.year||b.y,b.months||b.month||b.M,b.days||b.day||b.d,b.hours||b.hour||b.h,b.minutes||b.minute||b.m,b.seconds||b.second||b.s,b.milliseconds||b.millisecond||b.ms],x(a))}function z(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function A(a){var b,c,d,e=p(a._l),f=""+a._i;for(d=t(a._f,e).match(T),a._a=[],b=0;b<d.length;b++)c=(u(d[b],a).exec(f)||[])[0],c&&(f=f.slice(f.indexOf(c)+c.length)),mb[d[b]]&&w(d[b],c,a);f&&(a._il=f),a._isPm&&a._a[3]<12&&(a._a[3]+=12),a._isPm===!1&&12===a._a[3]&&(a._a[3]=0),x(a)}function B(a){var b,c,d,f,h,i=99;for(f=0;f<a._f.length;f++)b=g({},a),b._f=a._f[f],A(b),c=new e(b),h=l(b._a,c.toArray()),c._il&&(h+=c._il.length),i>h&&(i=h,d=c);g(a,d)}function C(a){var b,c=a._i,d=cb.exec(c);if(d){for(a._f="YYYY-MM-DD"+(d[2]||" "),b=0;4>b;b++)if(eb[b][1].exec(c)){a._f+=eb[b][0];break}_.exec(c)&&(a._f+=" Z"),A(a)}else a._d=new Date(c)}function D(b){var c=b._i,d=R.exec(c);c===a?b._d=new Date:d?b._d=new Date(+d[1]):"string"==typeof c?C(b):k(c)?(b._a=c.slice(0),x(b)):c instanceof Date?b._d=new Date(+c):"object"==typeof c?y(b):b._d=new Date(c)}function E(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function F(a,b,c){var d=O(Math.abs(a)/1e3),e=O(d/60),f=O(e/60),g=O(f/24),h=O(g/365),i=45>d&&["s",d]||1===e&&["m"]||45>e&&["mm",e]||1===f&&["h"]||22>f&&["hh",f]||1===g&&["d"]||25>=g&&["dd",g]||45>=g&&["M"]||345>g&&["MM",O(g/30)]||1===h&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,i[4]=c,E.apply({},i)}function G(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=L(a).add("d",f),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function H(a){var b=a._i,c=a._f;return null===b||""===b?null:("string"==typeof b&&(a._i=b=p().preparse(b)),L.isMoment(b)?(a=g({},b),a._d=new Date(+b._d)):c?k(c)?B(a):A(a):D(a),new e(a))}function I(a,b){L.fn[a]=L.fn[a+"s"]=function(a){var c=this._isUTC?"UTC":"";return null!=a?(this._d["set"+c+b](a),L.updateOffset(this),this):this._d["get"+c+b]()}}function J(a){L.duration.fn[a]=function(){return this._data[a]}}function K(a,b){L.duration.fn["as"+a]=function(){return+this/b}}for(var L,M,N="2.2.1",O=Math.round,P={},Q="undefined"!=typeof module&&module.exports,R=/^\/?Date\((\-?\d+)/i,S=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/,T=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,U=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,V=/\d\d?/,W=/\d{1,3}/,X=/\d{3}/,Y=/\d{1,4}/,Z=/[+\-]?\d{1,6}/,$=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,_=/Z|[\+\-]\d\d:?\d\d/i,ab=/T/i,bb=/[\+\-]?\d+(\.\d{1,3})?/,cb=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,db="YYYY-MM-DDTHH:mm:ssZ",eb=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],fb=/([\+\-]|\d\d)/gi,gb="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),hb={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ib={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",w:"week",W:"isoweek",M:"month",y:"year"},jb={},kb="DDD w W M D d".split(" "),lb="M D H h m s w W".split(" "),mb={M:function(){return this.month()+1},MMM:function(a){return this.lang().monthsShort(this,a)},MMMM:function(a){return this.lang().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.lang().weekdaysMin(this,a)},ddd:function(a){return this.lang().weekdaysShort(this,a)},dddd:function(a){return this.lang().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return i(this.year()%100,2)},YYYY:function(){return i(this.year(),4)},YYYYY:function(){return i(this.year(),5)},gg:function(){return i(this.weekYear()%100,2)},gggg:function(){return this.weekYear()},ggggg:function(){return i(this.weekYear(),5)},GG:function(){return i(this.isoWeekYear()%100,2)},GGGG:function(){return this.isoWeekYear()},GGGGG:function(){return i(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return i(~~(this.milliseconds()/10),2)},SSS:function(){return i(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(~~(a/60),2)+":"+i(~~a%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(~~(10*a/6),4)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()}};kb.length;)M=kb.pop(),mb[M+"o"]=c(mb[M],M);for(;lb.length;)M=lb.pop(),mb[M+M]=b(mb[M],2);for(mb.DDDD=b(mb.DDD,3),g(d.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=L.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=L([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return G(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6}}),L=function(a,b,c){return H({_i:a,_f:b,_l:c,_isUTC:!1})},L.utc=function(a,b,c){return H({_useUTC:!0,_isUTC:!0,_l:c,_i:a,_f:b}).utc()},L.unix=function(a){return L(1e3*a)},L.duration=function(a,b){var c,d,e=L.isDuration(a),g="number"==typeof a,h=e?a._input:g?{}:a,i=S.exec(a);return g?b?h[b]=a:h.milliseconds=a:i&&(c="-"===i[1]?-1:1,h={y:0,d:~~i[2]*c,h:~~i[3]*c,m:~~i[4]*c,s:~~i[5]*c,ms:~~i[6]*c}),d=new f(h),e&&a.hasOwnProperty("_lang")&&(d._lang=a._lang),d},L.version=N,L.defaultFormat=db,L.updateOffset=function(){},L.lang=function(a,b){return a?(a=a.toLowerCase(),a=a.replace("_","-"),b?n(a,b):null===b?(o(a),a="en"):P[a]||p(a),L.duration.fn._lang=L.fn._lang=p(a),void 0):L.fn._lang._abbr},L.langData=function(a){return a&&a._lang&&a._lang._abbr&&(a=a._lang._abbr),p(a)},L.isMoment=function(a){return a instanceof e},L.isDuration=function(a){return a instanceof f},g(L.fn=e.prototype,{clone:function(){return L(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){return s(L(this).utc(),"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!l(this._a,(this._isUTC?L.utc(this._a):L(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},invalidAt:function(){var a,b=this._a,c=(this._isUTC?L.utc(this._a):L(this._a)).toArray();for(a=6;a>=0&&b[a]===c[a];--a);return a},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(a){var b=s(this,a||L.defaultFormat);return this.lang().postformat(b)},add:function(a,b){var c;return c="string"==typeof a?L.duration(+b,a):L.duration(a,b),j(this,c,1),this},subtract:function(a,b){var c;return c="string"==typeof a?L.duration(+b,a):L.duration(a,b),j(this,c,-1),this},diff:function(a,b,c){var d,e,f=this._isUTC?L(a).zone(this._offset||0):L(a).local(),g=6e4*(this.zone()-f.zone());return b=m(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-L(this).startOf("month")-(f-L(f).startOf("month")))/d,e-=6e4*(this.zone()-L(this).startOf("month").zone()-(f.zone()-L(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:h(e)},from:function(a,b){return L.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)},fromNow:function(a){return this.from(L(),a)},calendar:function(){var a=this.diff(L().zone(this.zone()).startOf("day"),"days",!0),b=-6>a?"sameElse":-1>a?"lastWeek":0>a?"lastDay":1>a?"sameDay":2>a?"nextDay":7>a?"nextWeek":"sameElse";return this.format(this.lang().calendar(b,this))},isLeapYear:function(){var a=this.year();return 0===a%4&&0!==a%100||0===a%400},isDST:function(){return this.zone()<this.clone().month(0).zone()||this.zone()<this.clone().month(5).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?"string"==typeof a&&(a=this.lang().weekdaysParse(a),"number"!=typeof a)?this:this.add({d:a-b}):b},month:function(a){var b,c=this._isUTC?"UTC":"";return null!=a?"string"==typeof a&&(a=this.lang().monthsParse(a),"number"!=typeof a)?this:(b=this.date(),this.date(1),this._d["set"+c+"Month"](a),this.date(Math.min(b,this.daysInMonth())),L.updateOffset(this),this):this._d["get"+c+"Month"]()},startOf:function(a){switch(a=m(a)){case"year":this.month(0);case"month":this.date(1);case"week":case"isoweek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a?this.weekday(0):"isoweek"===a&&this.isoWeekday(1),this},endOf:function(a){return a=m(a),this.startOf(a).add("isoweek"===a?"week":a,1).subtract("ms",1)},isAfter:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)>+L(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+L(a).startOf(b)},isSame:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)===+L(a).startOf(b)},min:function(a){return a=L.apply(null,arguments),this>a?this:a},max:function(a){return a=L.apply(null,arguments),a>this?this:a},zone:function(a){var b=this._offset||0;return null==a?this._isUTC?b:this._d.getTimezoneOffset():("string"==typeof a&&(a=v(a)),Math.abs(a)<16&&(a=60*a),this._offset=a,this._isUTC=!0,b!==a&&j(this,L.duration(b-a,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},hasAlignedHourOffset:function(a){return a=a?L(a).zone():0,0===(this.zone()-a)%60},daysInMonth:function(){return L.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(a){var b=O((L(this).startOf("day")-L(this).startOf("year"))/864e5)+1;return null==a?b:this.add("d",a-b)},weekYear:function(a){var b=G(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==a?b:this.add("y",a-b)},isoWeekYear:function(a){var b=G(this,1,4).year;return null==a?b:this.add("y",a-b)},week:function(a){var b=this.lang().week(this);return null==a?b:this.add("d",7*(a-b))},isoWeek:function(a){var b=G(this,1,4).week;return null==a?b:this.add("d",7*(a-b))},weekday:function(a){var b=(this._d.getDay()+7-this.lang()._week.dow)%7;return null==a?b:this.add("d",a-b)},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},get:function(a){return a=m(a),this[a.toLowerCase()]()},set:function(a,b){a=m(a),this[a.toLowerCase()](b)},lang:function(b){return b===a?this._lang:(this._lang=p(b),this)}}),M=0;M<gb.length;M++)I(gb[M].toLowerCase().replace(/s$/,""),gb[M]);I("year","FullYear"),L.fn.days=L.fn.day,L.fn.months=L.fn.month,L.fn.weeks=L.fn.week,L.fn.isoWeeks=L.fn.isoWeek,L.fn.toJSON=L.fn.toISOString,g(L.duration.fn=f.prototype,{_bubble:function(){var a,b,c,d,e=this._milliseconds,f=this._days,g=this._months,i=this._data;i.milliseconds=e%1e3,a=h(e/1e3),i.seconds=a%60,b=h(a/60),i.minutes=b%60,c=h(b/60),i.hours=c%24,f+=h(c/24),i.days=f%30,g+=h(f/30),i.months=g%12,d=h(g/12),i.years=d},weeks:function(){return h(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*(this._months%12)+31536e6*~~(this._months/12)},humanize:function(a){var b=+this,c=F(b,!a,this.lang());return a&&(c=this.lang().pastFuture(b,c)),this.lang().postformat(c)},add:function(a,b){var c=L.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=L.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=m(a),this[a.toLowerCase()+"s"]()},as:function(a){return a=m(a),this["as"+a.charAt(0).toUpperCase()+a.slice(1)+"s"]()},lang:L.fn.lang});for(M in hb)hb.hasOwnProperty(M)&&(K(M,hb[M]),J(M.toLowerCase()));K("Weeks",6048e5),L.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},L.lang("en",{ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),Q&&(module.exports=L),"undefined"==typeof ender&&(this.moment=L),"function"==typeof define&&define.amd&&define("moment",[],function(){return L})}).call(this);
[{"interval":"2013y01w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y02w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y03w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y04w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y05w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y06w","entry":{"activities":[{"id":40454658,"name":"02/10/2013 San Francisco, CA","workout_type":null,"trainer":0,"start_date_local":"2013-02-10T01:05:34-08:00","moving_time":5481,"elapsed_time":6638,"distance":21484,"speed":14111,"elev_gain":197}]},"moving_time":5481,"elapsed_time":6638,"distance":21484,"speed":14111,"elev_gain":197},{"interval":"2013y07w","entry":{"activities":[{"id":40549355,"name":"Monday Morning Slog","workout_type":null,"trainer":0,"start_date_local":"2013-02-10T22:47:13-08:00","moving_time":3168,"elapsed_time":3431,"distance":12875,"speed":14631,"elev_gain":91},{"id":40649615,"name":"Run to (and past) the office","workout_type":null,"trainer":0,"start_date_local":"2013-02-11T22:40:32-08:00","moving_time":2868,"elapsed_time":3550,"distance":12192,"speed":15303,"elev_gain":49},{"id":40761466,"name":"Oh hey, it's Croz!","workout_type":null,"trainer":0,"start_date_local":"2013-02-12T22:45:53-08:00","moving_time":3321,"elapsed_time":3530,"distance":12914,"speed":13998,"elev_gain":102},{"id":40862937,"name":"Niner Miler","workout_type":null,"trainer":0,"start_date_local":"2013-02-13T22:35:53-08:00","moving_time":3496,"elapsed_time":3653,"distance":14484,"speed":14915,"elev_gain":51},{"id":41325890,"name":"Saturday morning slog.","workout_type":null,"trainer":0,"start_date_local":"2013-02-15T23:38:30-08:00","moving_time":3839,"elapsed_time":4142,"distance":15249,"speed":14300,"elev_gain":102},{"id":41326001,"name":"Twinning with Varner","workout_type":null,"trainer":0,"start_date_local":"2013-02-17T03:05:51-08:00","moving_time":3983,"elapsed_time":4098,"distance":13104,"speed":11844,"elev_gain":442}]},"moving_time":20675,"elapsed_time":22404,"distance":80818,"speed":14072,"elev_gain":837},{"interval":"2013y08w","entry":{"activities":[{"id":41518680,"name":"Escape from Doc Review","workout_type":null,"trainer":0,"start_date_local":"2013-02-18T22:46:19-08:00","moving_time":2832,"elapsed_time":2923,"distance":11335,"speed":14409,"elev_gain":100},{"id":41632726,"name":"Gunnin' 4 that # 1 spot","workout_type":null,"trainer":0,"start_date_local":"2013-02-19T22:47:26-08:00","moving_time":3491,"elapsed_time":3623,"distance":14034,"speed":14472,"elev_gain":102},{"id":41810523,"name":"Night Running. Just Running. At night...","workout_type":null,"trainer":0,"start_date_local":"2013-02-21T12:05:50-08:00","moving_time":2217,"elapsed_time":2370,"distance":8601,"speed":13966,"elev_gain":42},{"id":41838258,"name":"TGIFF","workout_type":null,"trainer":0,"start_date_local":"2013-02-21T22:56:59-08:00","moving_time":2406,"elapsed_time":2488,"distance":9656,"speed":14448,"elev_gain":50},{"id":42122243,"name":"\"Heyyyyyyyy\"","workout_type":null,"trainer":0,"start_date_local":"2013-02-24T00:51:43-08:00","moving_time":5866,"elapsed_time":6517,"distance":23362,"speed":14337,"elev_gain":176}]},"moving_time":16812,"elapsed_time":17921,"distance":66988,"speed":14344,"elev_gain":470},{"interval":"2013y09w","entry":{"activities":[{"id":42228187,"name":"Monday?","workout_type":null,"trainer":0,"start_date_local":"2013-02-24T22:52:57-08:00","moving_time":2526,"elapsed_time":2683,"distance":9700,"speed":13825,"elev_gain":49},{"id":42334874,"name":"Mistaken for Crosby (yet again)","workout_type":null,"trainer":0,"start_date_local":"2013-02-25T22:58:16-08:00","moving_time":2846,"elapsed_time":2863,"distance":11304,"speed":14298,"elev_gain":92},{"id":42445509,"name":"Doc Review Purgatory","workout_type":null,"trainer":0,"start_date_local":"2013-02-26T23:01:11-08:00","moving_time":2467,"elapsed_time":2589,"distance":9792,"speed":14289,"elev_gain":92},{"id":42559414,"name":"ATAT's Through the Fog","workout_type":null,"trainer":0,"start_date_local":"2013-02-27T23:00:48-08:00","moving_time":2725,"elapsed_time":2798,"distance":11267,"speed":14885,"elev_gain":50},{"id":42671250,"name":"Friday (with a real weekend afterwards!)","workout_type":null,"trainer":0,"start_date_local":"2013-02-28T23:02:59-08:00","moving_time":2513,"elapsed_time":2670,"distance":9696,"speed":13890,"elev_gain":101},{"id":43015911,"name":"Quick Saturday Jaunt (Ryan Kelly for President!)","workout_type":null,"trainer":0,"start_date_local":"2013-03-02T06:20:33-08:00","moving_time":3728,"elapsed_time":3924,"distance":15491,"speed":14959,"elev_gain":95},{"id":43016615,"name":"Running through many escapees from Alcatraz","workout_type":null,"trainer":0,"start_date_local":"2013-03-03T02:28:12-08:00","moving_time":5649,"elapsed_time":5979,"distance":22718,"speed":14477,"elev_gain":177}]},"moving_time":22454,"elapsed_time":23506,"distance":89968,"speed":14424,"elev_gain":656},{"interval":"2013y10w","entry":{"activities":[{"id":43122392,"name":"Monday Funday","workout_type":null,"trainer":0,"start_date_local":"2013-03-03T22:55:46-08:00","moving_time":2541,"elapsed_time":2685,"distance":9743,"speed":13804,"elev_gain":50},{"id":43251244,"name":"Movin' on Up","workout_type":null,"trainer":0,"start_date_local":"2013-03-04T22:40:20-08:00","moving_time":3649,"elapsed_time":3813,"distance":14546,"speed":14351,"elev_gain":105},{"id":43496242,"name":"L Glute Hurts","workout_type":null,"trainer":0,"start_date_local":"2013-03-06T22:37:33-08:00","moving_time":3889,"elapsed_time":4234,"distance":15436,"speed":14289,"elev_gain":101},{"id":43602257,"name":"FRIDAY!","workout_type":null,"trainer":0,"start_date_local":"2013-03-07T22:44:45-08:00","moving_time":2909,"elapsed_time":2942,"distance":11442,"speed":14160,"elev_gain":103},{"id":43763249,"name":"Put firmly in my place...","workout_type":null,"trainer":0,"start_date_local":"2013-03-09T02:18:39-08:00","moving_time":4009,"elapsed_time":4526,"distance":17383,"speed":15610,"elev_gain":92},{"id":43908624,"name":"Ugh.","workout_type":null,"trainer":0,"start_date_local":"2013-03-10T03:17:38-07:00","moving_time":5965,"elapsed_time":6453,"distance":23118,"speed":13952,"elev_gain":167}]},"moving_time":22962,"elapsed_time":24653,"distance":91668,"speed":14372,"elev_gain":618},{"interval":"2013y11w","entry":{"activities":[{"id":44015425,"name":"Stupid F***ing Farmers...","workout_type":null,"trainer":0,"start_date_local":"2013-03-10T23:45:27-07:00","moving_time":3514,"elapsed_time":3644,"distance":12887,"speed":13203,"elev_gain":92},{"id":44125641,"name":"Hopefully getting buckets tonight...","workout_type":null,"trainer":0,"start_date_local":"2013-03-11T23:41:34-07:00","moving_time":3014,"elapsed_time":3127,"distance":11318,"speed":13519,"elev_gain":92},{"id":44252950,"name":"(Buzz, your girlfriend) Woof.","workout_type":null,"trainer":0,"start_date_local":"2013-03-13T00:01:00-07:00","moving_time":2587,"elapsed_time":2825,"distance":9733,"speed":13545,"elev_gain":101},{"id":44497088,"name":"New Frees - Bad?","workout_type":null,"trainer":0,"start_date_local":"2013-03-15T00:04:46-07:00","moving_time":2565,"elapsed_time":2875,"distance":9815,"speed":13775,"elev_gain":103},{"id":44664878,"name":"First workout in months. Woof.","workout_type":null,"trainer":0,"start_date_local":"2013-03-16T04:24:12-07:00","moving_time":3683,"elapsed_time":4052,"distance":15537,"speed":15187,"elev_gain":107},{"id":44807254,"name":"Suck on these Emerald Nuts","workout_type":null,"trainer":0,"start_date_local":"2013-03-17T02:03:20-07:00","moving_time":6677,"elapsed_time":7951,"distance":26638,"speed":14362,"elev_gain":295}]},"moving_time":22040,"elapsed_time":24474,"distance":85928,"speed":14035,"elev_gain":790},{"interval":"2013y12w","entry":{"activities":[{"id":44922974,"name":"Mondays, Case of the","workout_type":null,"trainer":0,"start_date_local":"2013-03-17T23:37:25-07:00","moving_time":3418,"elapsed_time":3703,"distance":13347,"speed":14058,"elev_gain":100},{"id":45042542,"name":"F A R to the L E K","workout_type":null,"trainer":0,"start_date_local":"2013-03-18T23:41:43-07:00","moving_time":3697,"elapsed_time":3993,"distance":15485,"speed":15079,"elev_gain":92},{"id":45167787,"name":"Hump Day","workout_type":null,"trainer":0,"start_date_local":"2013-03-19T23:41:08-07:00","moving_time":3360,"elapsed_time":3550,"distance":12940,"speed":13864,"elev_gain":91},{"id":45767377,"name":"03/21/2013 San Francisco, CA","workout_type":null,"trainer":0,"start_date_local":"2013-03-20T23:58:16-07:00","moving_time":289,"elapsed_time":289,"distance":1008,"speed":12568,"elev_gain":0},{"id":45767381,"name":"Almost got hit by a trolley!","workout_type":null,"trainer":0,"start_date_local":"2013-03-22T12:06:13-07:00","moving_time":3802,"elapsed_time":3930,"distance":15338,"speed":14523,"elev_gain":101},{"id":45767379,"name":"Saturday lame attempt at at tempo","workout_type":null,"trainer":0,"start_date_local":"2013-03-23T07:11:21-07:00","moving_time":3358,"elapsed_time":3708,"distance":14237,"speed":15263,"elev_gain":88},{"id":45767382,"name":"Long run with Anaconda","workout_type":null,"trainer":0,"start_date_local":"2013-03-24T04:40:50-07:00","moving_time":6155,"elapsed_time":6807,"distance":24682,"speed":14436,"elev_gain":242}]},"moving_time":24079,"elapsed_time":25980,"distance":97037,"speed":14508,"elev_gain":714},{"interval":"2013y13w","entry":{"activities":[{"id":45801498,"name":"Ruh roh, getting sick?","workout_type":null,"trainer":0,"start_date_local":"2013-03-24T23:56:51-07:00","moving_time":2953,"elapsed_time":3049,"distance":11420,"speed":13923,"elev_gain":100}]},"moving_time":2953,"elapsed_time":3049,"distance":11420,"speed":13922,"elev_gain":100},{"interval":"2013y14w","entry":{"activities":[{"id":49975085,"name":"04/06/2013 San Francisco, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-06T03:02:47-07:00","moving_time":3282,"elapsed_time":3487,"distance":13063,"speed":14329,"elev_gain":102},{"id":49975082,"name":"04/07/2013 San Francisco, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-07T05:04:01-07:00","moving_time":5289,"elapsed_time":5673,"distance":21694,"speed":14766,"elev_gain":176}]},"moving_time":8571,"elapsed_time":9160,"distance":34757,"speed":14599,"elev_gain":278},{"interval":"2013y15w","entry":{"activities":[{"id":49975078,"name":"04/13/2013 San Francisco, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-13T03:12:29-07:00","moving_time":3809,"elapsed_time":3961,"distance":15314,"speed":14474,"elev_gain":101}]},"moving_time":3809,"elapsed_time":3961,"distance":15314,"speed":14474,"elev_gain":101},{"interval":"2013y16w","entry":{"activities":[{"id":49975064,"name":"04/20/2013 San Francisco, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-20T03:43:05-07:00","moving_time":3716,"elapsed_time":3856,"distance":15722,"speed":15231,"elev_gain":95},{"id":49975066,"name":"04/21/2013 San Francisco, CA","workout_type":null,"trainer":0,"start_date_local":"2013-04-21T03:42:24-07:00","moving_time":6115,"elapsed_time":6336,"distance":24172,"speed":14230,"elev_gain":171}]},"moving_time":9831,"elapsed_time":10192,"distance":39894,"speed":14609,"elev_gain":266},{"interval":"2013y17w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y18w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y19w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y20w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y21w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y22w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y23w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y24w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y25w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y26w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y27w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y28w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y29w","entry":{"activities":[{"id":75742003,"name":"Longest run in a while","workout_type":2,"trainer":0,"start_date_local":"2013-07-21T04:30:02-07:00","moving_time":7374,"elapsed_time":8186,"distance":29219,"speed":14265,"elev_gain":247}]},"moving_time":7374,"elapsed_time":8186,"distance":29219,"speed":14265,"elev_gain":247},{"interval":"2013y30w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y31w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y32w","entry":{"activities":[]},"moving_time":0,"elapsed_time":0,"distance":0,"speed":0,"elev_gain":0},{"interval":"2013y33w","entry":{"activities":[{"id":75741990,"name":"Excellent power to weight ratio...","workout_type":0,"trainer":0,"start_date_local":"2013-08-17T05:07:57-07:00","moving_time":4477,"elapsed_time":7466,"distance":22674,"speed":18233,"elev_gain":245},{"id":75741988,"name":"Solo Sunday Slog","workout_type":2,"trainer":0,"start_date_local":"2013-08-18T05:22:34-07:00","moving_time":5692,"elapsed_time":6646,"distance":24366,"speed":15410,"elev_gain":310}]},"moving_time":10169,"elapsed_time":14112,"distance":47040,"speed":16653,"elev_gain":555},{"interval":"2013y34w","entry":{"activities":[{"id":77534954,"name":"08/25/2013 San Francisco, CA","workout_type":null,"trainer":0,"start_date_local":"2013-08-25T05:06:27-07:00","moving_time":5883,"elapsed_time":6486,"distance":23561,"speed":14418,"elev_gain":260}]},"moving_time":5883,"elapsed_time":6486,"distance":23561,"speed":14418,"elev_gain":260},{"interval":"2013y35w","entry":{"activities":[{"id":79255076,"name":"08/31/2013 San Francisco, CA","workout_type":0,"trainer":0,"start_date_local":"2013-08-31T05:36:35-07:00","moving_time":4227,"elapsed_time":4921,"distance":17156,"speed":14611,"elev_gain":105},{"id":79255086,"name":"Ventura Marathon Crash Course","workout_type":2,"trainer":0,"start_date_local":"2013-09-01T01:27:56-07:00","moving_time":7521,"elapsed_time":8134,"distance":30981,"speed":14829,"elev_gain":263}]},"moving_time":11748,"elapsed_time":13055,"distance":48137,"speed":14751,"elev_gain":368},{"interval":"2013y36w","entry":{"activities":[{"id":79720701,"name":"09/02/2013 San Francisco, CA","workout_type":0,"trainer":0,"start_date_local":"2013-09-02T04:12:59-07:00","moving_time":3473,"elapsed_time":3756,"distance":14668,"speed":15205,"elev_gain":110},{"id":79720696,"name":"Bingo was his name-o!","workout_type":0,"trainer":0,"start_date_local":"2013-09-03T00:06:26-07:00","moving_time":3374,"elapsed_time":3499,"distance":12923,"speed":13789,"elev_gain":109},{"id":81174178,"name":"09/04/2013 San Francisco, CA","workout_type":0,"trainer":0,"start_date_local":"2013-09-03T23:51:58-07:00","moving_time":2587,"elapsed_time":2813,"distance":9691,"speed":13485,"elev_gain":99},{"id":81174177,"name":"09/05/2013 San Francisco, CA","workout_type":0,"trainer":0,"start_date_local":"2013-09-05T00:19:57-07:00","moving_time":4639,"elapsed_time":188737,"distance":18280,"speed":14186,"elev_gain":103},{"id":81174176,"name":"09/08/2013 Ventura, CA","workout_type":0,"trainer":0,"start_date_local":"2013-09-07T23:59:06-07:00","moving_time":10033,"elapsed_time":10929,"distance":42473,"speed":15240,"elev_gain":0}]},"moving_time":24106,"elapsed_time":209734,"distance":98035,"speed":14641,"elev_gain":421},{"interval":"2013y37w","entry":{"activities":[{"id":82723860,"name":"09/14/2013 San Francisco, CA","workout_type":0,"trainer":0,"start_date_local":"2013-09-14T04:56:37-07:00","moving_time":4076,"elapsed_time":4598,"distance":15482,"speed":13674,"elev_gain":99},{"id":82723857,"name":"Bypassed Bonk Town and Went Right to Bonk City","workout_type":2,"trainer":0,"start_date_local":"2013-09-15T04:57:06-07:00","moving_time":6805,"elapsed_time":8112,"distance":26056,"speed":13784,"elev_gain":242}]},"moving_time":10881,"elapsed_time":12710,"distance":41538,"speed":13743,"elev_gain":341},{"interval":"2013y38w","entry":{"activities":[{"id":83037525,"name":"Centro Sighting","workout_type":0,"trainer":0,"start_date_local":"2013-09-17T00:09:15-07:00","moving_time":3698,"elapsed_time":3976,"distance":14703,"speed":14314,"elev_gain":103}]},"moving_time":3698,"elapsed_time":3976,"distance":14703,"speed":14313,"elev_gain":103}]
var Ink = (typeof Ink === 'undefined') ? {} : Ink;
Ink.Tooltip = function(options){
this.$ = window.jQuery || window.$;
this.isMobile = ('ontouchstart' in window);
this.positions = {
remote : function(left, top){
return {
left : (left + this.offsetX),
top : (top + this.offsetY)
};
},
topLeft : function(){
var offset = (this.track === true) ? this.origin : this.$activeTarget.offset();
offset.left = (offset.left + this.offsetX);
offset.top = (offset.top - this.$el.outerHeight() + this.offsetY);
return offset;
},
topRight : function(){
var offset = (this.track === true) ? this.origin : this.$activeTarget.offset();
offset.left = (offset.left + this.offsetX + this.$activeTarget.outerWidth());
offset.top = (offset.top - this.$el.outerHeight() + this.offsetY);
return offset;
},
bottomLeft : function(){
var offset = (this.track === true) ? this.origin : this.$activeTarget.offset();
offset.left = (offset.left + this.offsetX);
offset.top = (offset.top + this.offsetY + this.$activeTarget.outerHeight());
return offset;
},
bottomRight : function(){
var offset = (this.track === true) ? this.origin : this.$activeTarget.offset();
offset.left = (offset.left + this.offsetX + this.$activeTarget.outerWidth());
offset.top = (offset.top + this.offsetY + this.$activeTarget.outerHeight());
return offset;
},
belowCenter: function(e){
var offset = (this.track === true) ? this.origin : this.$activeTarget.offset();
offset.left = (offset.left + this.$activeTarget.outerWidth() / 2) + this.offsetX - (this.$el.outerWidth() / 2);
offset.top = (offset.top + this.offsetY + this.$activeTarget.outerHeight());
return offset;
},
aboveCenter: function(e){
var offset = (this.track === true) ? this.origin : this.$activeTarget.offset();
offset.left = (offset.left + this.$activeTarget.outerWidth() / 2) + this.offsetX - (this.$el.outerWidth() / 2);
offset.top = (offset.top - this.$el.outerHeight() + this.offsetY);
return offset;
}
};
var defaults = {
target : null,
id : 'ink-tooltip',
className : 'ink-tooltip',
// timer for the delay. dont override
exitTimer : null,
// timer for the delay. dont override
timer : null,
// the tooltip element
$el : null,
// unique identifer token for event binding and dom queries
token : Math.round(Math.random() * 100000),
// the fadein delay
delay : 0,
// the offsets of the tooltip when it appears
offsetX : 0,
offsetY : 0,
// duh, transparency
opacity : 0.9,
// method for determining what to populate the tooltip with
getContent : this.getContent,
// should the tooltip track your mouse?
track : false,
// do you want the tooltip to fade in and fade out?
fade : false,
// alignment options: topLeft, topRight, bottomLeft, bottomRight
align : 'topLeft',
// the point of origin for the tooltip position, dont override
origin : { top: 0, left: 0 },
// callback for after the tooltip is shown
onShow : function(e){ return true; },
// callback for after the tooltip is hidden
onHide : function(e){ return true; },
remote : false
};
if(arguments.length > 0){
// set positioning to custom method if align option is a function
if(_.isFunction(options.align) == true){
this.positions.custom = options.align;
options.align = 'custom';
}
this.$.extend(defaults, options);
}
this.$.extend(this, defaults);
this.id = this.id += '-'+this.token;
// set positioning to remote if there is no target
if(this.target === null){
this.remote = true;
this.align = 'remote';
}else{
this.$target = this.$(this.target);
}
this.init();
};
Ink.Tooltip.prototype = {
init : function(){
// attach the tooltip to the page witn a unique identifier
var $el = this.$('<div style="display:none;" id="'+this.id+'" class="'+this.className+'"></div>');
this.$(document.body).append($el);
this.$el = this.$('#'+this.id);
// if this is a remote controlled tooltip, do not bind mouse events
if(this.remote === false){
if(this.isMobile === true){
this.$target.on('touchstart', this.$.proxy(this.handleOver, this));
this.$target.on('touchend', this.$.proxy(this.delayedOut, this));
}else{
this.$target.on('mouseenter', this.$.proxy(this.handleOver, this));
this.$target.on('mouseleave', this.$.proxy(this.handleOut, this));
}
if(this.track === true){
this.proxiedUpdateMousePosition = this.$.proxy(this.updateMousePosition, this);
}
}
return this;
},
// show the tooltip
show: function(e){
if(arguments.length > 0 && this.remote === false){
var position;
this.content(this.getContent(e));
if(this.track === true){
// this.proxiedUpdateMousePosition(e);
this.startTrackingPosition();
}
position = this.positions[this.align].call(this);
this.position({ left: position.left, top: position.top });
}
if(this.fade === true){
this.$el.fadeIn();
}else{
this.$el.show();
}
this.onShow.call(this,e);
return this;
},
// hide the tooltip
hide: function(e){
if(this.fade === true){
this.$el.fadeOut();
}else{
this.$el.hide();
}
if(this.track === true){
this.stopTrackingPosition();
}
this.onHide.call(this,e);
return this;
},
handleOver: function(e){
clearTimeout(this.timer);
clearTimeout(this.exitTimer);
this.$activeTarget = this.$(e.target);
if(this.delay !== 0){
this.timer = setTimeout(this.$.proxy(this.show, this, e), this.delay);
}else{
this.show(e);
}
},
handleOut: function(e){
clearTimeout(this.timer);
clearTimeout(this.exitTimer);
this.hide(e);
this.$activeTarget = null;
},
// get or set the position
position: function(){
if(arguments.length > 0){
this.$el.css({ left: arguments[0].left+'px', top: arguments[0].top+'px' });
}else{
return this.$el.position();
}
return this;
},
getContent: function(e){
return this.$(this.$activeTarget).data('ttc');
},
// get or set the tooltip content
content: function(){
if(arguments.length > 0){
this.$el.html(arguments[0]);
}else{
return this.$el.html();
}
return this;
},
// for touch end timing
delayedOut: function(e){
clearTimeout(this.exitTimer);
this.exitTimer = setTimeout(this.$.proxy(this.handleOut, this, e), this.delay);
},
// if tracking is enabled, will change the origin position to the mouse location
updateMousePosition: function(e){
if('pageY' in e){
var position;
this.origin.top = e.pageY;
this.origin.left = e.pageX;
position = this.positions[this.align].call(this);
this.position({ left: position.left, top: position.top });
}
},
// if tracking is enabled, will update the origin as the mouse moves over the element
startTrackingPosition: function(){
this.$('body').bind('mousemove', this.proxiedUpdateMousePosition);
},
// stop monitoring the position of the mouse
stopTrackingPosition: function(){
this.$('body').unbind('mousemove', this.proxiedUpdateMousePosition);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment