diff options
Diffstat (limited to 'site/app/webroot/js/stats/plots.js')
-rwxr-xr-x | site/app/webroot/js/stats/plots.js | 195 |
1 files changed, 186 insertions, 9 deletions
diff --git a/site/app/webroot/js/stats/plots.js b/site/app/webroot/js/stats/plots.js index 464b2c3..48f792e 100755 --- a/site/app/webroot/js/stats/plots.js +++ b/site/app/webroot/js/stats/plots.js @@ -7,11 +7,7 @@ var Plots = { determinePlot: function() { var selected = plotSelection.dropdowns['plot-selector'].selectedItem.value; - - // HACK: The group-by selector doesn't exist when the plot-selector is first - // instantiated, but this method is called at that point. - var group_by = (!plotSelection.dropdowns['group-by-selector']) ? null : - plotSelection.dropdowns['group-by-selector'].selectedItem.value; + var group_by = plotSelection.getGroupByValue(); // Remove current plot selections plotSelection.removeAll(); @@ -156,11 +152,13 @@ var Plots = { var plotType = plotSelection.dropdowns['plot-selector'].selectedItem.value; if (plotType == 'summary') { + $('#weeks-legend').hide(); $('#summary-legend').show(); $('#summary-options').show(); $('#group-by-selector').hide(); } else { + $('#weeks-legend').hide(); $('#summary-legend').hide(); $('#summary-options').hide(); $('#group-by-selector').show(); @@ -231,9 +229,22 @@ var Plots = { // If there's a value for the group-by selector, add it as a // parameter to the CSV URL to invoke it server-side. - var group_by = plotSelection.dropdowns['group-by-selector'].selectedItem.value; + var group_by = plotSelection.getGroupByValue(); + + if ('week_over_week' == group_by) { + if ('updatepings' == type || 'downloads' == type) { + $('#weeks-legend').show(); + return this.plotWeekOverWeek(); + } else { + // HACK: Until I can figure out how to disable the Compare + // by: Week option for views not supported for it + group_by = 'week'; + } + } + + $('#weeks-legend').hide(); if (group_by) Plots.currentCSV += '?group_by=' + group_by; - + this.dataSources = { 'count': new Timeplot.DefaultEventSource(), 'events-firefox': new Timeplot.DefaultEventSource(), @@ -304,7 +315,7 @@ var Plots = { this.plot(); }, - + plot: function() { var timeGeometry = new Timeplot.DefaultTimeGeometry(this.timeGeometry); var valueGeometry = new Timeplot.DefaultValueGeometry(this.valueGeometry); @@ -328,6 +339,172 @@ var Plots = { Plots.timeplot.loadXML(statsURL + 'xml/events/firefox', this.dataSources['events-firefox']); Plots.timeplot.loadXML(statsURL + 'xml/events/addon/' + addonID, this.dataSources['events-addon']); }, + + /** + * Construct a plot consisting of 2 different weeks' data overlaid on + * the same graph. + */ + plotWeekOverWeek: function() { + + var type = plotSelection.dropdowns['plot-selector'].selectedItem.value; + Plots.currentCSV = statsURL + 'csv/' + addonID + '/' + type; + + this.dataSources = { + 'count': new Timeplot.DefaultEventSource(), + }; + + PlotsTables.addListeners('week_over_week', this.dataSources); + + var date_parser = Timeline.NativeDateUnit.getParser('iso8601'); + + // Collect Mondays from the set of available dates. + var available_dates = plotSelection + .summary[ (type=='downloads') ? 'downloads' : 'updatepings' ] + .availableDates; + var dates = []; + var DAY_MONDAY = 1; + for (idx in available_dates) { + // The available dates data is a little weird - it's an object + // with numerical properties, instead of an array. + if (available_dates.hasOwnProperty(idx)) { + var date = date_parser(available_dates[idx]); + if (date.getDay() == DAY_MONDAY) + dates.push(available_dates[idx]); + } + } + + // Set up empty ranges set. + var ranges = { + week1: { min: '', max: '' }, + week2: { min: '', max: '' } + }; + + var WEEK = ( 1000 * 60 * 60 * 24 * 7 ); + + if ( $('#weeks-legend .template').length ) { + + // The date selection dropdowns still contain unpopulated + // templates, so set up the defaults and populate the dropdowns + + ranges['week2']['min'] = date_parser(dates[dates.length - 1]); + ranges['week2']['max'] = new Date(ranges['week2']['min'].getTime() + WEEK); + ranges['week1']['min'] = date_parser(dates[dates.length - 2]); + ranges['week1']['max'] = new Date(ranges['week1']['min'].getTime() + WEEK); + + var weeks = ['week1', 'week2']; + for (var i=0, week; week=weeks[i]; i++) { + + // Convert the selection template into a concrete element + var tmpl = $('#'+week+'-selection select.template'); + if (!tmpl.length) continue; + tmpl.remove().removeClass('template'); + + // Convert the current min date to string for comparison. + var min_str = ranges[week]['min'].strftime('%Y-%m-%d'); + + // Now populate the selection element with options cloned + // and populated from available dates. + var t_opt = tmpl.find('option').remove(); + for (var j=0,date; date=dates[j]; j++) { + var opt = t_opt.clone(); + + var dp = date.split('-'); + opt.text([dp[1], dp[2], dp[0]].join('/')) + .attr('value', date) + .appendTo(tmpl); + + if (date == min_str) + opt.attr('selected', 'selected'); + } + + // Finally inject the populated selector into the DOM and + // wire up an onChange handler to reload the plot. + tmpl.appendTo('#'+week+'-selection') + .change(function() { Plots.determinePlot() }); + } + + } else { + + // The date selection dropdowns are populated, so set ranges + // from the selected values. + + var weeks = ['week1', 'week2']; + for (var i=0, week; week=weeks[i]; i++) { + var opt = $('#'+week+'-selection select')[0]; + var date = opt.options[opt.selectedIndex].value; + ranges[week]['min'] = date_parser(date); + ranges[week]['max'] = new Date(ranges[week]['min'].getTime() + WEEK); + } + + } + + // Assemble the time geometries from the selected time ranges. + this.timeGeometries = { + 'week1': { + 'min': ranges['week1']['min'], + 'max': ranges['week1']['max'], + 'gridColor': '#CC6666', + 'axisLabelsPlacement': 'bottom' + }, + 'week2': { + 'min': ranges['week2']['min'], + 'max': ranges['week2']['max'], + 'gridColor': '#6666CC', + 'axisLabelsPlacement': 'top' + } + }; + + // Both time ranges share the same value geometry + this.valueGeometry = { + 'gridColor': '#000000', + 'axisLabelsPlacement': 'left', + 'min': 0 + }; + + // Construct the plot info structures for each of the overlaid sets. + Plots.newTimeplot(); + Plots.timeplot = Timeplot.create(document.getElementById(Plots.timeplot_id), [ + Timeplot.createPlotInfo({ + 'id': 'week1-plot', + 'dataSource': + new Timeplot.ColumnSource(this.dataSources['count'], 1), + 'timeGeometry': + new Timeplot.DefaultTimeGeometry(this.timeGeometries['week1']), + 'valueGeometry': + new Timeplot.DefaultValueGeometry(this.valueGeometry), + 'showValues': true, + 'dotColor': '#CC6666', + 'dotRadius': 3.0, + 'lineColor': '#CC6666', + 'lineWidth': 3.0, + 'fillColor': false + }), + Timeplot.createPlotInfo({ + 'id': 'week2-plot', + 'dataSource': + new Timeplot.ColumnSource(this.dataSources['count'], 1), + 'timeGeometry': + new Timeplot.DefaultTimeGeometry(this.timeGeometries['week2']), + 'valueGeometry': + new Timeplot.DefaultValueGeometry(this.valueGeometry), + 'showValues': true, + 'dotColor': '#6666CC', + 'dotRadius': 3.0, + 'lineColor': '#6666CC', + 'lineWidth': 3.0, + 'fillColor': false + }) + ]); + + // Finally, queue up a load for the plot data. + Plots.timeplot.loadText( + Plots.currentCSV, + ",", + this.dataSources['count'], + parseFields + ); + + }, addPlot: function(plotName, column, color) { if (plotName in this.plotInfo) @@ -397,4 +574,4 @@ function parseFields(data) { } return data; -}
\ No newline at end of file +} |