Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F652918
bar.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
24 KB
Subscribers
None
bar.js
View Options
{
// TODO add styles to stylesheet instead
function
scaffold
({
target
,
width
,
height
,
top
,
left
,
right
,
buffer
})
{
const
svg
=
mg_get_svg_child_of
(
target
);
// main margins
svg
.
append
(
'line'
)
.
attr
(
'x1'
,
0
)
.
attr
(
'x2'
,
width
)
.
attr
(
'y1'
,
top
)
.
attr
(
'y2'
,
top
)
.
attr
(
'stroke'
,
'black'
);
svg
.
append
(
'line'
)
.
attr
(
'x1'
,
0
)
.
attr
(
'x2'
,
width
)
.
attr
(
'y1'
,
height
-
bottom
)
.
attr
(
'y2'
,
height
-
bottom
)
.
attr
(
'stroke'
,
'black'
);
svg
.
append
(
'line'
)
.
attr
(
'x1'
,
left
)
.
attr
(
'x2'
,
left
)
.
attr
(
'y1'
,
0
)
.
attr
(
'y2'
,
height
)
.
attr
(
'stroke'
,
'black'
);
svg
.
append
(
'line'
)
.
attr
(
'x1'
,
width
-
right
)
.
attr
(
'x2'
,
width
-
right
)
.
attr
(
'y1'
,
0
)
.
attr
(
'y2'
,
height
)
.
attr
(
'stroke'
,
'black'
);
// plot area margins
svg
.
append
(
'line'
)
.
attr
(
'x1'
,
0
)
.
attr
(
'x2'
,
width
)
.
attr
(
'y1'
,
height
-
bottom
-
buffer
)
.
attr
(
'y2'
,
height
-
bottom
-
buffer
)
.
attr
(
'stroke'
,
'gray'
);
svg
.
append
(
'line'
)
.
attr
(
'x1'
,
0
)
.
attr
(
'x2'
,
width
)
.
attr
(
'y1'
,
top
+
buffer
)
.
attr
(
'y2'
,
top
+
buffer
)
.
attr
(
'stroke'
,
'gray'
);
svg
.
append
(
'line'
)
.
attr
(
'x1'
,
left
+
buffer
)
.
attr
(
'x2'
,
left
+
buffer
)
.
attr
(
'y1'
,
0
)
.
attr
(
'y2'
,
args
.
height
)
.
attr
(
'stroke'
,
'gray'
);
svg
.
append
(
'line'
)
.
attr
(
'x1'
,
width
-
right
-
buffer
)
.
attr
(
'x2'
,
width
-
right
-
buffer
)
.
attr
(
'y1'
,
0
)
.
attr
(
'y2'
,
height
)
.
attr
(
'stroke'
,
'gray'
);
}
// barchart re-write.
function
mg_targeted_legend
({
legend_target
,
orientation
,
scales
})
{
let
labels
;
const
plot
=
''
;
if
(
legend_target
)
{
const
div
=
d3
.
select
(
legend_target
).
append
(
'div'
).
classed
(
'mg-bar-target-legend'
,
true
);
if
(
orientation
==
'horizontal'
)
labels
=
scales
.
Y
.
domain
();
else
labels
=
scales
.
X
.
domain
();
labels
.
forEach
(
label
=>
{
const
outer_span
=
div
.
append
(
'span'
).
classed
(
'mg-bar-target-element'
,
true
);
outer_span
.
append
(
'span'
)
.
classed
(
'mg-bar-target-legend-shape'
,
true
)
.
style
(
'color'
,
scales
.
COLOR
(
label
))
.
text
(
'\u25FC '
);
outer_span
.
append
(
'span'
)
.
classed
(
'mg-bar-target-legend-text'
,
true
)
.
text
(
label
);
});
}
}
function
legend_on_graph
(
svg
,
args
)
{
// draw each element at the top right
// get labels
let
labels
;
if
(
args
.
orientation
==
'horizontal'
)
labels
=
args
.
scales
.
Y
.
domain
();
else
labels
=
args
.
scales
.
X
.
domain
();
let
lineCount
=
0
;
const
lineHeight
=
1.1
;
const
g
=
svg
.
append
(
'g'
).
classed
(
"mg-bar-legend"
,
true
);
const
textContainer
=
g
.
append
(
'text'
);
textContainer
.
selectAll
(
'*'
)
.
remove
();
textContainer
.
attr
(
'width'
,
args
.
right
)
.
attr
(
'height'
,
100
)
.
attr
(
'text-anchor'
,
'start'
);
labels
.
forEach
(
label
=>
{
const
sub_container
=
textContainer
.
append
(
'tspan'
)
.
attr
(
'x'
,
mg_get_plot_right
(
args
))
.
attr
(
'y'
,
args
.
height
/
2
)
.
attr
(
'dy'
,
`
${
lineCount
*
lineHeight
}
em`
);
sub_container
.
append
(
'tspan'
)
.
text
(
'\u25a0 '
)
.
attr
(
'fill'
,
args
.
scales
.
COLOR
(
label
))
.
attr
(
'font-size'
,
20
);
sub_container
.
append
(
'tspan'
)
.
text
(
label
)
.
attr
(
'font-weight'
,
300
)
.
attr
(
'font-size'
,
10
);
lineCount
++
;
});
// d.values.forEach(function (datum) {
// formatted_y = mg_format_y_rollover(args, num, datum);
// if (args.y_rollover_format !== null) {
// formatted_y = number_rollover_format(args.y_rollover_format, datum, args.y_accessor);
// } else {
// formatted_y = args.yax_units + num(datum[args.y_accessor]);
// }
// sub_container = textContainer.append('tspan').attr('x', 0).attr('y', (lineCount * lineHeight) + 'em');
// formatted_y = mg_format_y_rollover(args, num, datum);
// mouseover_tspan(sub_container, '\u2014 ')
// .color(args, datum);
// mouseover_tspan(sub_container, formatted_x + ' ' + formatted_y);
// lineCount++;
// });
}
function
barChart
(
args
)
{
this
.
args
=
args
;
this
.
init
=
(
args
)
=>
{
this
.
args
=
args
;
args
.
x_axis_type
=
mg_infer_type
(
args
,
'x'
);
args
.
y_axis_type
=
mg_infer_type
(
args
,
'y'
);
// this is specific to how rects work in svg, let's keep track of the bar orientation to
// plot appropriately.
if
(
args
.
x_axis_type
==
'categorical'
)
{
args
.
orientation
=
'vertical'
;
}
else
if
(
args
.
y_axis_type
==
'categorical'
)
{
args
.
orientation
=
'horizontal'
;
}
else
if
(
args
.
x_axis_type
!=
'categorical'
&&
args
.
y_axis_type
!=
'categorical'
)
{
// histogram.
args
.
orientation
=
'vertical'
;
}
raw_data_transformation
(
args
);
process_point
(
args
);
init
(
args
);
let
xMaker
;
let
yMaker
;
if
(
args
.
x_axis_type
===
'categorical'
)
{
xMaker
=
MG
.
scale_factory
(
args
)
.
namespace
(
'x'
)
.
categoricalDomainFromData
()
.
categoricalRangeBands
([
0
,
args
.
xgroup_height
],
args
.
xgroup_accessor
===
null
);
if
(
args
.
xgroup_accessor
)
{
new
MG
.
scale_factory
(
args
)
.
namespace
(
'xgroup'
)
.
categoricalDomainFromData
()
.
categoricalRangeBands
(
'bottom'
);
}
else
{
args
.
scales
.
XGROUP
=
d
=>
mg_get_plot_left
(
args
);
args
.
scalefns
.
xgroupf
=
d
=>
mg_get_plot_left
(
args
);
}
args
.
scalefns
.
xoutf
=
d
=>
args
.
scalefns
.
xf
(
d
)
+
args
.
scalefns
.
xgroupf
(
d
);
}
else
{
xMaker
=
MG
.
scale_factory
(
args
)
.
namespace
(
'x'
)
.
inflateDomain
(
true
)
.
zeroBottom
(
args
.
y_axis_type
===
'categorical'
)
.
numericalDomainFromData
((
args
.
baselines
||
[]).
map
(
d
=>
d
[
args
.
x_accessor
]))
.
numericalRange
(
'bottom'
);
args
.
scalefns
.
xoutf
=
args
.
scalefns
.
xf
;
}
// y-scale generation. This needs to get simplified.
if
(
args
.
y_axis_type
===
'categorical'
)
{
yMaker
=
MG
.
scale_factory
(
args
)
.
namespace
(
'y'
)
.
zeroBottom
(
true
)
.
categoricalDomainFromData
()
.
categoricalRangeBands
([
0
,
args
.
ygroup_height
],
true
);
if
(
args
.
ygroup_accessor
)
{
new
MG
.
scale_factory
(
args
)
.
namespace
(
'ygroup'
)
.
categoricalDomainFromData
()
.
categoricalRangeBands
(
'left'
);
}
else
{
args
.
scales
.
YGROUP
=
()
=>
mg_get_plot_top
(
args
);
args
.
scalefns
.
ygroupf
=
d
=>
mg_get_plot_top
(
args
);
}
args
.
scalefns
.
youtf
=
d
=>
args
.
scalefns
.
yf
(
d
)
+
args
.
scalefns
.
ygroupf
(
d
);
}
else
{
const
baselines
=
(
args
.
baselines
||
[]).
map
(
d
=>
d
[
args
.
y_accessor
]);
yMaker
=
MG
.
scale_factory
(
args
)
.
namespace
(
'y'
)
.
inflateDomain
(
true
)
.
zeroBottom
(
args
.
x_axis_type
===
'categorical'
)
.
numericalDomainFromData
(
baselines
)
.
numericalRange
(
'left'
);
args
.
scalefns
.
youtf
=
d
=>
args
.
scalefns
.
yf
(
d
);
}
if
(
args
.
ygroup_accessor
!==
null
)
{
args
.
ycolor_accessor
=
args
.
y_accessor
;
MG
.
scale_factory
(
args
)
.
namespace
(
'ycolor'
)
.
scaleName
(
'color'
)
.
categoricalDomainFromData
()
.
categoricalColorRange
();
}
if
(
args
.
xgroup_accessor
!==
null
)
{
args
.
xcolor_accessor
=
args
.
x_accessor
;
MG
.
scale_factory
(
args
)
.
namespace
(
'xcolor'
)
.
scaleName
(
'color'
)
.
categoricalDomainFromData
()
.
categoricalColorRange
();
}
// if (args.ygroup_accessor !== null) {
// MG.scale_factory(args)
// .namespace('ygroup')
// .categoricalDomainFromData()
// .categoricalColorRange();
// }
new
MG
.
axis_factory
(
args
)
.
namespace
(
'x'
)
.
type
(
args
.
x_axis_type
)
.
zeroLine
(
args
.
y_axis_type
===
'categorical'
)
.
position
(
args
.
x_axis_position
)
.
draw
();
new
MG
.
axis_factory
(
args
)
.
namespace
(
'y'
)
.
type
(
args
.
y_axis_type
)
.
zeroLine
(
args
.
x_axis_type
===
'categorical'
)
.
position
(
args
.
y_axis_position
)
.
draw
();
//mg_categorical_group_color_scale(args);
this
.
mainPlot
();
this
.
markers
();
this
.
rollover
();
this
.
windowListeners
();
//scaffold(args)
return
this
;
};
this
.
mainPlot
=
()
=>
{
const
svg
=
mg_get_svg_child_of
(
args
.
target
);
const
data
=
args
.
data
[
0
];
let
barplot
=
svg
.
select
(
'g.mg-barplot'
);
const
fresh_render
=
barplot
.
empty
();
let
bars
,
predictor_bars
,
pp
,
pp0
,
baseline_marks
;
const
perform_load_animation
=
fresh_render
&&
args
.
animate_on_load
;
const
should_transition
=
perform_load_animation
||
args
.
transition_on_update
;
const
transition_duration
=
args
.
transition_duration
||
1000
;
// draw the plot on first render
if
(
fresh_render
)
{
barplot
=
svg
.
append
(
'g'
)
.
classed
(
'mg-barplot'
,
true
);
}
bars
=
barplot
.
selectAll
(
'.mg-bar'
)
.
data
(
data
)
.
enter
()
.
append
(
'rect'
)
.
classed
(
'mg-bar'
,
true
)
.
classed
(
'default-bar'
,
args
.
scales
.
hasOwnProperty
(
'COLOR'
)
?
false
:
true
);
// TODO - reimplement
// reference_accessor {}
// if (args.predictor_accessor) {
// predictor_bars = barplot.selectAll('.mg-bar-prediction')
// .data(data.filter(function(d) {
// return d.hasOwnProperty(args.predictor_accessor) }));
// predictor_bars.exit().remove();
// predictor_bars.enter().append('rect')
// .classed('mg-bar-prediction', true);
// }
// if (args.baseline_accessor) {
// baseline_marks = barplot.selectAll('.mg-bar-baseline')
// .data(data.filter(function(d) {
// return d.hasOwnProperty(args.baseline_accessor) }));
// baseline_marks.exit().remove();
// baseline_marks.enter().append('line')
// .classed('mg-bar-baseline', true);
// }
let
appropriate_size
;
// setup transitions
// if (should_transition) {
// bars = bars.transition()
// .duration(transition_duration);
// if (predictor_bars) {
// predictor_bars = predictor_bars.transition()
// .duration(transition_duration);
// }
// if (baseline_marks) {
// baseline_marks = baseline_marks.transition()
// .duration(transition_duration);
// }
// }
//appropriate_size = args.scales.Y_ingroup.rangeBand()/1.5;
let
length
,
width
,
length_type
,
width_type
,
length_coord
,
width_coord
,
length_scalefn
,
width_scalefn
,
length_scale
,
width_scale
,
length_accessor
,
width_accessor
,
length_coord_map
,
width_coord_map
,
length_map
,
width_map
;
let
reference_length_map
,
reference_length_coord_fn
;
if
(
args
.
orientation
==
'vertical'
)
{
length
=
'height'
;
width
=
'width'
;
length_type
=
args
.
y_axis_type
;
width_type
=
args
.
x_axis_type
;
length_coord
=
'y'
;
width_coord
=
'x'
;
length_scalefn
=
length_type
==
'categorical'
?
args
.
scalefns
.
youtf
:
args
.
scalefns
.
yf
;
width_scalefn
=
width_type
==
'categorical'
?
args
.
scalefns
.
xoutf
:
args
.
scalefns
.
xf
;
length_scale
=
args
.
scales
.
Y
;
width_scale
=
args
.
scales
.
X
;
length_accessor
=
args
.
y_accessor
;
width_accessor
=
args
.
x_accessor
;
length_coord_map
=
d
=>
{
let
l
;
l
=
length_scalefn
(
d
);
if
(
d
[
length_accessor
]
<
0
)
{
l
=
length_scale
(
0
);
}
return
l
;
};
length_map
=
d
=>
Math
.
abs
(
length_scalefn
(
d
)
-
length_scale
(
0
));
reference_length_map
=
d
=>
Math
.
abs
(
length_scale
(
d
[
args
.
reference_accessor
])
-
length_scale
(
0
));
reference_length_coord_fn
=
d
=>
length_scale
(
d
[
args
.
reference_accessor
]);
}
if
(
args
.
orientation
==
'horizontal'
)
{
length
=
'width'
;
width
=
'height'
;
length_type
=
args
.
x_axis_type
;
width_type
=
args
.
y_axis_type
;
length_coord
=
'x'
;
width_coord
=
'y'
;
length_scalefn
=
length_type
==
'categorical'
?
args
.
scalefns
.
xoutf
:
args
.
scalefns
.
xf
;
width_scalefn
=
width_type
==
'categorical'
?
args
.
scalefns
.
youtf
:
args
.
scalefns
.
yf
;
length_scale
=
args
.
scales
.
X
;
width_scale
=
args
.
scales
.
Y
;
length_accessor
=
args
.
x_accessor
;
width_accessor
=
args
.
y_accessor
;
length_coord_map
=
d
=>
{
let
l
;
l
=
length_scale
(
0
);
return
l
;
};
length_map
=
d
=>
Math
.
abs
(
length_scalefn
(
d
)
-
length_scale
(
0
));
reference_length_map
=
d
=>
Math
.
abs
(
length_scale
(
d
[
args
.
reference_accessor
])
-
length_scale
(
0
));
reference_length_coord_fn
=
d
=>
length_scale
(
0
);
}
// if (perform_load_animation) {
// bars.attr(length, 0);
// if (predictor_bars) {
// predictor_bars.attr(length, 0);
// }
// // if (baseline_marks) {
// // baseline_marks.attr({
// // x1: args.scales.X(0),
// // x2: args.scales.X(0)
// // });
// // }
// }
bars
.
attr
(
length_coord
,
length_coord_map
);
// bars.attr(length_coord, 40)
//bars.attr(width_coord, 70)
bars
.
attr
(
width_coord
,
d
=>
{
let
w
;
if
(
width_type
==
'categorical'
)
{
w
=
width_scalefn
(
d
);
}
else
{
w
=
width_scale
(
0
);
if
(
d
[
width_accessor
]
<
0
)
{
w
=
width_scalefn
(
d
);
}
}
w
=
w
-
args
.
bar_thickness
/
2
;
return
w
;
});
if
(
args
.
scales
.
COLOR
)
{
bars
.
attr
(
'fill'
,
args
.
scalefns
.
colorf
);
}
bars
.
attr
(
length
,
length_map
)
.
attr
(
width
,
d
=>
args
.
bar_thickness
);
if
(
args
.
reference_accessor
!==
null
)
{
const
reference_data
=
data
.
filter
(
d
=>
d
.
hasOwnProperty
(
args
.
reference_accessor
));
const
reference_bars
=
barplot
.
selectAll
(
'.mg-categorical-reference'
)
.
data
(
reference_data
)
.
enter
()
.
append
(
'rect'
);
reference_bars
.
attr
(
length_coord
,
reference_length_coord_fn
)
.
attr
(
width_coord
,
d
=>
width_scalefn
(
d
)
-
args
.
reference_thickness
/
2
)
.
attr
(
length
,
reference_length_map
)
.
attr
(
width
,
args
.
reference_thickness
);
}
if
(
args
.
comparison_accessor
!==
null
)
{
let
comparison_thickness
=
null
;
if
(
args
.
comparison_thickness
===
null
)
{
comparison_thickness
=
args
.
bar_thickness
/
2
;
}
else
{
comparison_thickness
=
args
.
comparison_thickness
;
}
const
comparison_data
=
data
.
filter
(
d
=>
d
.
hasOwnProperty
(
args
.
comparison_accessor
));
const
comparison_marks
=
barplot
.
selectAll
(
'.mg-categorical-comparison'
)
.
data
(
comparison_data
)
.
enter
()
.
append
(
'line'
);
comparison_marks
.
attr
(
`
${
length_coord
}
1`
,
d
=>
length_scale
(
d
[
args
.
comparison_accessor
]))
.
attr
(
`
${
length_coord
}
2`
,
d
=>
length_scale
(
d
[
args
.
comparison_accessor
]))
.
attr
(
`
${
width_coord
}
1`
,
d
=>
width_scalefn
(
d
)
-
comparison_thickness
/
2
)
.
attr
(
`
${
width_coord
}
2`
,
d
=>
width_scalefn
(
d
)
+
comparison_thickness
/
2
)
.
attr
(
'stroke'
,
'black'
)
.
attr
(
'stroke-width'
,
args
.
comparison_width
);
}
//bars.attr(width_coord, );
// bars.attr('width', 50);
// bars.attr('height', 50);
// bars.attr('y', function(d){
// var y = args.scales.Y(0);
// if (d[args.y_accessor] < 0) {
// y = args.scalefns.yf(d);
// }
// return y;
// });
// bars.attr('x', function(d){
// return 40;
// })
// bars.attr('width', function(d){
// return 100;
// });
// bars.attr('height', 100);
// bars.attr('fill', 'black');
// bars.attr('x', function(d) {
// var x = args.scales.X(0);
// if (d[args.x_accessor] < 0) {
// x = args.scalefns.xf(d);
// }
// return x;
// })
// TODO - reimplement.
// if (args.predictor_accessor) {
// predictor_bars
// .attr('x', args.scales.X(0))
// .attr('y', function(d) {
// return args.scalefns.ygroupf(d) + args.scalefns.yf(d) + args.scales.Y.rangeBand() * (7 / 16) // + pp0 * appropriate_size/(pp*2) + appropriate_size / 2;
// })
// .attr('height', args.scales.Y.rangeBand() / 8) //appropriate_size / pp)
// .attr('width', function(d) {
// return args.scales.X(d[args.predictor_accessor]) - args.scales.X(0);
// });
// }
// TODO - reimplement.
// if (args.baseline_accessor) {
// baseline_marks
// .attr('x1', function(d) {
// return args.scales.X(d[args.baseline_accessor]); })
// .attr('x2', function(d) {
// return args.scales.X(d[args.baseline_accessor]); })
// .attr('y1', function(d) {
// return args.scalefns.ygroupf(d) + args.scalefns.yf(d) + args.scales.Y.rangeBand() / 4
// })
// .attr('y2', function(d) {
// return args.scalefns.ygroupf(d) + args.scalefns.yf(d) + args.scales.Y.rangeBand() * 3 / 4
// });
// }
if
(
args
.
legend
||
(
args
.
color_accessor
!==
null
&&
args
.
ygroup_accessor
!==
args
.
color_accessor
))
{
if
(
!
args
.
legend_target
)
legend_on_graph
(
svg
,
args
);
else
mg_targeted_legend
(
args
);
}
return
this
;
};
this
.
markers
=
()
=>
{
markers
(
args
);
return
this
;
};
this
.
rollover
=
()
=>
{
const
svg
=
mg_get_svg_child_of
(
args
.
target
);
let
g
;
if
(
svg
.
selectAll
(
'.mg-active-datapoint-container'
).
nodes
().
length
===
0
)
{
mg_add_g
(
svg
,
'mg-active-datapoint-container'
);
}
//remove the old rollovers if they already exist
svg
.
selectAll
(
'.mg-rollover-rect'
).
remove
();
svg
.
selectAll
(
'.mg-active-datapoint'
).
remove
();
// get orientation
let
length
,
width
,
length_type
,
width_type
,
length_coord
,
width_coord
,
length_scalefn
,
width_scalefn
,
length_scale
,
width_scale
,
length_accessor
,
width_accessor
;
let
length_coord_map
,
width_coord_map
,
length_map
,
width_map
;
if
(
args
.
orientation
==
'vertical'
)
{
length
=
'height'
;
width
=
'width'
;
length_type
=
args
.
y_axis_type
;
width_type
=
args
.
x_axis_type
;
length_coord
=
'y'
;
width_coord
=
'x'
;
length_scalefn
=
length_type
==
'categorical'
?
args
.
scalefns
.
youtf
:
args
.
scalefns
.
yf
;
width_scalefn
=
width_type
==
'categorical'
?
args
.
scalefns
.
xoutf
:
args
.
scalefns
.
xf
;
length_scale
=
args
.
scales
.
Y
;
width_scale
=
args
.
scales
.
X
;
length_accessor
=
args
.
y_accessor
;
width_accessor
=
args
.
x_accessor
;
length_coord_map
=
d
=>
mg_get_plot_top
(
args
);
length_map
=
d
=>
args
.
height
-
args
.
top
-
args
.
bottom
-
args
.
buffer
*
2
;
}
if
(
args
.
orientation
==
'horizontal'
)
{
length
=
'width'
;
width
=
'height'
;
length_type
=
args
.
x_axis_type
;
width_type
=
args
.
y_axis_type
;
length_coord
=
'x'
;
width_coord
=
'y'
;
length_scalefn
=
length_type
==
'categorical'
?
args
.
scalefns
.
xoutf
:
args
.
scalefns
.
xf
;
width_scalefn
=
width_type
==
'categorical'
?
args
.
scalefns
.
youtf
:
args
.
scalefns
.
yf
;
length_scale
=
args
.
scales
.
X
;
width_scale
=
args
.
scales
.
Y
;
length_accessor
=
args
.
x_accessor
;
width_accessor
=
args
.
y_accessor
;
length_coord_map
=
d
=>
{
let
l
;
l
=
length_scale
(
0
);
return
l
;
};
length_map
=
d
=>
args
.
width
-
args
.
left
-
args
.
right
-
args
.
buffer
*
2
;
}
//rollover text
let
rollover_x
,
rollover_anchor
;
if
(
args
.
rollover_align
===
'right'
)
{
rollover_x
=
args
.
width
-
args
.
right
;
rollover_anchor
=
'end'
;
}
else
if
(
args
.
rollover_align
===
'left'
)
{
rollover_x
=
args
.
left
;
rollover_anchor
=
'start'
;
}
else
{
rollover_x
=
(
args
.
width
-
args
.
left
-
args
.
right
)
/
2
+
args
.
left
;
rollover_anchor
=
'middle'
;
}
svg
.
append
(
'text'
)
.
attr
(
'class'
,
'mg-active-datapoint'
)
.
attr
(
'xml:space'
,
'preserve'
)
.
attr
(
'x'
,
rollover_x
)
.
attr
(
'y'
,
args
.
top
*
0.75
)
.
attr
(
'dy'
,
'.35em'
)
.
attr
(
'text-anchor'
,
rollover_anchor
);
g
=
svg
.
append
(
'g'
)
.
attr
(
'class'
,
'mg-rollover-rect'
);
//draw rollover bars
const
bars
=
g
.
selectAll
(
".mg-bar-rollover"
)
.
data
(
args
.
data
[
0
]).
enter
()
.
append
(
"rect"
)
.
attr
(
'class'
,
'mg-bar-rollover'
);
bars
.
attr
(
'opacity'
,
0
)
.
attr
(
length_coord
,
length_coord_map
)
.
attr
(
width_coord
,
d
=>
{
let
w
;
if
(
width_type
==
'categorical'
)
{
w
=
width_scalefn
(
d
);
}
else
{
w
=
width_scale
(
0
);
if
(
d
[
width_accessor
]
<
0
)
{
w
=
width_scalefn
(
d
);
}
}
w
=
w
-
args
.
bar_thickness
/
2
;
return
w
;
});
bars
.
attr
(
length
,
length_map
);
bars
.
attr
(
width
,
d
=>
args
.
bar_thickness
);
bars
.
on
(
'mouseover'
,
this
.
rolloverOn
(
args
))
.
on
(
'mouseout'
,
this
.
rolloverOff
(
args
))
.
on
(
'mousemove'
,
this
.
rolloverMove
(
args
));
return
this
;
};
this
.
rolloverOn
=
(
args
)
=>
{
const
svg
=
mg_get_svg_child_of
(
args
.
target
);
const
label_accessor
=
this
.
is_vertical
?
args
.
x_accessor
:
args
.
y_accessor
;
const
data_accessor
=
this
.
is_vertical
?
args
.
y_accessor
:
args
.
x_accessor
;
const
label_units
=
this
.
is_vertical
?
args
.
yax_units
:
args
.
xax_units
;
return
(
d
,
i
)
=>
{
const
fmt
=
MG
.
time_format
(
args
.
utc_time
,
'%b %e, %Y'
);
const
num
=
format_rollover_number
(
args
);
//highlight active bar
const
bar
=
svg
.
selectAll
(
'g.mg-barplot .mg-bar'
)
.
filter
((
d
,
j
)
=>
j
===
i
).
classed
(
'active'
,
true
);
if
(
args
.
scales
.
hasOwnProperty
(
'COLOR'
))
{
bar
.
attr
(
'fill'
,
d3
.
rgb
(
args
.
scalefns
.
colorf
(
d
)).
darker
());
}
else
{
bar
.
classed
(
'default-active'
,
true
);
}
//update rollover text
if
(
args
.
show_rollover_text
)
{
const
mouseover
=
mg_mouseover_text
(
args
,
{
svg
});
let
row
=
mouseover
.
mouseover_row
();
if
(
args
.
ygroup_accessor
)
row
.
text
(
`
${
d
[
args
.
ygroup_accessor
]
}
`
).
bold
();
row
.
text
(
mg_format_x_mouseover
(
args
,
d
));
row
.
text
(
`
${
args
.
y_accessor
}
:
${
d
[
args
.
y_accessor
]
}
`
);
if
(
args
.
predictor_accessor
||
args
.
baseline_accessor
)
{
row
=
mouseover
.
mouseover_row
();
if
(
args
.
predictor_accessor
)
row
.
text
(
mg_format_data_for_mouseover
(
args
,
d
,
null
,
args
.
predictor_accessor
,
false
));
if
(
args
.
baseline_accessor
)
row
.
text
(
mg_format_data_for_mouseover
(
args
,
d
,
null
,
args
.
baseline_accessor
,
false
));
}
}
if
(
args
.
mouseover
)
{
args
.
mouseover
(
d
,
i
);
}
};
};
this
.
rolloverOff
=
(
args
)
=>
{
const
svg
=
mg_get_svg_child_of
(
args
.
target
);
return
(
d
,
i
)
=>
{
//reset active bar
const
bar
=
svg
.
selectAll
(
'g.mg-barplot .mg-bar.active'
).
classed
(
'active'
,
false
);
if
(
args
.
scales
.
hasOwnProperty
(
'COLOR'
))
{
bar
.
attr
(
'fill'
,
args
.
scalefns
.
colorf
(
d
));
}
else
{
bar
.
classed
(
'default-active'
,
false
);
}
//reset active data point text
svg
.
select
(
'.mg-active-datapoint'
)
.
text
(
''
);
mg_clear_mouseover_container
(
svg
);
if
(
args
.
mouseout
)
{
args
.
mouseout
(
d
,
i
);
}
};
};
this
.
rolloverMove
=
(
args
)
=>
(
d
,
i
)
=>
{
if
(
args
.
mousemove
)
{
args
.
mousemove
(
d
,
i
);
}
};
this
.
windowListeners
=
()
=>
{
mg_window_listeners
(
this
.
args
);
return
this
;
};
this
.
init
(
args
);
}
const
options
=
{
buffer
:
[
16
,
'number'
],
y_accessor
:
[
'factor'
,
'string'
],
x_accessor
:
[
'value'
,
'string'
],
reference_accessor
:
[
null
,
'string'
],
comparison_accessor
:
[
null
,
'string'
],
secondary_label_accessor
:
[
null
,
'string'
],
color_accessor
:
[
null
,
'string'
],
color_type
:
[
'category'
,
[
'number'
,
'category'
]],
color_domain
:
[
null
,
'number[]'
],
reference_thickness
:
[
1
,
'number'
],
comparison_width
:
[
3
,
'number'
],
comparison_thickness
:
[
null
,
'number'
],
legend
:
[
false
,
'boolean'
],
legend_target
:
[
null
,
'string'
],
mouseover_align
:
[
'right'
,
[
'right'
,
'left'
]],
baseline_accessor
:
[
null
,
'string'
],
predictor_accessor
:
[
null
,
'string'
],
predictor_proportion
:
[
5
,
'number'
],
show_bar_zero
:
[
true
,
'boolean'
],
binned
:
[
true
,
'boolean'
],
truncate_x_labels
:
[
true
,
'boolean'
],
truncate_y_labels
:
[
true
,
'boolean'
]
};
MG
.
register
(
'bar'
,
barChart
,
options
);
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, Feb 6, 12:06 AM (6 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
81606
Default Alt Text
bar.js (24 KB)
Attached To
rNOLA Nola
Event Timeline
Log In to Comment