From f4e65ea23181bb83e077e900da24bf4e03936b96 Mon Sep 17 00:00:00 2001 From: almossawi Date: Sun, 19 Oct 2014 14:33:24 -0700 Subject: [PATCH] Fix issue #137 Committing updated metrics-graphics.js and metrics-graphics.min.js files, since those were regenerated to fix issues that we we discovered when deploying v0.5.1 to our set of internal dashboards. --- css/metrics-graphics-demo.css | 4 ++ data/missing-y.json | 15 +++++ dev.html | 1 + js/main.js | 34 +++++++++- js/metrics-graphics.js | 117 ++++++++++++++++++++-------------- js/metrics-graphics.min.js | 36 ++++------- src/common/markers.js | 4 +- src/common/moz_chart.js | 1 + src/misc/process.js | 57 ++++++++++++++++- 9 files changed, 196 insertions(+), 73 deletions(-) create mode 100644 data/missing-y.json diff --git a/css/metrics-graphics-demo.css b/css/metrics-graphics-demo.css index 149ed03966..338f7e0524 100644 --- a/css/metrics-graphics-demo.css +++ b/css/metrics-graphics-demo.css @@ -6,6 +6,10 @@ a.active { padding: 5px; } +.chart_title { + margin-left: 30px; +} + #footer { font-size: 11px; padding: 40px; diff --git a/data/missing-y.json b/data/missing-y.json new file mode 100644 index 0000000000..643dc7ad84 --- /dev/null +++ b/data/missing-y.json @@ -0,0 +1,15 @@ + + [ + { + "date": "2014-01-01", + "value": 500 + }, + { + "date": "2014-01-19", + "value": 2000 + }, + { + "date": "2014-04-30", + "value": 3000 + } + ] diff --git a/dev.html b/dev.html index 56e327e824..4d9e70e39f 100644 --- a/dev.html +++ b/dev.html @@ -91,6 +91,7 @@
+
diff --git a/js/main.js b/js/main.js index 325d851c7e..0699141579 100644 --- a/js/main.js +++ b/js/main.js @@ -26,6 +26,38 @@ $(document).ready(function() { assignEventListeners(); + + d3.json('data/missing-y.json', function(data) { + var fff = d3.time.format('%Y-%m-%d'); + for(var i=0;imissing_y_is_zero: true, missing values for a time-series will be interpreted as zeros. In this example, we've override the rollover callback to show 'no date' for missing observations.", + data: data, + interpolate: 'basic', + missing_y_is_zero: true, + width: torso.width, + height: torso.height, + right: torso.right, + target: '#missing-y', + x_accessor: 'date', + y_accessor: 'value', + rollover_callback: function(d, i) { + var df = d3.time.format('%b %d, %Y'); + var date = df(d['date']); + var y_val = (d.value == 0) ? 'no data' : d.value; + + $('#missing-y svg .active_datapoint') + .html(date + ' ' + y_val); + } + }) + }); + //generate a Bates distribution of 10 random variables var values = d3.range(10000).map(d3.random.bates(10)); var x = d3.scale.linear() @@ -184,7 +216,7 @@ $(document).ready(function() { //add a multi-line chart moz_chart({ title:"Multi-line Chart", - description: "This line chart contains multiple lines. We're still working out the style details.", + description: "This line chart contains multiple lines.", data: data, width: torso.width, height: torso.height, diff --git a/js/metrics-graphics.js b/js/metrics-graphics.js index d119d54d85..18c55d0f99 100644 --- a/js/metrics-graphics.js +++ b/js/metrics-graphics.js @@ -3,12 +3,13 @@ var charts = {}; var globals = {}; globals.link = false; -globals.version = "0.5"; +globals.version = "0.6"; function moz_chart() { var moz = {}; moz.defaults = {}; moz.defaults.all = { + missing_y_is_zero: true, // if true, missing values of y will be treated as zeros legend: '' , // an array identifying the labels for a chart's lines legend_target: '', // if set, the specified element is populated with a legend error: '', // if set, a graph will show an error icon and log the error to the console @@ -722,7 +723,7 @@ function markers(args) { gm.selectAll('.markers') .data(args.markers.filter(function(d){ return (args.scales.X(d[args.x_accessor]) > args.buffer + args.left) - && (args.scales.X(d[args.x_accessor]) < args.buffer + args.width - args.right); + && (args.scales.X(d[args.x_accessor]) < args.width - args.buffer - args.right); })) .enter() .append('line') @@ -741,7 +742,7 @@ function markers(args) { gm.selectAll('.markers') .data(args.markers.filter(function(d){ return (args.scales.X(d[args.x_accessor]) > args.buffer + args.left) - && (args.scales.X(d[args.x_accessor]) < args.buffer + args.width - args.right); + && (args.scales.X(d[args.x_accessor]) < args.width - args.buffer - args.right); })) .enter() .append('text') @@ -789,23 +790,33 @@ var button_layout = function(target) { this.feature_set = {}; this.public_name = {}; this.sorters = {}; + this.manual = []; + this.manual_map = {}; + this.manual_callback = {}; this.data = function(data) { this._data = data; return this; } + this.manual_button = function(feature, feature_set, callback) { + this.feature_set[feature]=feature_set; + this.manual_map[strip_punctuation(feature)] = feature; + this.manual_callback[feature]=callback;// the default is going to be the first feature. + return this; + } + this.button = function(feature) { var sorter, the_label; if (arguments.length>1) { this.public_name[feature] = arguments[1]; - } + } + if (arguments.length>2) { this.sorters[feature] = arguments[2]; } this.feature_set[feature] = []; - return this; } @@ -816,68 +827,68 @@ var button_layout = function(target) { this.display = function() { var callback = this._callback; + var manual_callback = this.manual_callback; + var manual_map = this.manual_map; + var d,f, features, feat; features = Object.keys(this.feature_set); - // build out this.feature_set with this.data - for (var i=0; i"); + $(this.target).append("
"); + var the_string = ''; + for (var feature in this.feature_set) { features = this.feature_set[feature]; $(this.target + ' div.segments').append( - "
" - + "" - + "" - + "
" - ); - - for (var i=0; i' + // This never changes. + '' + + '' + + '
'); + + for (var i=0;i" - + features[i] + "" + '
  • ' + + features[i] + '
  • ' ); } } - - $('.'+ strip_punctuation(feature) + '-btns .dropdown-menu li a') - .on('click', function() { + + $('.' + strip_punctuation(feature) + '-btns .dropdown-menu li a').on('click', function() { var k = $(this).data('key'); var feature = $(this).data('feature'); - - $('.' + strip_punctuation(feature) + '-btns button.btn span.title') - .html(k); - - callback(feature, k); - + var manual_feature; + $('.' + strip_punctuation(feature) + '-btns button.btn span.title').html(k); + if (!manual_map.hasOwnProperty(feature)) { + callback(feature, k); + } else { + manual_feature = manual_map[feature]; + manual_callback[manual_feature](k); + } + return false; }) } @@ -887,7 +898,6 @@ var button_layout = function(target) { return this } - charts.line = function(args) { this.args = args; @@ -1895,10 +1905,23 @@ function raw_data_transformation(args){ }); } } + return this } -function process_line(args){ +//todo, do it for multi-line too +function process_line(args) { + //are we replacing missing y values with zeros? + console.log(args.time_series); + if(args.missing_y_is_zero && args.chart_type == 'line' && args.time_series) { + //todo get date series from date at args.data[0] to args.data[args.data.length-1] + var first_date = args.data[0]; + var last_date = args.data[args.data.length-1]; + console.log(first_date, last_date); + + //todo + } + return this; } diff --git a/js/metrics-graphics.min.js b/js/metrics-graphics.min.js index b0bb24d84c..b01b6dfdd3 100644 --- a/js/metrics-graphics.min.js +++ b/js/metrics-graphics.min.js @@ -1,4 +1,4 @@ -'use strict';var charts={};var globals={};globals.link=false;globals.version="0.5";function moz_chart(){var moz={};moz.defaults={};moz.defaults.all={legend:'',legend_target:'',error:'',animate_on_load:false,top:40,bottom:30,right:10,left:50,buffer:8,width:350,height:220,small_height_threshold:120,small_width_threshold:160,small_text:false,xax_count:6,xax_tick:5,yax_count:5,yax_tick:5,x_extended_ticks:false,y_extended_ticks:false,y_scale_type:'linear',max_x:null,max_y:null,min_x:null,min_y:null,point_size:2.5,x_accessor:'date',xax_units:'',x_label:'',x_axis:true,y_axis:true,y_accessor:'value',y_label:'',yax_units:'',transition_on_update:true,rollover_callback:null,show_rollover_text:true,show_confidence_band:null,xax_format:function(d){var df=d3.time.format('%b %d');var pf=d3.formatPrefix(d);return(this.x_accessor=='date')?df(d):pf.scale(d)+pf.symbol;},area:true,chart_type:'line',data:[],decimals:2,format:'count',inflator:10/9,linked:false,list:false,baselines:null,markers:null,scalefns:{},scales:{},show_years:true,target:'#viz',interpolate:'cardinal',custom_line_color_map:[],max_data_size:null} +'use strict';var charts={};var globals={};globals.link=false;globals.version="0.6";function moz_chart(){var moz={};moz.defaults={};moz.defaults.all={missing_y_is_zero:true,legend:'',legend_target:'',error:'',animate_on_load:false,top:40,bottom:30,right:10,left:50,buffer:8,width:350,height:220,small_height_threshold:120,small_width_threshold:160,small_text:false,xax_count:6,xax_tick:5,yax_count:5,yax_tick:5,x_extended_ticks:false,y_extended_ticks:false,y_scale_type:'linear',max_x:null,max_y:null,min_x:null,min_y:null,point_size:2.5,x_accessor:'date',xax_units:'',x_label:'',x_axis:true,y_axis:true,y_accessor:'value',y_label:'',yax_units:'',transition_on_update:true,rollover_callback:null,show_rollover_text:true,show_confidence_band:null,xax_format:function(d){var df=d3.time.format('%b %d');var pf=d3.formatPrefix(d);return(this.x_accessor=='date')?df(d):pf.scale(d)+pf.symbol;},area:true,chart_type:'line',data:[],decimals:2,format:'count',inflator:10/9,linked:false,list:false,baselines:null,markers:null,scalefns:{},scales:{},show_years:true,target:'#viz',interpolate:'cardinal',custom_line_color_map:[],max_data_size:null} moz.defaults.point={ls:false,lowess:false} moz.defaults.histogram={rollover_callback:function(d,i){$('#histogram svg .active_datapoint').html('Frequency Count: '+d.y);},binned:false,bins:null,processed_x_accessor:'x',processed_y_accessor:'y',processed_dx_accessor:'dx',bar_margin:1} moz.defaults.bar={y_accessor:'factor',x_accessor:'value',binned:false,padding_percentage:.1,outer_padding_percentage:.1,height:500,top:20} @@ -69,33 +69,24 @@ var lines_to_remove=arrDiff(array_full_series(args.max_data_size),args.custom_li else{var num_of_new=args.data.length;var num_of_existing=$(args.target+' svg .main-line').length;for(var i=num_of_existing;i>num_of_new;i--){$(args.target+' svg .main-line.line'+i+'-color').remove();}}} return this;} function markers(args){var svg=d3.select(args.target+' svg');var gm;var gb;if(args.markers){if($(args.target+' svg .markers').length>0){$(args.target+' svg .markers').remove();} -gm=svg.append('g').attr('class','markers');gm.selectAll('.markers').data(args.markers.filter(function(d){return(args.scales.X(d[args.x_accessor])>args.buffer+args.left)&&(args.scales.X(d[args.x_accessor])args.buffer+args.left)&&(args.scales.X(d[args.x_accessor])args.buffer+args.left)&&(args.scales.X(d[args.x_accessor])args.buffer+args.left)&&(args.scales.X(d[args.x_accessor])1){this.public_name[feature]=arguments[1];} if(arguments.length>2){this.sorters[feature]=arguments[2];} this.feature_set[feature]=[];return this;} this.callback=function(callback){this._callback=callback;return this;} -this.display=function(){var callback=this._callback;var d,f,features,feat;features=Object.keys(this.feature_set);for(var i=0;i");for(var feature in this.feature_set){features=this.feature_set[feature];$(this.target+' div.segments').append("
    " -+"" -+"" -+"
    ");for(var i=0;i" -+features[i]+"");}} -$('.'+strip_punctuation(feature)+'-btns .dropdown-menu li a').on('click',function(){var k=$(this).data('key');var feature=$(this).data('feature');$('.'+strip_punctuation(feature)+'-btns button.btn span.title').html(k);callback(feature,k);return false;})} +$(this.target).empty();$(this.target).append("
    ");var the_string='';for(var feature in this.feature_set){features=this.feature_set[feature];$(this.target+' div.segments').append('
    '+''+'' ++'
    ');for(var i=0;i' ++features[i]+'');}} +$('.'+strip_punctuation(feature)+'-btns .dropdown-menu li a').on('click',function(){var k=$(this).data('key');var feature=$(this).data('feature');var manual_feature;$('.'+strip_punctuation(feature)+'-btns button.btn span.title').html(k);if(!manual_map.hasOwnProperty(feature)){callback(feature,k);}else{manual_feature=manual_map[feature];manual_callback[manual_feature](k);} +return false;})} return this;} return this} charts.line=function(args){this.args=args;this.init=function(args){raw_data_transformation(args);process_line(args);init(args);x_axis(args);y_axis(args);return this;} @@ -203,7 +194,8 @@ function raw_data_transformation(args){if(!$.isArray(args.data[0])) args.data=[args.data];if($.isArray(args.y_accessor)){args.data=args.data.map(function(_d){return args.y_accessor.map(function(ya){return _d.map(function(di){di=clone(di);di['multiline_y_accessor']=di[ya];return di;})})})[0];args.y_accessor='multiline_y_accessor';} if(args.chart_type=='line'){for(var i=0;i args.buffer + args.left) - && (args.scales.X(d[args.x_accessor]) < args.buffer + args.width - args.right); + && (args.scales.X(d[args.x_accessor]) < args.width - args.buffer - args.right); })) .enter() .append('line') @@ -34,7 +34,7 @@ function markers(args) { gm.selectAll('.markers') .data(args.markers.filter(function(d){ return (args.scales.X(d[args.x_accessor]) > args.buffer + args.left) - && (args.scales.X(d[args.x_accessor]) < args.buffer + args.width - args.right); + && (args.scales.X(d[args.x_accessor]) < args.width - args.buffer - args.right); })) .enter() .append('text') diff --git a/src/common/moz_chart.js b/src/common/moz_chart.js index ef3a09bc34..58b6a608b8 100644 --- a/src/common/moz_chart.js +++ b/src/common/moz_chart.js @@ -9,6 +9,7 @@ function moz_chart() { var moz = {}; moz.defaults = {}; moz.defaults.all = { + missing_y_is_zero: false, // if true, missing values of y will be treated as zeros legend: '' , // an array identifying the labels for a chart's lines legend_target: '', // if set, the specified element is populated with a legend error: '', // if set, a graph will show an error icon and log the error to the console diff --git a/src/misc/process.js b/src/misc/process.js index 948c942e7e..7d06406cfa 100644 --- a/src/misc/process.js +++ b/src/misc/process.js @@ -26,10 +26,65 @@ function raw_data_transformation(args){ }); } } + return this } -function process_line(args){ +function process_line(args) { + //are we replacing missing y values with zeros? + + //do we have a time-series? + var is_time_series = ($.type(args.data[0][0][args.x_accessor]) == 'date') + ? true + : false; + + if(args.missing_y_is_zero && args.chart_type == 'line' && is_time_series) { + for(var i=0;i