'use strict'; 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; };