1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
MG.globals = {};
MG.deprecations = {
rollover_callback: { replacement: 'mouseover', version: '2.0' },
rollout_callback: { replacement: 'mouseout', version: '2.0' },
x_rollover_format: { replacement: 'x_mouseover', version: '2.10' },
y_rollover_format: { replacement: 'y_mouseover', version: '2.10' },
show_years: { replacement: 'show_secondary_x_label', version: '2.1' },
xax_start_at_min: { replacement: 'axes_not_compact', version: '2.7' },
interpolate_tension: { replacement: 'interpolate', version: '2.10' }
};
MG.globals.link = false;
MG.globals.version = "1.1";
MG.options = { // <name>: [<defaultValue>, <availableType>]
x_axis_type: [null, ['categorical']], // TO BE INTRODUCED IN 2.10
y_axis_type: [null, ['categorical']], // TO BE INTRODUCED IN 2.10
y_padding_percentage: [0.05, 'number'], // for categorical scales
y_outer_padding_percentage: [0.1, 'number'], // for categorical scales
ygroup_padding_percentage: [0.25, 'number'], // for categorical scales
ygroup_outer_padding_percentage: [0, 'number'], // for categorical scales
x_padding_percentage: [0.05, 'number'], // for categorical scales
x_outer_padding_percentage: [0.1, 'number'], // for categorical scales
xgroup_padding_percentage: [0.25, 'number'], // for categorical scales
xgroup_outer_padding_percentage: [0, 'number'], // for categorical scales
ygroup_accessor: [null, 'string'],
xgroup_accessor: [null, 'string'],
y_categorical_show_guides: [false, 'boolean'],
x_categorical_show_guide: [false, 'boolean'],
rotate_x_labels: [0, 'number'],
rotate_y_labels: [0, 'number'],
scales: [{}],
scalefns: [{}],
// Data
data: [[], ['object[]', 'number[]']], // the data object
missing_is_zero: [false, 'boolean'], // assume missing observations are zero
missing_is_hidden: [false, 'boolean'], // show missing observations as missing line segments
missing_is_hidden_accessor: [null, 'string'], // the accessor for identifying observations as missing
utc_time: [false, 'boolean'], // determines whether to use a UTC or local time scale
x_accessor: ['date', 'string'], // the data element that's the x-accessor
x_sort: [true, 'boolean'], // determines whether to sort the x-axis' values
y_accessor: ['value', ['string', 'string[]']], // the data element that's the y-accessor
// Axes
axes_not_compact: [true, 'boolean'], // determines whether to draw compact or non-compact axes
european_clock: [false, 'boolean'], // determines whether to show labels using a 24-hour clock
inflator: [10/9, 'number'], // a multiplier for inflating max_x and max_y
max_x: [null, ['number', Date]], // the maximum x-value
max_y: [null, ['number', Date]], // the maximum y-value
min_x: [null, ['number', Date]], // the minimum x-value
min_y: [null, ['number', Date]], // the minimum y-value
min_y_from_data: [false, 'boolean'], // starts y-axis at data's minimum value
show_year_markers: [false, 'boolean'], // determines whether to show year markers along the x-axis
show_secondary_x_label: [true, 'boolean'], // determines whether to show years along the x-axis
small_text: [false, 'boolean'],
x_extended_ticks: [false, 'boolean'], // determines whether to extend the x-axis ticks across the chart
x_axis: [true, 'boolean'], // determines whether to display the x-axis
x_label: ['', 'string'], // the label to show below the x-axis
xax_count: [6, 'number'], // the number of x-axis ticks
xax_format: [null, 'function'], // a function that formats the x-axis' labels
xax_tick_length: [5, 'number'], // the x-axis' tick length in pixels
xax_units: ['', 'string'], // a prefix symbol to be shown alongside the x-axis' labels
x_scale_type: ['linear', 'log'], // the x-axis scale type
y_axis: [true, 'boolean'], // determines whether to display the y-axis
x_axis_position: ['bottom'], // string
y_axis_position: ['left'], // string
y_extended_ticks: [false, 'boolean'], // determines whether to extend the y-axis ticks across the chart
y_label: ['', 'string'], // the label to show beside the y-axis
y_scale_type: ['linear', ['linear', 'log']], // the y-axis scale type
yax_count: [3, 'number'], // the number of y-axis ticks
yax_format: [null, 'function'], // a function that formats the y-axis' labels
yax_tick_length: [5, 'number'], // the y-axis' tick length in pixels
yax_units: ['', 'string'], // a prefix symbol to be shown alongside the y-axis' labels
yax_units_append: [false, 'boolean'], // determines whether to append rather than prepend units
// GraphicOptions
aggregate_rollover: [false, 'boolean'], // links the lines in a multi-line graphic
animate_on_load: [false, 'boolean'], // determines whether lines are transitioned on first-load
area: [true, ['boolean', 'array']], // determines whether to fill the area below the line
flip_area_under_y_value: [null, 'number'], // Specify a Y baseline number value to flip area under it
baselines: [null, 'object[]'], // horizontal lines that indicate, say, goals.
chart_type: ['line', ['line', 'histogram', 'point', 'bar', 'missing-data']], // '{line, histogram, point, bar, missing-data}'],
color: [null, ['string', 'string[]']],
colors: [null, ['string', 'string[]']],
custom_line_color_map: [[], 'number[]'], // maps an arbitrary set of lines to colors
decimals: [2, 'number'], // the number of decimals to show in a rollover
error: ['', 'string'], // does the graphic have an error that we want to communicate to users
format: ['count', ['count', 'percentage']], // the format of the data object (count or percentage)
full_height: [false, 'boolean'], // sets height to that of the parent, adjusts dimensions on window resize
full_width: [false, 'boolean'], // sets width to that of the parent, adjusts dimensions on window resize
interpolate: [d3.curveCatmullRom.alpha(0), [d3.curveBasisClosed, d3.curveBasisOpen, d3.curveBasis, d3.curveBundle, d3.curveCardinalClosed, d3.curveCardinalOpen, d3.curveCardinal, d3.curveCatmullRomClosed, d3.curveCatmullRomOpen, d3.curveLinearClosed, d3.curveLinear, d3.curveMonotoneX, d3.curveMonotoneY, d3.curveNatural, d3.curveStep, d3.curveStepAfter, d3.curveStepBefore]], // the interpolation function to use for rendering lines
legend: ['', 'string[]'], // an array of literals used to label lines
legend_target: ['', 'string'], // the DOM element to insert the legend in
linked: [false, 'boolean'], // used to link multiple graphics together
linked_format: ['%Y-%m-%d', 'string'], // specifies the format of linked rollovers
list: [false, 'boolean'], // automatically maps the data to x and y accessors
markers: [null, 'object[]'], // vertical lines that indicate, say, milestones
max_data_size: [null, 'number'], // for use with custom_line_color_map
missing_text: [null, 'string'], // The text to display for missing graphics
show_missing_background: [true, 'boolean'], // Displays a background for missing graphics
mousemove_align: ['right', 'string'], // implemented in point.js
x_mouseover: [null, ['string', 'function']],
y_mouseover: [null, ['string', 'function']],
mouseover: [null, 'function'], // custom rollover function
mousemove: [null, 'function'], // custom rollover function
mouseout: [null, 'function'], // custom rollover function
click: [null, 'function'],
point_size: [2.5, 'number'], // the radius of the dots in the scatterplot
active_point_on_lines: [false, 'boolean'], // if set, active dot on lines will be displayed.
active_point_accessor: ['active', 'string'], // data accessor value to determine if a point is active or not
active_point_size: [2, 'number'], // the size of the dot that appears on a line when
points_always_visible: [false, 'boolean'], // whether to always display data points and not just on hover
rollover_time_format: [null, 'string'], // custom time format for rollovers
show_confidence_band: [null, 'string[]'], // determines whether to show a confidence band
show_rollover_text: [true, 'boolean'], // determines whether to show text for a data point on rollover
show_tooltips: [true, 'boolean'], // determines whether to display descriptions in tooltips
showActivePoint: [true, 'boolean'], // If enabled show active data point information in chart
target: ['#viz', ['string', HTMLElement]], // the DOM element to insert the graphic in
transition_on_update: [true, 'boolean'], // gracefully transitions the lines on data change
x_rug: [false, 'boolean'], // show a rug plot along the x-axis
y_rug: [false, 'boolean'], // show a rug plot along the y-axis
mouseover_align: ['right', ['right', 'left']],
brush: [null, ['xy','x','y']], // add brush function
brushing_selection_changed: [null, 'function'], // callback function on brushing. the first parameter are the arguments that correspond to this chart, the second parameter is the range of the selection
zoom_target: [null, 'object'], // the zooming target of brushing function
click_to_zoom_out: [true, 'boolean'], // if true and the graph is currently zoomed in, clicking on the graph will zoom out
// Layout
buffer: [8, 'number'], // the padding around the graphic
bottom: [45, 'number'], // the size of the bottom margin
center_title_full_width: [false, 'boolean'], // center title over entire graph
height: [220, 'number'], // the graphic's height
left: [50, 'number'], // the size of the left margin
right: [10, 'number'], // the size of the right margin
small_height_threshold: [120, 'number'], // maximum height for a small graphic
small_width_threshold: [160, 'number'], // maximum width for a small graphic
top: [65, 'number'], // the size of the top margin
width: [350, 'number'], // the graphic's width
title_y_position: [10, 'number'], // how many pixels from the top edge (0) should we show the title at
title: [null, 'string'],
description: [null, 'string']
};
MG.charts = {};
MG.defaults = options_to_defaults(MG.options);
MG.data_graphic = function(args) {
'use strict';
MG.call_hook('global.defaults', MG.defaults);
if (!args) { args = {}; }
for (let key in args) {
if (!mg_validate_option(key, args[key])) {
if (!(key in MG.options)) {
console.warn(`Option ${key} not recognized`);
} else {
console.warn(`Option ${key} expected type ${MG.options[key][1]} but got ${args[key]} instead`);
}
}
}
var selected_chart = MG.charts[args.chart_type || MG.defaults.chart_type];
merge_with_defaults(args, selected_chart.defaults, MG.defaults);
if (args.list) {
args.x_accessor = 0;
args.y_accessor = 1;
}
// check for deprecated parameters
for (var key in MG.deprecations) {
if (args.hasOwnProperty(key)) {
var deprecation = MG.deprecations[key],
message = 'Use of `args.' + key + '` has been deprecated',
replacement = deprecation.replacement,
version;
// transparently alias the deprecated
if (replacement) {
if (args[replacement]) {
message += '. The replacement - `args.' + replacement + '` - has already been defined. This definition will be discarded.';
} else {
args[replacement] = args[key];
}
}
if (deprecation.warned) {
continue;
}
deprecation.warned = true;
if (replacement) {
message += ' in favor of `args.' + replacement + '`';
}
warn_deprecation(message, deprecation.version);
}
}
MG.call_hook('global.before_init', args);
new selected_chart.descriptor(args);
return args.data;
};
|