plotly.js
Version:
The open source javascript graphing library that powers plotly
188 lines (156 loc) • 6.29 kB
JavaScript
var Lib = require('../../lib');
var Color = require('../../components/color');
var setCursor = require('../../lib/setcursor');
var pieHelpers = require('../pie/helpers');
exports.findEntryWithLevel = function(hierarchy, level) {
var out;
if(level) {
hierarchy.eachAfter(function(pt) {
if(exports.getPtId(pt) === level) {
return out = pt.copy();
}
});
}
return out || hierarchy;
};
exports.findEntryWithChild = function(hierarchy, childId) {
var out;
hierarchy.eachAfter(function(pt) {
var children = pt.children || [];
for(var i = 0; i < children.length; i++) {
var child = children[i];
if(exports.getPtId(child) === childId) {
return out = pt.copy();
}
}
});
return out || hierarchy;
};
exports.isEntry = function(pt) {
return !pt.parent;
};
exports.isLeaf = function(pt) {
return !pt.children;
};
exports.getPtId = function(pt) {
return pt.data.data.id;
};
exports.getPtLabel = function(pt) {
return pt.data.data.label;
};
exports.getValue = function(d) {
return d.value;
};
exports.isHierarchyRoot = function(pt) {
return getParentId(pt) === '';
};
exports.setSliceCursor = function(sliceTop, gd, opts) {
var hide = opts.isTransitioning;
if(!hide) {
var pt = sliceTop.datum();
hide = (
(opts.hideOnRoot && exports.isHierarchyRoot(pt)) ||
(opts.hideOnLeaves && exports.isLeaf(pt))
);
}
setCursor(sliceTop, hide ? null : 'pointer');
};
function determineOutsideTextFont(trace, pt, layoutFont) {
return {
color: exports.getOutsideTextFontKey('color', trace, pt, layoutFont),
family: exports.getOutsideTextFontKey('family', trace, pt, layoutFont),
size: exports.getOutsideTextFontKey('size', trace, pt, layoutFont),
weight: exports.getOutsideTextFontKey('weight', trace, pt, layoutFont),
style: exports.getOutsideTextFontKey('style', trace, pt, layoutFont),
variant: exports.getOutsideTextFontKey('variant', trace, pt, layoutFont),
textcase: exports.getOutsideTextFontKey('textcase', trace, pt, layoutFont),
lineposition: exports.getOutsideTextFontKey('lineposition', trace, pt, layoutFont),
shadow: exports.getOutsideTextFontKey('shadow', trace, pt, layoutFont),
};
}
function determineInsideTextFont(trace, pt, layoutFont, opts) {
var onPathbar = (opts || {}).onPathbar;
var cdi = pt.data.data;
var ptNumber = cdi.i;
var customColor = Lib.castOption(trace, ptNumber,
(onPathbar ? 'pathbar.textfont' : 'insidetextfont') + '.color'
);
if(!customColor && trace._input.textfont) {
// Why not simply using trace.textfont? Because if not set, it
// defaults to layout.font which has a default color. But if
// textfont.color and insidetextfont.color don't supply a value,
// a contrasting color shall be used.
customColor = Lib.castOption(trace._input, ptNumber, 'textfont.color');
}
return {
color: customColor || Color.contrast(cdi.color),
family: exports.getInsideTextFontKey('family', trace, pt, layoutFont, opts),
size: exports.getInsideTextFontKey('size', trace, pt, layoutFont, opts),
weight: exports.getInsideTextFontKey('weight', trace, pt, layoutFont, opts),
style: exports.getInsideTextFontKey('style', trace, pt, layoutFont, opts),
variant: exports.getInsideTextFontKey('variant', trace, pt, layoutFont, opts),
textcase: exports.getInsideTextFontKey('textcase', trace, pt, layoutFont, opts),
lineposition: exports.getInsideTextFontKey('lineposition', trace, pt, layoutFont, opts),
shadow: exports.getInsideTextFontKey('shadow', trace, pt, layoutFont, opts),
};
}
exports.getInsideTextFontKey = function(keyStr, trace, pt, layoutFont, opts) {
var onPathbar = (opts || {}).onPathbar;
var cont = onPathbar ? 'pathbar.textfont' : 'insidetextfont';
var ptNumber = pt.data.data.i;
return (
Lib.castOption(trace, ptNumber, cont + '.' + keyStr) ||
Lib.castOption(trace, ptNumber, 'textfont.' + keyStr) ||
layoutFont.size
);
};
exports.getOutsideTextFontKey = function(keyStr, trace, pt, layoutFont) {
var ptNumber = pt.data.data.i;
return (
Lib.castOption(trace, ptNumber, 'outsidetextfont.' + keyStr) ||
Lib.castOption(trace, ptNumber, 'textfont.' + keyStr) ||
layoutFont.size
);
};
exports.isOutsideText = function(trace, pt) {
return !trace._hasColorscale && exports.isHierarchyRoot(pt);
};
exports.determineTextFont = function(trace, pt, layoutFont, opts) {
return exports.isOutsideText(trace, pt) ?
determineOutsideTextFont(trace, pt, layoutFont) :
determineInsideTextFont(trace, pt, layoutFont, opts);
};
exports.hasTransition = function(transitionOpts) {
// We could optimize hasTransition per trace,
// as sunburst, treemap & icicle have no cross-trace logic!
return !!(transitionOpts && transitionOpts.duration > 0);
};
exports.getMaxDepth = function(trace) {
return trace.maxdepth >= 0 ? trace.maxdepth : Infinity;
};
exports.isHeader = function(pt, trace) { // it is only used in treemap.
return !(exports.isLeaf(pt) || pt.depth === trace._maxDepth - 1);
};
function getParentId(pt) {
return pt.data.data.pid;
}
exports.getParent = function(hierarchy, pt) {
return exports.findEntryWithLevel(hierarchy, getParentId(pt));
};
exports.listPath = function(d, keyStr) {
var parent = d.parent;
if(!parent) return [];
var list = keyStr ? [parent.data[keyStr]] : [parent];
return exports.listPath(parent, keyStr).concat(list);
};
exports.getPath = function(d) {
return exports.listPath(d, 'label').join('/') + '/';
};
exports.formatValue = pieHelpers.formatPieValue;
// TODO: should combine the two in a separate PR - Also please note Lib.formatPercent should support separators.
exports.formatPercent = function(v, separators) {
var tx = Lib.formatPercent(v, 0); // use funnel(area) version
if(tx === '0%') tx = pieHelpers.formatPiePercent(v, separators); // use pie version
return tx;
};
;