Skip to content

Instantly share code, notes, and snippets.

@john-guerra
Last active May 20, 2021 18:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save john-guerra/2e68feffb2997e4f57401c426d5c6bdf to your computer and use it in GitHub Desktop.
Save john-guerra/2e68feffb2997e4f57401c426d5c6bdf to your computer and use it in GitHub Desktop.
// https://github.com/john-guerra/Navio#readme v0.0.67 Copyright 2021 John Alexis Guerra Gómez
import * as d3 from 'd3';
import { map, format, interpolateBlues, interpolatePurples, interpolateBrBG, interpolateOranges, interpolateGreys, schemeCategory10, event, selectAll, select, path, scaleBand, scaleQuantize, range, brushY, mouse, drag, extent, scaleOrdinal, scaleSequential, set, min } from 'd3';
import { interpolateBlues as interpolateBlues$1, interpolatePurples as interpolatePurples$1, interpolateBrBG as interpolateBrBG$1, interpolateOranges as interpolateOranges$1, interpolateGreys as interpolateGreys$1 } from 'd3-scale-chromatic';
import Popper from 'popper.js';
function FilterByRange(opts) {
const first = opts.first;
const last = opts.last;
const level = opts.level;
const itemAttr = opts.itemAttr;
const getAttrib = opts.getAttrib || (d => d[itemAttr]);
const getAttribName = opts.getAttribName || (attrib => typeof(attrib) === "function" ? attrib.name : attrib);
function filter(d) {
return d.__i[level] >= first.__i[level] && d.__i[level] <= last.__i[level];
}
function toStr() {
let firstVal = `${getAttrib(first,itemAttr)}`,
lastVal = `${getAttrib(last,itemAttr)}`;
firstVal = typeof(firstVal) === typeof("") ? firstVal.slice(0,5) : firstVal;
lastVal = typeof(lastVal) === typeof("") ? lastVal.slice(0,5) : lastVal;
return `${getAttribName(itemAttr)} range including ${firstVal} to ${lastVal}`;
}
return {
filter,
toStr,
type:"range"
};
}
function FilterByValue(opts) {
const itemAttr = opts.itemAttr;
const sel = opts.sel;
const getAttrib = opts.getAttrib || (d => d[itemAttr]);
const getAttribName = opts.getAttribName || (attrib => typeof(attrib) === "function" ? attrib.name : attrib);
function filter(d) {
return getAttrib(d, itemAttr) === getAttrib(sel, itemAttr);
}
function toStr() {
return `${getAttribName(itemAttr)} == ${getAttrib(sel, itemAttr)}`;
}
return {
filter,
toStr,
type:"value"
};
}
function FilterByValueDifferent(opts) {
const itemAttr = opts.itemAttr;
const sel = opts.sel;
const getAttrib = opts.getAttrib || (d => d[itemAttr]);
const getAttribName = opts.getAttribName || (attrib => typeof(attrib) === "function" ? attrib.name : attrib);
function filter(d) {
return getAttrib(d, itemAttr) !== getAttrib(sel, itemAttr);
}
function toStr() {
return `${getAttribName(itemAttr)} != ${getAttrib(sel, itemAttr)}`;
}
return {
filter,
toStr,
type:"negativeValue"
};
}
function FilterByRangeNegative(opts) {
const first = opts.first;
const last = opts.last;
const level = opts.level;
const itemAttr = opts.itemAttr;
const getAttrib = opts.getAttrib || (d => d[itemAttr]);
const getAttribName = opts.getAttribName || (attrib => typeof(attrib) === "function" ? attrib.name : attrib);
function filter(d) {
return d.__i[level] < first.__i[level] || d.__i[level] > last.__i[level];
}
function toStr() {
let firstVal = `${getAttrib(first,itemAttr)}`,
lastVal = `${getAttrib(last,itemAttr)}`;
firstVal = typeof(firstVal) === typeof("") ? firstVal.slice(0,5) : firstVal;
lastVal = typeof(lastVal) === typeof("") ? lastVal.slice(0,5) : lastVal;
return `${getAttribName(itemAttr)} range excluding ${firstVal} to ${lastVal}`;
}
return {
filter,
toStr,
type:"negativeRange"
};
}
// Like d3.ascending but supporting null
function d3AscendingNull(a, b) {
if (b === null || b === undefined) {
if (a === null || a === undefined) return 0; // a == b == null
else return 1; // b==null a!=null
} else { // b!=null
if (a === null || a === undefined) return -1;
else {
// Both are non null
if (typeof(a)!==typeof(b)) {
a = ""+a; b = ""+b; //If they have different types, convert them to strings
}
if (a < b) return -1;
else if (a > b) return 1;
else if (a >= b) return 0;
else return NaN;
}
}
}
function d3DescendingNull(a, b) {
if (b === null || b === undefined) {
if (a === null || a === undefined) return 0; // a == b == null
else return -1; // b==null a!=null
} else { // b!=null
if (a === null || a === undefined) return 1;
else {
// Both are non null
if (typeof(a)!==typeof(b)) {
a = ""+a; b = ""+b; //If they have different types, convert them to strings
}
if (a < b) return 1;
else if (a > b) return -1;
else if (a >= b) return 0;
else return NaN;
}
}
}
// A fake scale that uses only the first digits of a text to compute the color.
// Creates a list of all the possible first digits and uses a sequential scale to color based on such index
function scaleText(nullColor, digits = 1, defaultColorInterpolator) {
// const defaultColorInterpolator = "interpolateGreys" in d3 ? d3.interpolateGreys : interpolateGreys; // Hack to keep it working with d3.v4
let scale = scaleSequential(defaultColorInterpolator),
dRepresentativesCounts = map(), // Contains the counts for each letter/substrg
dRepresentativesIndexes = map();
// Computes the actual value, based on the index of the first digits in the domain
function compute(d) {
if (typeof(d)!==typeof("")) {
d = d + ""; // Force text
}
let ci = dRepresentativesIndexes.get(
d.slice(0, digits)
);
if (ci === undefined) {
console.log(
`scaleText Couldn't find index for ${d} did you call domain? Using ascii of first letter`
);
ci = d
// .slice(0, digits)
.charCodeAt(0);
}
return scale(ci) || nullColor;
}
function computeRepresentatives(data, doIndex = true) {
dRepresentativesCounts = map();
for (let v of data) {
//Initialize
if (!dRepresentativesCounts.has(v)) dRepresentativesCounts.set(v, 0);
//count+=1
dRepresentativesCounts.set(v, dRepresentativesCounts.get(v) + 1);
}
const ret = {
counts: dRepresentativesCounts
};
if (doIndex) {
// Compute the indexes of each representative
dRepresentativesIndexes = map();
let i = 0;
for (let r of dRepresentativesCounts.keys().sort()) {
dRepresentativesIndexes.set(r, i++);
}
ret.indexes = dRepresentativesIndexes;
}
return ret;
}
compute.digits = function(_) {
return arguments.length ? ((digits = _), compute) : digits;
};
compute.scale = function(_) {
return arguments.length ? ((scale = _), compute) : scale;
};
compute.domain = function(data) {
if (arguments.length) {
// Compute representatives for letters/substrings
computeRepresentatives(
data
// .filter(d => typeof(d) === typeof(""))
.map(d => (""+d).slice(0, digits))
);
scale.domain([0, dRepresentativesCounts.keys().length]);
return compute;
} else {
return scale.domain();
}
};
compute.computeRepresentatives = computeRepresentatives;
compute.__type = "text";
return compute;
}
// A fake scale that uses the ranked order for coloring
function scaleOrdered(nullColor, defaultColorInterpolator) {
let scale = scaleOrdinal();
// dRepresentativesCounts = d3.map(), // Contains the counts for each letter/substrg
// dRepresentativesIndexes = d3.map();
// Computes the actual value, based on the index of the first digits in the domain
function compute(d) {
if (d === undefined || d=== null) return nullColor;
else return scale(d);
}
function computeRepresentatives(data) {
// Sorting with d3 set converts to strings :(
// return d3.set(data).values().sort((a,b) => d3AscendingNull(a,b));
// Also convert to strings :(
// dValues = {};
// for (let v of data) {
// //Initialize
// if (dValues[v]===undefined) dValues[v]=0;
// //count+=1
// dValues[v]+=1;
// }
// const vals = [];
// for (let v in dValues) {
// vals.push(v);
// }
// return vals.sort();
const vals = [];
let prev = null;
for (let v of data.sort((a,b) => d3AscendingNull(a,b))) {
if (prev!==v) {
vals.push(v);
prev = v;
}
}
return vals;
}
compute.domain = function(data) {
if (arguments.length) {
// Compute representatives for letters/substrings
const values = computeRepresentatives(data);
scale.domain(values)
.range(values.map((_, i) => defaultColorInterpolator(i/values.length)));
return compute;
} else {
return scale.domain();
}
};
compute.computeRepresentatives = computeRepresentatives;
compute.__type = "ordered";
return compute;
}
// Returns a flat array with all the attributes in an object up to recursionLevel.
// Returns attributes as lists to avoid confusion with names containing dots
const getAttribsFromObjectRecursive = function(
obj,
recursionLevel = Infinity
) {
function helper(obj, recursionCount) {
var attr,
res = [];
for (attr in obj) {
if (
obj.hasOwnProperty(attr) &&
attr !== "__i" &&
attr !== "__seqId" &&
attr !== "selected"
) {
if (
recursionCount < recursionLevel &&
!Array.isArray(obj[attr]) &&
obj[attr] !== null &&
obj[attr] !== undefined &&
!(obj[attr] instanceof Date) && // Not a date
typeof obj[attr] === typeof {}
) {
// Recursive call on objects
res = res.concat(
helper(obj[attr], recursionCount + 1).map(a => [attr].concat(a))
);
} else {
res.push([attr]);
}
}
}
return res;
}
return helper(obj, 0);
};
function convertAttribToFn(attr) {
if (typeof attr === "string") {
attr = attr.split(".");
}
let fnName = attr.join("_");
// .replace(/\./g, "_"); // Try to get a better function name
// https://stackoverflow.com/questions/1661197/what-characters-are-valid-for-javascript-variable-names
// const validRegExp = /^(?!(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$)[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc0-9\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19b0-\u19c0\u19c8\u19c9\u19d0-\u19d9\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f]*$/;
const access = attr.map(a => `["${a}"]`).join(""); // a.b.c => ["a"]["b"]["c"]
let body = `return function ${fnName}(d) { try { return d${access} } catch (e) { return undefined }; };`;
try {
return new Function(body)();
} catch (e) {
// Try sanitizing the variable name
fnName = fnName.replace(/[^a-zA-Z0-9_-]/g, ""); // remove special characters
body = `return function ${fnName}(d) { try { return d${access} } catch (e) { return undefined }; };`;
return new Function(body)();
}
}
// Returns an array of strings or functions to access all the attributes in an object
function getAttribsFromObjectAsFn(obj, recursionLevel = Infinity) {
const attribs = getAttribsFromObjectRecursive(obj, recursionLevel);
return attribs.map(attr =>
attr.length > 1 ? convertAttribToFn(attr) : attr
);
}
// import * as d3 from "./../../node_modules/d3/dist/d3.js"; // Force react to use the es6 module
//eleId must be the ID of a context element where everything is going to be drawn
function navio(selection, _h) {
let nv = this || {},
data = [], //Contains the original data attributes
dataIs = [], //Contains only the indices to the data, is an array of arrays, one for each level
links = [],
visibleLinks = [],
dData = map(), // A hash for the data
// dAttribs = d3.map(),
attribsOrdered = [],
dAttribs = map(),
dSortBy = [], //contains which attribute to sort by on each column
dBrushes = [],
filtersByLevel = [], // The filters applied to each level
yScales = [],
xScale,
x,
height = _h !== undefined ? _h : 600,
colScales = map(),
levelScale,
svg,
canvas,
context,
tooltip,
tooltipElement,
tooltipCoords = { x: -50, y: -50 },
id = "__seqId",
updateCallback = function () {},
cursorSubstractData =
"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU0LjEgKDc2NDkwKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5jdXJzb3JTdWJzdHJhY3Q8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iY3Vyc29yU3Vic3RyYWN0IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBkPSJNOSwwLjUgTDcsMC41IEw3LDcgTDAuNSw3IEwwLjUsOSBMNyw5IEw3LDE1LjUgTDksMTUuNSBMOSw5IEwxNS41LDkgTDE1LjUsNyBMOSw3IEw5LDAuNSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHN0cm9rZT0iI0ZGRkZGRiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgICAgIDxyZWN0IGlkPSJSZWN0YW5nbGUiIGZpbGw9IiMwMDAwMDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE1LjAwMDAwMCwgMTUuMDAwMDAwKSByb3RhdGUoLTI3MC4wMDAwMDApIHRyYW5zbGF0ZSgtMTUuMDAwMDAwLCAtMTUuMDAwMDAwKSAiIHg9IjE0IiB5PSIxMSIgd2lkdGg9IjIiIGhlaWdodD0iOCI+PC9yZWN0PgogICAgPC9nPgo8L3N2Zz4=",
cursorAddData =
"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU0LjEgKDc2NDkwKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5jdXJzb3JBZGQ8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iY3Vyc29yQWRkIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBkPSJNOSwwLjUgTDcsMC41IEw3LDcgTDAuNSw3IEwwLjUsOSBMNyw5IEw3LDE1LjUgTDksMTUuNSBMOSw5IEwxNS41LDkgTDE1LjUsNyBMOSw3IEw5LDAuNSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHN0cm9rZT0iI0ZGRkZGRiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgICAgIDxwYXRoIGQ9Ik0xNiwxNCBMMTksMTQgTDE5LDE2IEwxNiwxNiBMMTYsMTkgTDE0LDE5IEwxNCwxNiBMMTEsMTYgTDExLDE0IEwxNCwxNCBMMTQsMTEgTDE2LDExIEwxNiwxNCBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIGZpbGw9IiMwMDAwMDAiPjwvcGF0aD4KICAgIDwvZz4KPC9zdmc+",
cursorData =
"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU0LjEgKDc2NDkwKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5jdXJzb3I8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iY3Vyc29yIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBkPSJNOSwwLjUgTDcsMC41IEw3LDcgTDAuNSw3IEwwLjUsOSBMNyw5IEw3LDE1LjUgTDksMTUuNSBMOSw5IEwxNS41LDkgTDE1LjUsNyBMOSw3IEw5LDAuNSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHN0cm9rZT0iI0ZGRkZGRiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgPC9nPgo8L3N2Zz4=";
// Default parameters
nv.x0 = 0; //Where to start drawing navio in x
nv.y0 = 100; //Where to start drawing navio in y, useful if your attrib names are too long
nv.maxNumDistictForCategorical = 10; // addAllAttribs uses this for deciding if an attribute is categorical (has less than nv.maxNumDistictForCategorical categories) or ordered
nv.maxNumDistictForOrdered = 90; // addAllAttribs uses this for deciding if an attribute is ordered (has less than nv.maxNumDistictForCategorical categories) or text
// use nv.maxNumDistictForOrdered = Infinity for never choosing Text
nv.howManyItemsShouldSearchForNotNull = 100; // How many rows should addAllAttribs search to decide guess an attribute type
nv.margin = 10; // Margin around navio
nv.levelsSeparation = 40; // Separation between the levels
nv.divisionsColor = "white"; // Border color for the divisions
nv.nullColor = "#ffedfd"; // Color for null values
nv.levelConnectionsColor = "rgba(205, 220, 163, 0.5)"; // Color for the conections between levels
nv.divisionsThreshold = 4; // What's the minimum row height needed to draw divisions
nv.fmtCounts = format(",.0d"); // Format used to display the counts on the bottom
nv.legendFont = "14px sans-serif"; // The font for the header
nv.linkColor = "#ccc"; // Color used for network links if provided with nv.links()
nv.nestedFilters = true; // Should navio use nested levels?
nv.showAttribTitles = true; // Show headers?
nv.attribWidth = 15; // Width of the columns
nv.attribRotation = -45; // Headers rotation
nv.attribFontSize = 13; // Headers font size
nv.attribFontSizeSelected = 32; // Headers font size when mouse over
nv.filterFontSize = 8; // Font size of the filters explanations on the bottom
nv.tooltipFontSize = 12; // Font size for the tooltip
nv.tooltipBgColor = "#b2ddf1"; // Font color for tooltip background
nv.tooltipMargin = 50; // How much to separate the tooltip from the cursor
nv.tooltipArrowSize = 10; // How big is the arrow on the tooltip
nv.addAllAttribsRecursionLevel = Infinity; // How many levels depth do we keep on adding nested attributes
nv.addAllAttribsIncludeObjects = false; // Should addAllAttribs include objects
nv.addAllAttribsIncludeArrays = false; // Should addAllAttribs include arrays
nv.digitsForText = 2; // How many digits to use for text attributes
// Necessary hack for supporting d3v4 and d3v5
nv.defaultColorInterpolator =
"interpolateBlues" in d3 ? interpolateBlues : interpolateBlues$1;
nv.defaultColorInterpolatorDate =
"interpolatePurples" in d3 ? interpolatePurples : interpolatePurples$1;
nv.defaultColorInterpolatorDiverging =
"interpolateBrBG" in d3 ? interpolateBrBG : interpolateBrBG$1;
nv.defaultColorInterpolatorOrdered =
"interpolateOranges" in d3 ? interpolateOranges : interpolateOranges$1;
nv.defaultColorInterpolatorText =
"interpolateGreys" in d3 ? interpolateGreys : interpolateGreys$1;
nv.defaultColorRangeBoolean = ["#a1d76a", "#e9a3c9", "white"]; //true false null
nv.defaultColorRangeSelected = ["white", "#b5cf6b"];
nv.defaultColorCategorical = schemeCategory10;
function nozoom() {
event.preventDefault();
}
function initTooltipPopper() {
if (tooltipElement) tooltipElement.remove();
selectAll("._nv_popover").remove();
tooltipElement = select("body")
.append("div")
.attr("class", "_nv_popover")
// .style("text-shadow", "0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff")
.style("pointer-events", "none")
.style("font-family", "sans-serif")
.style("font-size", nv.tooltipFontSize)
.style("text-align", "center")
.style("background", nv.tooltipBgColor)
.style("position", "relative")
.style("color", "black")
.style("z-index", 4)
.style("border-radius", "4px")
.style("box-shadow", "0 0 2px rgba(0,0,0,0.5)")
.style("padding", "10px")
.style("text-align", "center")
.style("display", "none");
tooltipElement.append("style").attr("scoped", "").text(`
[x-arrow] {
width: 0;
height: 0;
border-style: solid;
position: absolute;
margin: ${nv.tooltipArrowSize}px;
border-color: ${nv.tooltipBgColor}
}
._nv_popover[x-placement="left"] {
margin-right: ${nv.tooltipArrowSize + nv.tooltipMargin}px;
}
._nv_popover[x-placement="left"] [x-arrow] {
border-width: ${nv.tooltipArrowSize}px 0 ${nv.tooltipArrowSize}px ${
nv.tooltipArrowSize
}px;
border-top-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
right: -${nv.tooltipArrowSize}px;
top: calc(50% - ${nv.tooltipArrowSize}px);
margin-left: 0;
margin-right: 0;
}
._nv_popover[x-placement="right"] {
margin-left: ${nv.tooltipArrowSize + nv.tooltipMargin}px;
}
._nv_popover[x-placement="right"] [x-arrow] {
border-width: ${nv.tooltipArrowSize}px ${nv.tooltipArrowSize}px ${
nv.tooltipArrowSize
}px 0;
border-left-color: transparent;
border-top-color: transparent;
border-bottom-color: transparent;
left: -${nv.tooltipArrowSize}px;
top: calc(50% - ${nv.tooltipArrowSize}px);
margin-left: 0;
margin-right: 0;
}
._nv_popover[x-placement="bottom"] {
margin-top: ${nv.tooltipArrowSize + nv.tooltipMargin}px;
}
._nv_popover[x-placement="bottom"] [x-arrow] {
border-width: 0 ${nv.tooltipArrowSize}px ${nv.tooltipArrowSize}px ${
nv.tooltipArrowSize
}px;
border-left-color: transparent;
border-right-color: transparent;
border-top-color: transparent;
top: -${nv.tooltipArrowSize}px;
left: calc(50% - ${nv.tooltipArrowSize}px);
margin-top: 0;
margin-bottom: 0;
}
._nv_popover[x-placement="top"] {
margin-bottom: ${nv.tooltipArrowSize + nv.tooltipMargin}px;
}
._nv_popover[x-placement="top"] [x-arrow] {
border-width: ${nv.tooltipArrowSize}px ${nv.tooltipArrowSize}px 0 ${
nv.tooltipArrowSize
}px;
border-left-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
bottom: -${nv.tooltipArrowSize}px;
left: calc(50% - ${nv.tooltipArrowSize}px);
margin-top: 0;
margin-bottom: 0;
}
`);
tooltipElement.append("div").attr("class", "tool_id");
tooltipElement
.append("div")
.attr("class", "tool_value_name")
.style("font-weight", "bold")
.style("font-size", "120%");
tooltipElement
.append("div")
.attr("class", "tool_value_val")
.style("max-width", "400px")
.style("max-height", "5.5em")
.style("text-align", "left")
.style("overflow", "hidden")
.style("font-size", "90%");
tooltipElement
.append("div")
.style("font-size", "70%")
.style("margin-top", "10px")
.style("text-align", "left")
.style("color", "#777")
.html(`<div>Click to filter a value (<strong>alt</strong> for negative filter).<br>
Drag for filtering a range.<br> <strong>shift</strong> click for appending to the filters</div>`);
tooltipElement.append("div").attr("x-arrow", "");
const ref = {
getBoundingClientRect: () => {
const svgBR = svg.node().getBoundingClientRect();
return {
top: tooltipCoords.y + svgBR.top,
right: tooltipCoords.x + svgBR.left,
bottom: tooltipCoords.y + svgBR.top,
left: tooltipCoords.x + svgBR.left,
width: 0,
height: 0,
};
},
clientWidth: 0,
clientHeight: 0,
};
// const ref= {
// getBoundingClientRect: () => {
// return {
// top: tooltipCoords.y,
// right: tooltipCoords.x,
// bottom: tooltipCoords.y,
// left: tooltipCoords.x,
// width: 0,
// height: 0,
// };
// },
// clientWidth: 0,
// clientHeight: 0,
// };
tooltip = new Popper(ref, tooltipElement.node(), {
placement: "right",
// modifiers: {
// preventOverflow: {
// boundariesElement: selection.node(),
// },
// },
});
}
function changeCursorOnKey() {
if (event.key === "Alt") {
selectAll(".overlay")
.attr("cursor", `url(${cursorSubstractData}) 8 8, zoom-out`)
.style("cursor", `url(${cursorSubstractData}) 8 8, zoom-out`);
// console.log("Alt!");
} else if (event.key === "Shift") {
selectAll(".overlay")
.attr("cursor", `url(${cursorAddData}) 8 8, zoom-in`)
.style("cursor", `url(${cursorAddData}) 8 8, zoom-in`);
// console.log("Alt!");
} else {
selectAll(".overlay").style(
"cursor",
`url(${cursorData}) 8 8, crosshair`
);
}
if (event.type === "keyup")
selectAll(".overlay").style(
"cursor",
`url(${cursorData}) 8 8, crosshair`
);
// console.log("key", d3.event.type);
}
function init() {
// Try to support strings and elements
selection =
typeof selection === typeof "" ? select(selection) : selection;
selection =
selection.selectAll === undefined ? select(selection) : selection;
selection.selectAll("*").remove();
const divNavio = selection
.on("touchstart", nozoom)
.on("touchmove", nozoom)
.style("height", height + "px")
.attr("class", "navio")
.append("div")
.style("overflow-x", "auto")
.style("position", "relative");
divNavio.append("canvas");
svg = divNavio
.append("svg")
.style("overflow", "visible")
.style("position", "absolute")
// .style("cursor", `url(${cursorData}) 8 8, crosshair`)
.style("z-index", 3)
.style("top", 0)
.style("left", 0);
divNavio
.append("div")
.attr("class", "explanations")
.style("overflow", "visible")
.style("position", "absolute")
.style("z-index", 5)
.style("top", nv.margin + "px")
.style("left", nv.margin + "px");
// TODO: Try a more localized selection
select("body")
.on("keydown", changeCursorOnKey)
.on("keyup", changeCursorOnKey);
svg.append("g").attr("class", "attribs");
initTooltipPopper();
svg
.append("g")
.attr("id", "closeButton")
.style("fill", "white")
.style("stroke", "black")
.style("display", "none")
.append("path")
.call(function (sel) {
var crossSize = 7,
path$$1 = path(); // Draw a cross and a circle
path$$1.moveTo(0, 0);
path$$1.lineTo(crossSize, crossSize);
path$$1.moveTo(crossSize, 0);
path$$1.lineTo(0, crossSize);
path$$1.moveTo(crossSize * 1.2 + crossSize / 2, crossSize / 2);
path$$1.arc(crossSize / 2, crossSize / 2, crossSize * 1.2, 0, Math.PI * 2);
sel.attr("d", path$$1.toString());
})
.on("click", () => deleteSubsequentLevels()); //delete last level
xScale = scaleBand()
// .rangeBands([0, nv.attribWidth], 0.1, 0);
.range([0, nv.attribWidth])
.round(true)
.paddingInner(0.1)
.paddingOuter(0);
levelScale = scaleBand().round(true);
colScales = map();
x = function (val, level) {
return levelScale(level) + xScale(val);
};
canvas = selection.select("canvas").node();
// canvas.style.position = "absolute";
canvas.style.top = canvas.offsetTop + "px";
canvas.style.left = canvas.offsetLeft + "px";
// canvas.style.width = "150px";
canvas.style.height = height + "px";
const scale = window.devicePixelRatio;
// canvas.width = width * scale;
canvas.height = height * scale;
context = canvas.getContext("2d");
context.scale(scale, scale);
context.imageSmoothingEnabled = context.mozImageSmoothingEnabled = context.webkitImageSmoothingEnabled = false;
context.globalCompositeOperation = "source-over";
}
function showLoading(ele) {
select(ele).style("cursor", "progress");
svg.style("cursor", "progress");
}
function hideLoading(ele) {
// d3.select("._nv_loading").remove();
select(ele).style("cursor", null);
svg.style("cursor", null);
}
function deferEvent(cbk) {
return function (d, i, all) {
showLoading(this);
requestAnimationFrame(() => {
cbk(d, i, all);
hideLoading(this);
});
};
}
function invertOrdinalScale(scale, x) {
// Taken from https://bl.ocks.org/shimizu/808e0f5cadb6a63f28bb00082dc8fe3f
// custom invert function
var domain = scale.domain();
var range$$1 = scale.range();
var qScale = scaleQuantize().domain(range$$1).range(domain);
return qScale(x);
}
function updateSorting(levelToUpdate, _dataIs) {
if (!dSortBy.hasOwnProperty(levelToUpdate)) {
return;
}
_dataIs = _dataIs !== undefined ? _dataIs : dataIs;
var before = performance.now();
const sort = dSortBy[levelToUpdate];
_dataIs[levelToUpdate].sort(function (a, b) {
return sort.desc
? d3DescendingNull(
getAttrib(data[a], sort.attrib),
getAttrib(data[b], sort.attrib)
)
: d3AscendingNull(
getAttrib(data[a], sort.attrib),
getAttrib(data[b], sort.attrib)
);
});
assignIndexes(_dataIs[levelToUpdate], levelToUpdate);
var after = performance.now();
}
function onSortLevel(d) {
if (event && event.defaultPrevented) return; // dragged
dSortBy[d.level] = {
attrib: d.attrib,
desc:
dSortBy[d.level] !== undefined && dSortBy[d.level].attrib === d.attrib
? !dSortBy[d.level].desc
: false,
};
deleteObsoleteFiltersFromLevel(d.level + 1);
updateSorting(d.level);
removeBrushOnLevel(d.level);
nv.updateData(dataIs, colScales, {
levelsToUpdate: [d.level],
});
updateCallback(nv.getVisible());
}
function getAttrib(item, attrib) {
if (typeof attrib === "function") {
try {
return attrib(item);
} catch (e) {
// console.log("navio error getting attrib with item ", item, " attrib ", attrib, "error", e);
return undefined;
}
} else {
return item[attrib];
}
}
function getAttribName(attrib) {
if (typeof attrib === "function") {
return attrib.name ? attrib.name : attrib;
} else {
return attrib;
}
}
function drawItem(item, level) {
var attrib, i, y;
context.save();
for (i = 0; i < attribsOrdered.length; i++) {
attrib = attribsOrdered[i];
const val = getAttrib(item, attrib);
const attribName = getAttribName(attrib);
y = Math.round(yScales[level](item[id]) + yScales[level].bandwidth() / 2);
// y = yScales[level](item[id]) + yScales[level].bandwidth()/2;
context.beginPath();
context.moveTo(Math.round(x(attribName, level)), y);
context.lineTo(Math.round(x(attribName, level) + xScale.bandwidth()), y);
context.lineWidth = Math.ceil(yScales[level].bandwidth());
// context.lineWidth = 1;
context.strokeStyle =
val === undefined || val === null || val === "" || val === "none"
? nv.nullColor
: colScales.get(attrib)(val);
context.stroke();
// TODO get this out
//If the range bands are tick enough draw divisions
if (yScales[level].bandwidth() > nv.divisionsThreshold * 2) {
var yLine = Math.round(yScales[level](item[id]));
// y = yScales[level](item[id])+yScales[level].bandwidth()/2;
context.beginPath();
context.moveTo(x(attribName, level), yLine);
context.lineTo(x(attribName, level) + xScale.bandwidth(), yLine);
context.lineWidth = 1;
// context.lineWidth = 1;
context.strokeStyle = nv.divisionsColor;
context.stroke();
}
}
context.restore();
} // drawItem
function drawLevelBorder(i) {
context.save();
context.beginPath();
context.rect(
levelScale(i),
yScales[i].range()[0] - 1,
xScale.range()[1] + 1,
yScales[i].range()[1] + 2 - yScales[i].range()[0]
);
context.strokeStyle = "black";
context.lineWidth = 1;
context.stroke();
context.restore();
}
function removeBrushOnLevel(lev) {
if (lev < 0) return;
select("#level" + lev)
.selectAll(".brush")
.call(dBrushes[lev].move, null);
}
function removeAllBrushesBut(but) {
for (var lev = 0; lev < dataIs.length; lev += 1) {
if (lev === but) continue;
removeBrushOnLevel(lev);
}
}
// Assigns the indexes on the new level data
function assignIndexes(dataIsToUpdate, level) {
for (var j = 0; j < dataIsToUpdate.length; j++) {
data[dataIsToUpdate[j]].__i[level] = j;
}
}
// Some actions will make obsolete certain filters, such as a resort on a previous level
// with range filters
function deleteObsoleteFiltersFromLevel(level) {
for (let l = level; l < filtersByLevel.length; l++) {
filtersByLevel[l] = filtersByLevel[l].filter(
(f) => f.type === "value" || f.type === "negativeValue"
);
}
}
// Applies the filters for the selected level, using the passed data if any
function applyFilters(level, _dataIs) {
let before, after;
_dataIs = _dataIs !== undefined ? _dataIs : dataIs;
before = performance.now();
// Check if each item fits on any filter
const negFilters = filtersByLevel[level].filter(
(f) => f.type === "negativeValue" || f.type === "negativeRange"
),
posFilters = filtersByLevel[level].filter(
(f) => f.type !== "negativeValue" || f.type !== "negativeRange"
);
var filteredData = _dataIs[level].filter((d) => {
// OR of positives, AND of negatives
return (data[d].selected =
posFilters.reduce((p, f) => p || f.filter(data[d]), false) &&
negFilters.reduce((p, f) => p && f.filter(data[d]), true));
// // Check if a possitive filter apply
// for (let filter of posFilters) {
// if (filter.filter(data[d])) {
// data[d].selected = true;
// // break;
// return data[d].selected;
// }
// }
// for (let filter of negFilters) {
// if (filter.filter(data[d])) {
// data[d].selected = false;
// return data[d].selected;
// }
// }
// return true;
});
// var filteredData = filtersByLevel[level].reduce(reduceFilters, dataIs[level]);
after = performance.now();
return filteredData;
}
function getLastLevelFromFilters() {
let lastLevel = 0;
for (let i = 0; i < filtersByLevel.length; i++) {
lastLevel = i;
if (!filtersByLevel[i] || !filtersByLevel[i].length) {
break;
}
}
return lastLevel;
}
function applyFiltersAndUpdate(fromLevel) {
const lastLevel = getLastLevelFromFilters();
// Start from the previous data
let newData = dataIs;
for (let level = fromLevel; level <= lastLevel; level++) {
// We don't have filters for this level, delete subsequent levels
if (
!filtersByLevel.hasOwnProperty(level) ||
!filtersByLevel[level].length
) {
newData = deleteSubsequentLevels(level + 1, newData, {
shouldUpdate: false,
});
break;
}
// else apply filters
let filteredData = applyFilters(level, newData);
//Assign the index
assignIndexes(filteredData, level + 1);
if (filteredData.length === 0) ;
// newData = dataIs.slice(0,level+1);
if (nv.nestedFilters) {
// newData.push(filteredData);
newData[level + 1] = filteredData;
}
// Update sortings of the next level
updateSorting(level + 1);
}
// Update all the levels
nv.updateData(newData, colScales, {
shouldDrawBrushes: true,
levelsToUpdate: range(fromLevel, newData.length), // Range is not inclusive so is not length-1
});
updateCallback(nv.getVisible());
}
function updateBrushes(d, level) {
dBrushes[level] = brushY()
.extent([
[x(xScale.domain()[0], level), yScales[level].range()[0]],
[
x(xScale.domain()[xScale.domain().length - 1], level) +
xScale.bandwidth() * 1.1,
yScales[level].range()[1],
],
])
.on("brush", brushed)
.on("end", onSelectByRange);
var _brush = select(this)
.selectAll(".brush")
.data([
{
data: d.map((index) => data[index]),
level: level,
},
]);
_brush
.enter()
.merge(_brush)
.append("g")
.on("mousemove", onMouseOver)
.on("click", onSelectByValue)
.on("mouseout", onMouseOut)
.attr("class", "brush")
.call(dBrushes[level])
.selectAll("rect")
.attr(
"width",
x(xScale.domain()[xScale.domain().length - 1], level) +
xScale.bandwidth() * 1.1
);
_brush.exit().remove();
function brushed() {
if (!event.sourceEvent) return; // Only transition after input.
if (!event.selection) {
// return;
// d3.event.preventDefault();
// onSelectByValueFromCoords(d3.event.sourceEvent.clientX, d3.event.sourceEvent.clientY);
return; // Ignore empty selections.
}
const clientX = event.sourceEvent.clientX,
clientY = event.sourceEvent.clientY,
xOnWidget = event.sourceEvent.offsetX,
yOnWidget = event.sourceEvent.offsetY;
showTooptip(xOnWidget, yOnWidget, clientX, clientY, level);
}
function onSelectByRange() {
if (!event.sourceEvent) return; // Only transition after input.
if (!event.selection) {
// return;
// d3.event.preventDefault();
// onSelectByValueFromCoords(d3.event.sourceEvent.clientX, d3.event.sourceEvent.clientY);
return; // Ignore empty selections.
}
showLoading(this);
removeAllBrushesBut(level);
var before = performance.now();
var brushed = event.selection;
var // first = dData.get(invertOrdinalScale(yScales[level], brushed[0] -yScales[level].bandwidth())),
first = dData.get(invertOrdinalScale(yScales[level], brushed[0])),
// last = dData.get(invertOrdinalScale(yScales[level], brushed[1] -yScales[level].bandwidth()))
last = dData.get(invertOrdinalScale(yScales[level], brushed[1]));
let newFilter;
if (event.sourceEvent.altKey) {
newFilter = new FilterByRangeNegative({
first,
last,
level: level,
itemAttr: dSortBy[level] ? dSortBy[level].attrib : "__seqId",
getAttrib,
getAttribName,
});
} else {
newFilter = new FilterByRange({
first,
last,
level: level,
itemAttr: dSortBy[level] ? dSortBy[level].attrib : "__seqId",
getAttrib,
getAttribName,
});
}
if (event.sourceEvent.shiftKey) {
// First filter, create the list
if (!filtersByLevel.hasOwnProperty(level)) {
filtersByLevel[level] = [];
}
// Append the filter
filtersByLevel[level].push(newFilter);
} else {
// Remove previous filters
filtersByLevel[level] = [newFilter];
}
// A range filter on a former level makes range filters obsolete in subsequent levels
deleteObsoleteFiltersFromLevel(level + 1);
applyFiltersAndUpdate(level);
var after = performance.now();
hideLoading(this);
} // onSelectByRange
function onSelectByValue() {
showLoading(this);
var clientY = mouse(event.target)[1],
clientX = mouse(event.target)[0];
onSelectByValueFromCoords(clientX, clientY);
hideLoading(this);
}
function onSelectByValueFromCoords(clientX, clientY) {
removeAllBrushesBut(-1); // Remove all brushes
const before = performance.now();
const itemId = invertOrdinalScale(yScales[level], clientY);
const after = performance.now();
let itemAttr = invertOrdinalScale(xScale, clientX - levelScale(level));
if (itemAttr === undefined) {
console.log(
`navio.selectByValue: error, couldn't find attr in coords ${
(clientY)
}`
);
return;
}
itemAttr = dAttribs.get(itemAttr);
const sel = dData.get(itemId);
let newFilter;
if (event.altKey) {
newFilter = new FilterByValueDifferent({
sel,
itemAttr,
getAttrib,
getAttribName,
});
} else {
newFilter = new FilterByValue({
sel,
itemAttr,
getAttrib,
getAttribName,
});
}
if (event.shiftKey) {
// First filter, create the list
if (!filtersByLevel.hasOwnProperty(level)) {
filtersByLevel[level] = [];
}
// Append the filter
filtersByLevel[level].push(newFilter);
} else {
// Remove previous filters
filtersByLevel[level] = [newFilter];
}
// A filter on a former level makes range filters obsolete in subsequent levels
deleteObsoleteFiltersFromLevel(level + 1);
applyFiltersAndUpdate(level);
}
} // updateBrushes
function showTooptip(xOnWidget, yOnWidget, clientX, clientY, level) {
let itemId;
try {
itemId = invertOrdinalScale(yScales[level], yOnWidget);
} catch (e) {
return;
}
let itemAttr = invertOrdinalScale(xScale, xOnWidget - levelScale(level));
const d = dData.get(itemId);
itemAttr = dAttribs.get(itemAttr);
if (!d || d === undefined) {
console.log("Couldn't find datum for tooltip y", yOnWidget, d);
return;
}
tooltipCoords.x = xOnWidget;
tooltipCoords.y = yOnWidget;
tooltipElement.select(".tool_id").text(itemId);
tooltipElement.select(".tool_value_name").text(getAttribName(itemAttr));
tooltipElement.select(".tool_value_val").text(getAttrib(d, itemAttr));
tooltipElement.style("display", "initial");
tooltip.scheduleUpdate();
// if ( DEBUG ) console.log("Mouse over", d);
}
function onMouseOver(overData) {
const xOnWidget = mouse(event.target)[0],
yOnWidget = mouse(event.target)[1],
clientX = event.clientX,
clientY = event.clientY;
// if (d3.event.altKey) {
// d3.selectAll(".overlay").style("cursor", "zoom-out");
// console.log("Alt!");
// } else {
// d3.selectAll(".overlay").style("cursor", `url(${cursorData}) 8 8, crosshair`);
// }
// // console.log("key");
if (!overData.data || overData.data.length === 0) {
return;
}
// if (DEBUG) console.log("onMouseOver", xOnWidget, yOnWidget, clientY, d3.event.pageY, d3.event.offsetY, d3.event);
showTooptip(xOnWidget, yOnWidget, clientX, clientY, overData.level);
}
function onMouseOut() {
tooltipCoords.x = -200;
tooltipCoords.y = -200;
tooltipElement.style("display", "none");
tooltip.scheduleUpdate();
// svg.select(".nvTooltip")
// .attr("transform", "translate(" + (-200) + "," + (-200) + ")")
// .call(function (tool) {
// tool.select(".tool_id")
// .text("");
// tool.select(".tool_value_name")
// .text("");
// tool.select(".tool_value_val")
// .text("");
// });
}
function drawCounts(levelOverlay, levelOverlayEnter) {
levelOverlayEnter
.append("text")
.merge(levelOverlay.select("text.numNodesLabel"))
.attr("class", "numNodesLabel")
.style("font-family", "sans-serif")
.style("pointer-events", "none")
.attr("y", function (_, i) {
return yScales[i].range()[1] + 15;
})
.attr("x", function (_, i) {
return levelScale(i);
})
.text(function (d) {
return nv.fmtCounts(d.length);
});
}
function drawFilterExplanationsHTML(levelOverlay, levelOverlayEnter) {
const lastAttrib = xScale.domain()[xScale.domain().length - 1],
rightBorder = (level) => x(lastAttrib, level) + xScale.bandwidth() + 2;
const filterExps = selection
.select("div.explanations")
.selectAll("div.filterExplanation")
.data(dataIs);
const filterExpEnter = filterExps
.enter()
.append("div")
.attr("class", "filterExplanation")
.merge(filterExps)
.style("position", "absolute")
.style("top", "0")
.style("left", "0")
.style("min-width", "200px")
.style(
"transform",
(_, i) =>
`translate(${rightBorder(i)}px, ${
yScales[i].range()[1] + nv.filterFontSize * 1.2
}px)`
);
const filterExpTexts = filterExpEnter
// .append("div")
// .attr("class", "filterExplanationText")
.merge(filterExps.select(".filterExplanation"))
.style("font-size", nv.filterFontSize + "pt")
.selectAll("div")
.data((_, i) =>
filtersByLevel[i]
? filtersByLevel[i].map((f) => {
f.level = i;
return f;
})
: []
);
filterExpTexts
.enter()
.append("div")
.merge(filterExpTexts)
// .attr("dy", nv.filterFontSize * 1.2 + 7)
// .attr("x", 0)
.style("cursor", "not-allowed")
.text((f) => "\u24CD " + f.toStr())
.on("click", (f, i) => {
console.log("Click remove filter", i, f);
filtersByLevel[f.level].splice(i, 1);
applyFiltersAndUpdate(f.level);
});
filterExpTexts.exit().remove();
filterExps.exit().remove();
}
function drawAttribHeaders(attribOverlay, attribOverlayEnter) {
if (nv.showAttribTitles) {
attribOverlayEnter
.append("text")
.merge(attribOverlay.select("text"))
.style("cursor", "point")
.style("-webkit-user-select", "none")
.style("-moz-user-select", "none")
.style("-ms-user-select", "none")
.style("user-select", "none")
.text(function (d) {
return d.attrib === "__seqId"
? "sequential Index"
: d.name +
(dSortBy[d.level] !== undefined &&
dSortBy[d.level].attrib === d.attrib
? dSortBy[d.level].desc
? " \u2193"
: " \u2191"
: "");
})
.attr("x", xScale.bandwidth() / 2)
.attr("y", 0)
.style("font-weight", function (d) {
return dSortBy[d.level] !== undefined &&
dSortBy[d.level].attrib === d.attrib
? "bolder"
: "normal";
})
.style("font-family", "sans-serif")
.style("font-size", function () {
// make it grow ?
// if (dSortBy[d.level]!==undefined &&
// dSortBy[d.level].attrib === d.attrib )
// d3.select(this).dispatch("mousemove");
return Math.min(nv.attribFontSize, nv.attribWidth) + "px";
})
.on("click", deferEvent(onSortLevel))
.call(
drag()
.container(attribOverlayEnter.merge(attribOverlay).node())
.on("start", attribDragstarted)
.on("drag", attribDragged)
.on("end", attribDragended)
)
.on("mousemove", function () {
var sel = select(this);
sel =
sel.transition !== undefined ? sel.transition().duration(150) : sel;
sel.style("font-size", nv.attribFontSizeSelected + "px");
})
.on("mouseout", function () {
var sel = select(this);
sel =
sel.transition !== undefined ? sel.transition().duration(150) : sel;
sel.style(
"font-size",
Math.min(nv.attribFontSize, nv.attribWidth) + "px"
);
})
.attr("transform", `rotate(${nv.attribRotation})`);
} // if (nv.showAttribTitles) {
}
function drawAttributesHolders(levelOverlay, levelOverlayEnter) {
var attribs = attribsOrdered;
var attribOverlay = levelOverlayEnter
.merge(levelOverlay)
.selectAll(".attribOverlay")
.data(function (_, i) {
return attribs.map(function (a) {
return {
attrib: a,
name: getAttribName(a),
level: i,
};
});
});
var attribOverlayEnter = attribOverlay
.enter()
.append("g")
.attr("class", "attribOverlay")
.style("cursor", "pointer");
attribOverlayEnter
.merge(attribOverlay)
.attr(
"transform",
(d) =>
`translate(${x(d.name, d.level)}, ${yScales[d.level].range()[0]})`
);
attribOverlayEnter
.append("rect")
.merge(attribOverlay.select("rect"))
.attr("fill", "none")
// .style("opacity", "0.1")
.attr("x", 0)
.attr("y", 0)
.attr("width", function () {
return xScale.bandwidth() * 1.1;
})
.attr("height", function (d) {
return yScales[d.level].range()[1] - yScales[d.level].range()[0];
});
drawAttribHeaders(attribOverlay, attribOverlayEnter);
attribOverlay.exit().remove();
}
function drawBrushes(recomputeBrushes) {
var levelOverlay = svg
.select(".attribs")
.selectAll(".levelOverlay")
.data(dataIs);
var levelOverlayEnter = levelOverlay.enter().append("g");
levelOverlayEnter.attr("class", "levelOverlay").attr("id", function (d, i) {
return "level" + i;
});
// Bugfix: when adding all attribs we need to update the brush
if (recomputeBrushes) {
levelOverlayEnter.merge(levelOverlay).each(updateBrushes);
} else {
levelOverlayEnter.each(updateBrushes);
}
drawAttributesHolders(levelOverlay, levelOverlayEnter);
drawCounts(levelOverlay, levelOverlayEnter);
// drawFilterExplanations(levelOverlay, levelOverlayEnter);
drawFilterExplanationsHTML(levelOverlay, levelOverlayEnter);
levelOverlay.exit().remove();
} // drawBrushes
function attribDragstarted(d) {
if (!event.sourceEvent.shiftKey) return;
select(this.parentNode).attr("transform", function (d) {
return (
"translate(" +
(event.x + nv.attribFontSize / 2) +
"," +
yScales[d.level].range()[0] +
")"
);
});
}
function attribDragged() {
if (!event.sourceEvent.shiftKey) return;
select(this.parentNode).attr("transform", function (d) {
return (
"translate(" +
(event.x + nv.attribFontSize / 2) +
"," +
yScales[d.level].range()[0] +
")"
);
});
}
function attribDragended(d) {
if (!event.sourceEvent.shiftKey) return;
let attrDraggedInto = invertOrdinalScale(
xScale,
event.x + nv.attribFontSize / 2 - levelScale(d.level)
);
attrDraggedInto = dAttribs.get(attrDraggedInto);
var pos;
select(this.parentNode).attr("transform", function (d) {
return (
"translate(" +
x(d.name, d.level) +
"," +
yScales[d.level].range()[0] +
")"
);
});
if (attrDraggedInto !== d.attrib) {
pos = attribsOrdered.indexOf(attrDraggedInto);
moveAttrToPos(d.attrib, pos);
nv.updateData(dataIs);
}
}
function drawCloseButton() {
var maxLevel = dataIs.length - 1;
svg
.select("#closeButton")
.style("display", dataIs.length === 1 ? "none" : "block")
.attr(
"transform",
"translate(" +
(levelScale(maxLevel) +
levelScale.bandwidth() -
nv.levelsSeparation +
15) +
"," +
yScales[maxLevel].range()[0] +
")"
);
}
// Links between nodes
function drawLink(link) {
var lastAttrib = xScale.domain()[xScale.domain().length - 1],
rightBorder = x(lastAttrib, dataIs.length - 1) + xScale.bandwidth() + 2,
ys =
yScales[dataIs.length - 1](link.source[id]) +
yScales[dataIs.length - 1].bandwidth() / 2,
yt =
yScales[dataIs.length - 1](link.target[id]) +
yScales[dataIs.length - 1].bandwidth() / 2,
miny = Math.min(ys, yt),
maxy = Math.max(ys, yt),
midy = maxy - miny;
context.moveTo(rightBorder, miny); //starting point
context.quadraticCurveTo(
rightBorder + midy / 6,
miny + midy / 2, // mid point
rightBorder,
maxy // end point
);
}
function drawLinks() {
if (!links.length) return;
context.save();
context.beginPath();
context.strokeStyle = nv.linkColor;
context.globalAlpha = Math.min(
1,
Math.max(0.1, 1000 / links[links.length - 1].length)
); // More links more transparency
// context.lineWidth = 0.5;
for (let link of visibleLinks) {
drawLink(link);
}
// visibleLinks.forEach(drawLink);
context.stroke();
context.restore();
}
function drawLine(points, width, color, close) {
context.beginPath();
for (let i = 0; i < points.length; i++) {
const p = points[i];
if (i === 0) {
context.moveTo(p.x, p.y);
} else {
context.lineTo(p.x, p.y);
}
}
context.lineWidth = width;
if (close) {
context.fillStyle = color;
context.closePath();
context.fill();
} else {
context.strokeStyle = color;
context.stroke();
}
}
function drawLevelConnections(level) {
if (level <= 0) {
return;
}
for (let item of dataIs[level].representatives) {
// Compute the yPrev by calculating the index of the corresponding representative
var iOnPrev = dData.get(data[item][id]).__i[level - 1];
var iRep = Math.floor(
iOnPrev - (iOnPrev % dataIs[level - 1].itemsPerpixel)
);
// if (DEBUG) console.log("i rep = "+ iRep);
// if (DEBUG) console.log(data[level-1][iRep]);
// if (DEBUG) console.log(yScales[level-1](data[level-1][iRep][id]));
var locPrevLevel = {
x: levelScale(level - 1) + xScale.range()[1],
y: yScales[level - 1](data[dataIs[level - 1][iRep]][id]),
};
var locLevel = {
x: levelScale(level),
y: yScales[level](data[item][id]),
};
var points = [
locPrevLevel,
{ x: locPrevLevel.x + nv.levelsSeparation * 0.3, y: locPrevLevel.y },
{ x: locLevel.x - nv.levelsSeparation * 0.3, y: locLevel.y },
locLevel,
{ x: locLevel.x, y: locLevel.y + yScales[level].bandwidth() },
{
x: locLevel.x - nv.levelsSeparation * 0.3,
y: locLevel.y + yScales[level].bandwidth(),
},
{
x: locPrevLevel.x + nv.levelsSeparation * 0.3,
y: locPrevLevel.y + yScales[level - 1].bandwidth(),
},
{
x: locPrevLevel.x,
y: locPrevLevel.y + yScales[level - 1].bandwidth(),
},
locPrevLevel,
];
drawLine(points, 1, nv.levelConnectionsColor);
drawLine(points, 1, nv.levelConnectionsColor, true);
}
}
function computeRepresentatives(levelToUpdate) {
let representatives = [];
if (dataIs[levelToUpdate].length > height) {
const itemsPerpixel = Math.max(
Math.floor(dataIs[levelToUpdate].length / (height * 2)),
1
);
dataIs[levelToUpdate].itemsPerpixel = itemsPerpixel;
for (let i = 0; i < dataIs[levelToUpdate].length; i += itemsPerpixel) {
representatives.push(dataIs[levelToUpdate][i]);
}
} else {
dataIs[levelToUpdate].itemsPerpixel = 1;
representatives = dataIs[levelToUpdate];
}
dataIs[levelToUpdate].representatives = representatives;
return representatives;
}
function updateColorDomains() {
// colScales = d3.map();
for (let attrib of attribsOrdered) {
if (attrib === "selected") continue;
var scale = colScales.get(attrib);
if (scale.__type === "seq" || scale.__type === "date") {
scale.domain(
extent(
dataIs[0].map(function (i) {
return getAttrib(data[i], attrib);
})
)
); //TODO: make it compute it based on the local range
} else if (scale.__type === "div") {
const [min$$1, max] = extent(
dataIs[0].map(function (i) {
return getAttrib(data[i], attrib);
})
);
const absMax = Math.max(-min$$1, max); // Assumes diverging point on 0
scale.domain([-absMax, absMax]);
} else if (scale.__type === "text" || scale.__type === "ordered") {
scale.domain(dataIs[0].map((i) => getAttrib(data[i], attrib)));
}
colScales.set(getAttribName(attrib), scale);
}
}
function updateScales(opts) {
let { levelsToUpdate, shouldUpdateColorDomains } = opts || {};
const before = performance.now();
const lastLevel = dataIs.length - 1;
levelsToUpdate =
levelsToUpdate !== undefined ? levelsToUpdate : [lastLevel];
shouldUpdateColorDomains =
shouldUpdateColorDomains !== undefined ? shouldUpdateColorDomains : false;
yScales.splice(lastLevel + 1, yScales.length);
for (let levelToUp of levelsToUpdate) {
yScales[levelToUp] = scaleBand()
.range([nv.y0, height - nv.margin - 30])
.paddingInner(0.0)
.paddingOuter(0);
// Compute Representatives
const representatives = computeRepresentatives(levelToUp);
// Update x and y scales
yScales[levelToUp].domain(
representatives.map(function (rep) {
return data[rep][id];
})
);
}
xScale
.domain(attribsOrdered.map((d) => getAttribName(d)))
.range([0, nv.attribWidth * dAttribs.keys().length])
.paddingInner(0.1)
.paddingOuter(0);
levelScale
.domain(
dataIs.map(function (d, i) {
return i;
})
)
.range([
nv.x0 + nv.margin,
(xScale.range()[1] + nv.levelsSeparation) * dataIs.length + nv.x0,
])
.paddingInner(0)
.paddingOuter(0);
// Update color scales domains
if (shouldUpdateColorDomains) {
updateColorDomains();
}
const after = performance.now();
}
// Deletes the last level by default, or all the subsequent levels of _level on _dataIs
function deleteSubsequentLevels(_level, _dataIs, opts) {
if (dataIs.length <= 1) return;
let { shouldUpdate } = opts || {};
let level = _level !== undefined ? _level : dataIs.length - 1;
_dataIs = _dataIs !== undefined ? _dataIs : dataIs;
shouldUpdate = shouldUpdate !== undefined ? shouldUpdate : true;
if (!_dataIs.hasOwnProperty(level)) {
return _dataIs;
}
showLoading(this);
if (level > 0) {
removeBrushOnLevel(level - 1);
for (let d of _dataIs[level - 1]) {
data[d].selected = true;
}
if (
filtersByLevel.hasOwnProperty(level - 1) &&
filtersByLevel[level - 1].length
) {
// Cleanup filters from the previous level
for (let i = 0; i < filtersByLevel[level - 1].length; i++) {
delete filtersByLevel[level - 1][i];
}
}
filtersByLevel[level - 1] = [];
}
_dataIs.splice(level);
if (shouldUpdate) {
nv.updateData(_dataIs, colScales);
updateCallback(nv.getVisible());
}
hideLoading(this);
return _dataIs;
}
function moveAttrToPos(attr, pos) {
var i = attribsOrdered.indexOf(attr);
if (i === -1) {
console.log("moveAttrToPos attr not found", attr);
return;
}
if (pos > attribsOrdered.length || pos < 0) {
console.log(
"moveAttrToPos pos out of bounds",
pos,
attribsOrdered.length
);
return;
}
attribsOrdered.splice(i, 1);
attribsOrdered.splice(pos, 0, attr);
}
function findNotNull(data, attr) {
let i, val;
for (
i = 0;
i < nv.howManyItemsShouldSearchForNotNull && i < data.length;
i++
) {
val = typeof attr === "function" ? attr(data[i]) : data[i][attr];
if (val !== null && val !== undefined && val !== "") {
return val;
}
}
return val;
}
function recomputeVisibleLinks() {
if (links.length > 0) {
visibleLinks = links.filter(function (d) {
return d.source.selected && d.target.selected;
});
}
}
function updateLevel(levelData, i) {
drawLevelBorder(i);
for (let rep of levelData.representatives) {
drawItem(data[rep], i);
}
drawLevelConnections(i);
}
function updateWidthAndHeight() {
const ctxWidth = levelScale.range()[1] + nv.margin + nv.x0;
select(canvas)
.attr("width", ctxWidth)
.attr("height", height)
.style("width", ctxWidth)
.style("height", height + "px");
canvas.style.width = ctxWidth + "px";
canvas.style.height = height + "px";
svg.attr("width", ctxWidth).attr("height", height);
}
nv.initData = function (mData, mColScales) {
var before = performance.now();
// getAttribsFromObject(mData[0][0]);
colScales = mColScales;
// colScales.keys().forEach(function (d) {
// dAttribs.set(d, true);
// });
dData = map();
for (let i = 0; i < data.length; i++) {
const d = data[i];
d.__seqId = i; //create a default id with the sequential number
dData.set(d[id], d);
d.__i = [];
d.__i[0] = i;
}
filtersByLevel = [];
filtersByLevel[0] = []; // Initialice filters as empty for lev 0
// nv.updateData(mData, mColScales, mSortByAttr);
var after = performance.now();
};
nv.updateData = function (mDataIs, mColScales, opts) {
const {
levelsToUpdate,
shouldUpdateColorDomains,
shouldDrawBrushes,
recomputeBrushes,
} = opts || {};
var before = performance.now();
if (typeof mDataIs !== typeof []) {
console.log("navio updateData didn't receive an array");
return;
}
colScales = mColScales !== undefined ? mColScales : colScales;
dataIs = mDataIs;
// Delete filters on unused levels
filtersByLevel.splice(mDataIs.length);
// Initialize new filter level
filtersByLevel[mDataIs.length] = [];
recomputeVisibleLinks();
// Delete unnecesary brushes
dBrushes.splice(mDataIs.length);
updateScales({
levelsToUpdate,
shouldUpdateColorDomains,
});
updateWidthAndHeight();
nv.update({
levelsToUpdate,
shouldDrawBrushes,
recomputeBrushes,
});
var after = performance.now();
}; // updateData
nv.update = function (opts) {
let {
recomputeBrushes,
// levelsToUpdate,
shouldDrawBrushes,
} = opts || {};
if (!dataIs.length) return nv;
recomputeBrushes =
recomputeBrushes !== undefined ? recomputeBrushes : false;
shouldDrawBrushes =
shouldDrawBrushes !== undefined ? shouldDrawBrushes : true;
var before = performance.now();
var w = levelScale.range()[1] + nv.margin + nv.x0;
// If updating all levels erase everything
// if (levelsToUpdate===undefined) {
context.clearRect(0, 0, w + 1, height + 1);
// }
drawLinks();
// If we didn't get a specific level to update, do them all
// if (levelsToUpdate===undefined) {
for (let i = 0; i < dataIs.length; i++) {
updateLevel(dataIs[i], i);
}
// } else {
// levelToUpdate.forEach(levelToUp => {
// if (! dataIs.length.hasOwnProperty(levelToUp)) {
// updateLevel(dataIs[levelToUp], levelToUp);
// } else {
// if (DEBUG) console.log("Asked to update a level that doesn't exist, ignoring. Level=" , levelToUp, " levs to update" levelsToUpdate);
// }
// });
// }
if (shouldDrawBrushes) {
drawBrushes(recomputeBrushes);
drawCloseButton();
}
var after = performance.now();
return nv;
};
nv.addAttrib = function (attr, scale) {
if (scale === undefined) {
scale = scaleOrdinal(schemeCategory10);
}
if (dAttribs.has(getAttribName(attr))) {
console.log(`navio.addAttrib attribute ${attr} already added`);
return;
}
attribsOrdered.push(attr);
dAttribs.set(getAttribName(attr), attr);
colScales.set(attr, scale);
return nv;
};
nv.addSequentialAttrib = function (attr, _scale) {
const domain =
data !== undefined && data.length > 0
? extent(data, function (d) {
return getAttrib(d, attr);
})
: [0, 1]; //if we don"t have data, set the default domain
const scale =
_scale || scaleSequential(nv.defaultColorInterpolator).domain(domain);
scale.__type = "seq";
nv.addAttrib(attr, scale);
return nv;
};
// Same as addSequentialAttrib but with a different color
nv.addDateAttrib = function (attr, _scale) {
const domain =
data !== undefined && data.length > 0
? extent(data, function (d) {
return getAttrib(d, attr);
})
: [0, 1];
const scale =
_scale ||
scaleSequential(nv.defaultColorInterpolatorDate).domain(domain); //if we don"t have data, set the default domain
nv.addAttrib(attr, scale);
scale.__type = "date";
return nv;
};
// Adds a diverging scale
nv.addDivergingAttrib = function (attr, _scale) {
const domain =
data !== undefined && data.length > 0
? extent(data, function (d) {
return getAttrib(d, attr);
})
: [-1, 1];
const scale =
_scale ||
scaleSequential(nv.defaultColorInterpolatorDiverging)
.domain([domain[0], domain[1]]); //if we don"t have data, set the default domain
scale.__type = "div";
nv.addAttrib(attr, scale);
return nv;
};
nv.addCategoricalAttrib = function (attr, _scale) {
const scale = _scale || scaleOrdinal(nv.defaultColorCategorical);
scale.__type = "cat";
nv.addAttrib(attr, scale);
return nv;
};
nv.addTextAttrib = function (attr, _scale) {
const scale =
_scale ||
scaleText(
nv.nullColor,
nv.digitsForText,
nv.defaultColorInterpolatorText
);
nv.addAttrib(attr, scale);
return nv;
};
nv.addOrderedAttrib = function (attr, _scale) {
const scale =
_scale || scaleOrdered(nv.nullColor, nv.defaultColorInterpolatorOrdered);
nv.addAttrib(attr, scale);
return nv;
};
nv.addBooleanAttrib = function (attr, _scale) {
const scale =
_scale ||
scaleOrdinal()
.domain([true, false, null])
.range(nv.defaultColorRangeBoolean);
scale.__type = "bool";
nv.addAttrib(attr, scale);
return nv;
};
// Adds all the attributes on the data, or all the attributes provided on the list based on their types
nv.addAllAttribs = function (_attribs) {
if (!data || !data.length)
throw Error(
"addAllAttribs called without data to guess the attribs. Make sure to call it after setting the data"
);
var attribs =
_attribs !== undefined
? _attribs
: getAttribsFromObjectAsFn(data[0], nv.addAllAttribsRecursionLevel);
for (let attr of attribs) {
if (attr === "__seqId" || attr === "__i" || attr === "selected") continue;
const attrName = typeof attr === "function" ? attr.name : attr;
const firstNotNull = findNotNull(data, attr);
if (
firstNotNull === null ||
firstNotNull === undefined ||
typeof firstNotNull === typeof ""
) {
const numDistictValues = set(
data
.slice(0, nv.howManyItemsShouldSearchForNotNull)
.map((d) => getAttrib(d, attr))
)
.values().length;
// How many different elements are there
if (numDistictValues < nv.maxNumDistictForCategorical) {
console.log(
`Navio: Adding attr ${attrName} as categorical with ${numDistictValues} categories`
);
nv.addCategoricalAttrib(attr);
} else if (numDistictValues < nv.maxNumDistictForOrdered) {
nv.addOrderedAttrib(attr);
console.log(
`Navio: Attr ${attrName} has more than ${nv.maxNumDistictForCategorical} distinct values (${numDistictValues}) using orderedAttrib`
);
} else {
console.log(
`Navio: Attr ${attrName} has more than ${nv.maxNumDistictForOrdered} distinct values (${numDistictValues}) using textAttrib`
);
nv.addTextAttrib(attr);
}
} else if (typeof firstNotNull === typeof 0) {
// Numbers
if (min(data, (d) => getAttrib(d, attr)) < 0) {
console.log(`Navio: Adding attr ${attrName} as diverging`);
nv.addDivergingAttrib(attr);
} else {
console.log(`Navio: Adding attr ${attrName} as sequential`);
nv.addSequentialAttrib(attr);
}
} else if (firstNotNull instanceof Date) {
console.log(`Navio: Adding attr ${attrName} as date`);
nv.addDateAttrib(attr);
} else if (typeof firstNotNull === typeof true) {
console.log(`Navio: Adding attr ${attrName} as boolean`);
nv.addBooleanAttrib(attr);
} else {
// Default categories
if (Array.isArray(firstNotNull)) {
if (nv.addAllAttribsIncludeArrays) {
console.log(
`Navio: Adding ${attrName} adding as categorical (type=array)`
);
nv.addCategoricalAttrib(attr);
} else {
console.log(
`Navio: AddAllAttribs detected array ${attrName}, but ignoring it. To include it set nv.addAllAttribsIncludeArrays=true`
);
}
} else {
if (nv.addAllAttribsIncludeObjects) {
console.log(
`Navio: Adding object ${attrName} adding as categorical (type=object)`
);
nv.addCategoricalAttrib(attr);
} else {
console.log(
`Navio: AddAllAttribs detected object ${attrName}, but ignoring it. To include it set nv.addAllAttribsIncludeObjects=true`
);
}
}
}
}
nv.data(data);
// drawBrushes(true); // updates brushes width
return nv;
};
nv.data = function (_) {
initTooltipPopper();
if (!colScales.has("selected")) {
nv.addAttrib(
"selected",
scaleOrdinal()
.domain([false, true])
.range(nv.defaultColorRangeSelected)
//, "#cddca3", "#8c6d31", "#bd9e39"]
);
moveAttrToPos("selected", 0);
}
if (!colScales.has("__seqId")) {
nv.addSequentialAttrib("__seqId");
moveAttrToPos("__seqId", 1);
}
if (arguments.length) {
data = _.slice(0);
for (let d of data) {
d.selected = true;
}
dataIs = [
data.map(function (_, i) {
return i;
}),
];
nv.initData(dataIs, colScales);
// Has the user added attributes already? then update
if (attribsOrdered.length > 2) {
nv.updateData(dataIs, colScales, { shouldUpdateColorDomains: true });
}
return nv;
} else {
return data;
}
};
nv.getSelected = function () {
return dataIs[dataIs.length - 1]
.filter(function (d) {
return data[d].selected;
})
.map(function (d) {
return data[d];
});
};
// Legacy support
nv.getVisible = nv.getSelected;
nv.sortBy = function (_attrib, _desc = false, _level = undefined) {
// The default level is the last one
let level = Math.max(
0,
_level !== undefined && _level < dataIs.length
? _level
: dataIs.length - 1
);
if (_attrib !== undefined) {
// if (attribsOrdered.indexOf(_attrib)===-1) {
// throw `sortBy: ${_attrib} is not in the list of attributes`
// }
dSortBy[level] = {
attrib: _attrib,
desc: _desc,
};
return nv.update();
} else {
return dSortBy[level];
}
};
nv.updateCallback = function (_) {
return arguments.length ? ((updateCallback = _), nv) : updateCallback;
};
nv.selectedColorRange = function (_) {
return arguments.length
? ((nv.defaultColorRangeSelected = _), nv)
: nv.defaultColorRangeSelected;
};
// nv.defaultColorInterpolator = function(_) {
// return arguments.length ? (nv.defaultColorInterpolator = _, nv) : nv.defaultColorInterpolator;
// };
nv.id = function (_) {
return arguments.length ? ((id = _), nv) : id;
};
nv.links = function (_) {
if (arguments.length) {
links = _;
recomputeVisibleLinks();
return nv;
} else {
return links;
}
};
// Returns a d3.scale used for coloring the corresponding attrib
// check scale.__type for finding out the type of attribute (if undefined, navio doesn't know the type)
nv.getColorScale = function (attrib) {
return colScales.get(attrib);
};
// Returns an array with the list (in order) of attributes used right now
nv.getAttribs = function () {
return attribsOrdered;
};
// Slower update that recomputes brushes and checks for parameters.
// Use it if you change any parameters or added new attributes after calling .data
nv.hardUpdate = function (opts = {}) {
const shouldDrawBrushes =
opts.shouldDrawBrushes !== undefined ? opts.shouldDrawBrushes : true,
shouldUpdateColorDomains =
opts.shouldUpdateColorDomains !== undefined
? opts.shouldUpdateColorDomains
: true,
recomputeBrushes =
opts.recomputeBrushes !== undefined ? opts.recomputeBrushes : true,
levelsToUpdate =
opts.levelsToUpdate !== undefined
? opts.levelsToUpdate
: range(dataIs.length); // Range is not inclusive so is not length-1;
// Update all the levels
nv.updateData(dataIs, colScales, {
shouldDrawBrushes,
shouldUpdateColorDomains,
recomputeBrushes,
levelsToUpdate,
});
};
init();
return nv;
}
// Returns a flat array with all the attributes in an object up to recursionLevel
navio.getAttribsFromObjectRecursive = getAttribsFromObjectRecursive;
// Returns a flat array with all the attributes in an object up to recursionLevel, for nested attributes returns a function
navio.getAttribsFromObjectAsFn = getAttribsFromObjectAsFn;
// export { getAttribsFromObjectRecursive } from "./utils.js";
// export {NavioComponent, navio};
export default navio;
// https://github.com/john-guerra/Navio#readme v0.0.66 Copyright 2021 John Alexis Guerra Gómez
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("d3"),require("d3-scale-chromatic"),require("popper.js")):"function"==typeof define&&define.amd?define(["d3","d3-scale-chromatic","popper.js"],e):t.navio=e(t.d3,t.d3ScaleChromatic,t.Popper)}(this,function(t,e,n){"use strict";function o(t){const e=t.first,n=t.last,o=t.level,r=t.itemAttr,i=t.getAttrib||(t=>t[r]),l=t.getAttribName||(t=>"function"==typeof t?t.name:t);return{filter:function(t){return t.__i[o]>=e.__i[o]&&t.__i[o]<=n.__i[o]},toStr:function(){let t=`${i(e,r)}`,o=`${i(n,r)}`;return t="string"==typeof t?t.slice(0,5):t,o="string"==typeof o?o.slice(0,5):o,`${l(r)} range including ${t} to ${o}`},type:"range"}}function r(t){const e=t.itemAttr,n=t.sel,o=t.getAttrib||(t=>t[e]),r=t.getAttribName||(t=>"function"==typeof t?t.name:t);return{filter:function(t){return o(t,e)===o(n,e)},toStr:function(){return`${r(e)} == ${o(n,e)}`},type:"value"}}function i(t){const e=t.itemAttr,n=t.sel,o=t.getAttrib||(t=>t[e]),r=t.getAttribName||(t=>"function"==typeof t?t.name:t);return{filter:function(t){return o(t,e)!==o(n,e)},toStr:function(){return`${r(e)} != ${o(n,e)}`},type:"negativeValue"}}function l(t){const e=t.first,n=t.last,o=t.level,r=t.itemAttr,i=t.getAttrib||(t=>t[r]),l=t.getAttribName||(t=>"function"==typeof t?t.name:t);return{filter:function(t){return t.__i[o]<e.__i[o]||t.__i[o]>n.__i[o]},toStr:function(){let t=`${i(e,r)}`,o=`${i(n,r)}`;return t="string"==typeof t?t.slice(0,5):t,o="string"==typeof o?o.slice(0,5):o,`${l(r)} range excluding ${t} to ${o}`},type:"negativeRange"}}function a(t,e){return null==e?null==t?0:1:null==t?-1:(typeof t!=typeof e&&(t=""+t,e=""+e),t<e?-1:t>e?1:t>=e?0:NaN)}n=n&&n.hasOwnProperty("default")?n.default:n;const s=function(t,e=1/0){return function t(n,o){var r,i=[];for(r in n)n.hasOwnProperty(r)&&"__i"!==r&&"__seqId"!==r&&"selected"!==r&&(!(o<e)||Array.isArray(n[r])||null===n[r]||void 0===n[r]||n[r]instanceof Date||typeof n[r]!=typeof{}?i.push([r]):i=i.concat(t(n[r],o+1).map(t=>[r].concat(t))));return i}(t,0)};function d(t,e=1/0){return s(t,e).map(t=>t.length>1?function(t){"string"==typeof t&&(t=t.split("."));let e=t.join("_");const n=t.map(t=>`["${t}"]`).join("");let o=`return function ${e}(d) { try { return d${n} } catch (e) { return undefined }; };`;try{return new Function(o)()}catch(t){return o=`return function ${e=e.replace(/[^a-zA-Z0-9_-]/g,"")}(d) { try { return d${n} } catch (e) { return undefined }; };`,new Function(o)()}}(t):t)}function c(s,c){let u,p,g,f,m,v,h,y,b=this||{},A=[],w=[],I=[],x=[],S=t.map(),C=[],D=t.map(),M=[],N=[],z=[],_=[],B=void 0!==c?c:600,T=t.map(),Z={x:-50,y:-50},R="__seqId",$=function(){},P="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU0LjEgKDc2NDkwKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5jdXJzb3JTdWJzdHJhY3Q8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iY3Vyc29yU3Vic3RyYWN0IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBkPSJNOSwwLjUgTDcsMC41IEw3LDcgTDAuNSw3IEwwLjUsOSBMNyw5IEw3LDE1LjUgTDksMTUuNSBMOSw5IEwxNS41LDkgTDE1LjUsNyBMOSw3IEw5LDAuNSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHN0cm9rZT0iI0ZGRkZGRiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgICAgIDxyZWN0IGlkPSJSZWN0YW5nbGUiIGZpbGw9IiMwMDAwMDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE1LjAwMDAwMCwgMTUuMDAwMDAwKSByb3RhdGUoLTI3MC4wMDAwMDApIHRyYW5zbGF0ZSgtMTUuMDAwMDAwLCAtMTUuMDAwMDAwKSAiIHg9IjE0IiB5PSIxMSIgd2lkdGg9IjIiIGhlaWdodD0iOCI+PC9yZWN0PgogICAgPC9nPgo8L3N2Zz4=",k="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU0LjEgKDc2NDkwKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5jdXJzb3JBZGQ8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iY3Vyc29yQWRkIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBkPSJNOSwwLjUgTDcsMC41IEw3LDcgTDAuNSw3IEwwLjUsOSBMNyw5IEw3LDE1LjUgTDksMTUuNSBMOSw5IEwxNS41LDkgTDE1LjUsNyBMOSw3IEw5LDAuNSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHN0cm9rZT0iI0ZGRkZGRiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgICAgIDxwYXRoIGQ9Ik0xNiwxNCBMMTksMTQgTDE5LDE2IEwxNiwxNiBMMTYsMTkgTDE0LDE5IEwxNCwxNiBMMTEsMTYgTDExLDE0IEwxNCwxNCBMMTQsMTEgTDE2LDExIEwxNiwxNCBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIGZpbGw9IiMwMDAwMDAiPjwvcGF0aD4KICAgIDwvZz4KPC9zdmc+",G="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU0LjEgKDc2NDkwKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5jdXJzb3I8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iY3Vyc29yIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBkPSJNOSwwLjUgTDcsMC41IEw3LDcgTDAuNSw3IEwwLjUsOSBMNyw5IEw3LDE1LjUgTDksMTUuNSBMOSw5IEwxNS41LDkgTDE1LjUsNyBMOSw3IEw5LDAuNSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHN0cm9rZT0iI0ZGRkZGRiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgPC9nPgo8L3N2Zz4=";function L(){t.event.preventDefault()}function E(){y&&y.remove(),t.selectAll("._nv_popover").remove(),(y=t.select("body").append("div").attr("class","_nv_popover").style("pointer-events","none").style("font-family","sans-serif").style("font-size",b.tooltipFontSize).style("text-align","center").style("background",b.tooltipBgColor).style("position","relative").style("color","black").style("z-index",4).style("border-radius","4px").style("box-shadow","0 0 2px rgba(0,0,0,0.5)").style("padding","10px").style("text-align","center").style("display","none")).append("style").attr("scoped","").text(`\n [x-arrow] {\n width: 0;\n height: 0;\n border-style: solid;\n position: absolute;\n margin: ${b.tooltipArrowSize}px;\n border-color: ${b.tooltipBgColor}\n }\n\n ._nv_popover[x-placement="left"] {\n margin-right: ${b.tooltipArrowSize+b.tooltipMargin}px;\n }\n\n ._nv_popover[x-placement="left"] [x-arrow] {\n border-width: ${b.tooltipArrowSize}px 0 ${b.tooltipArrowSize}px ${b.tooltipArrowSize}px;\n border-top-color: transparent;\n border-right-color: transparent;\n border-bottom-color: transparent;\n right: -${b.tooltipArrowSize}px;\n top: calc(50% - ${b.tooltipArrowSize}px);\n margin-left: 0;\n margin-right: 0;\n }\n\n ._nv_popover[x-placement="right"] {\n margin-left: ${b.tooltipArrowSize+b.tooltipMargin}px;\n }\n\n ._nv_popover[x-placement="right"] [x-arrow] {\n border-width: ${b.tooltipArrowSize}px ${b.tooltipArrowSize}px ${b.tooltipArrowSize}px 0;\n border-left-color: transparent;\n border-top-color: transparent;\n border-bottom-color: transparent;\n left: -${b.tooltipArrowSize}px;\n top: calc(50% - ${b.tooltipArrowSize}px);\n margin-left: 0;\n margin-right: 0;\n }\n\n ._nv_popover[x-placement="bottom"] {\n margin-top: ${b.tooltipArrowSize+b.tooltipMargin}px;\n }\n\n ._nv_popover[x-placement="bottom"] [x-arrow] {\n border-width: 0 ${b.tooltipArrowSize}px ${b.tooltipArrowSize}px ${b.tooltipArrowSize}px;\n border-left-color: transparent;\n border-right-color: transparent;\n border-top-color: transparent;\n top: -${b.tooltipArrowSize}px;\n left: calc(50% - ${b.tooltipArrowSize}px);\n margin-top: 0;\n margin-bottom: 0;\n }\n\n ._nv_popover[x-placement="top"] {\n margin-bottom: ${b.tooltipArrowSize+b.tooltipMargin}px;\n }\n\n ._nv_popover[x-placement="top"] [x-arrow] {\n border-width: ${b.tooltipArrowSize}px ${b.tooltipArrowSize}px 0 ${b.tooltipArrowSize}px;\n border-left-color: transparent;\n border-right-color: transparent;\n border-bottom-color: transparent;\n bottom: -${b.tooltipArrowSize}px;\n left: calc(50% - ${b.tooltipArrowSize}px);\n margin-top: 0;\n margin-bottom: 0;\n }\n\n\n `),y.append("div").attr("class","tool_id"),y.append("div").attr("class","tool_value_name").style("font-weight","bold").style("font-size","120%"),y.append("div").attr("class","tool_value_val").style("max-width","400px").style("max-height","5.5em").style("text-align","left").style("overflow","hidden").style("font-size","90%"),y.append("div").style("font-size","70%").style("margin-top","10px").style("text-align","left").style("color","#777").html("<div>Click to filter a value (<strong>alt</strong> for negative filter).<br>\n Drag for filtering a range.<br> <strong>shift</strong> click for appending to the filters</div>"),y.append("div").attr("x-arrow",""),h=new n({getBoundingClientRect:()=>{const t=f.node().getBoundingClientRect();return{top:Z.y+t.top,right:Z.x+t.left,bottom:Z.y+t.top,left:Z.x+t.left,width:0,height:0}},clientWidth:0,clientHeight:0},y.node(),{placement:"right"})}function U(){"Alt"===t.event.key?t.selectAll(".overlay").attr("cursor",`url(${P}) 8 8, zoom-out`).style("cursor",`url(${P}) 8 8, zoom-out`):"Shift"===t.event.key?t.selectAll(".overlay").attr("cursor",`url(${k}) 8 8, zoom-in`).style("cursor",`url(${k}) 8 8, zoom-in`):t.selectAll(".overlay").style("cursor",`url(${G}) 8 8, crosshair`),"keyup"===t.event.type&&t.selectAll(".overlay").style("cursor",`url(${G}) 8 8, crosshair`)}function O(e){t.select(e).style("cursor","progress"),f.style("cursor","progress")}function j(e){t.select(e).style("cursor",null),f.style("cursor",null)}function W(e,n){var o=e.domain(),r=e.range();return t.scaleQuantize().domain(r).range(o)(n)}function F(t,e){if(!M.hasOwnProperty(t))return;e=void 0!==e?e:w;performance.now();const n=M[t];e[t].sort(function(t,e){return n.desc?function(t,e){return null==e?null==t?0:-1:null==t?1:(typeof t!=typeof e&&(t=""+t,e=""+e),t<e?1:t>e?-1:t>=e?0:NaN)}(Y(A[t],n.attrib),Y(A[e],n.attrib)):a(Y(A[t],n.attrib),Y(A[e],n.attrib))}),q(e[t],t);performance.now()}function V(e){t.event&&t.event.defaultPrevented||(M[e.level]={attrib:e.attrib,desc:void 0!==M[e.level]&&M[e.level].attrib===e.attrib&&!M[e.level].desc},Q(e.level+1),F(e.level),J(e.level),b.updateData(w,T,{levelsToUpdate:[e.level]}),$(b.getVisible()))}function Y(t,e){if("function"!=typeof e)return t[e];try{return e(t)}catch(t){return}}function H(t){return"function"==typeof t&&t.name?t.name:t}function X(t,e){var n,o,r;for(v.save(),o=0;o<C.length;o++){const l=Y(t,n=C[o]),a=H(n);if(r=Math.round(_[e](t[R])+_[e].bandwidth()/2),v.beginPath(),v.moveTo(Math.round(p(a,e)),r),v.lineTo(Math.round(p(a,e)+u.bandwidth()),r),v.lineWidth=Math.ceil(_[e].bandwidth()),v.strokeStyle=null==l||""===l||"none"===l?b.nullColor:T.get(n)(l),v.stroke(),_[e].bandwidth()>2*b.divisionsThreshold){var i=Math.round(_[e](t[R]));v.beginPath(),v.moveTo(p(a,e),i),v.lineTo(p(a,e)+u.bandwidth(),i),v.lineWidth=1,v.strokeStyle=b.divisionsColor,v.stroke()}}v.restore()}function J(e){e<0||t.select("#level"+e).selectAll(".brush").call(N[e].move,null)}function K(t){for(var e=0;e<w.length;e+=1)e!==t&&J(e)}function q(t,e){for(var n=0;n<t.length;n++)A[t[n]].__i[e]=n}function Q(t){for(let e=t;e<z.length;e++)z[e]=z[e].filter(t=>"value"===t.type||"negativeValue"===t.type)}function tt(t,e){let n,o;e=void 0!==e?e:w,n=performance.now();const r=z[t].filter(t=>"negativeValue"===t.type||"negativeRange"===t.type),i=z[t].filter(t=>"negativeValue"!==t.type||"negativeRange"!==t.type);var l=e[t].filter(t=>A[t].selected=i.reduce((e,n)=>e||n.filter(A[t]),!1)&&r.reduce((e,n)=>e&&n.filter(A[t]),!0));return o=performance.now(),l}function et(e){const n=function(){let t=0;for(let e=0;e<z.length&&(t=e,z[e]&&z[e].length);e++);return t}();let o=w;for(let t=e;t<=n;t++){if(!z.hasOwnProperty(t)||!z[t].length){o=vt(t+1,o,{shouldUpdate:!1});break}let e=tt(t,o);q(e,t+1),e.length,b.nestedFilters&&(o[t+1]=e),F(t+1)}b.updateData(o,T,{shouldDrawBrushes:!0,levelsToUpdate:t.range(e,o.length)}),$(b.getVisible())}function nt(e,n){N[n]=t.brushY().extent([[p(u.domain()[0],n),_[n].range()[0]],[p(u.domain()[u.domain().length-1],n)+1.1*u.bandwidth(),_[n].range()[1]]]).on("brush",function(){if(!t.event.sourceEvent)return;if(!t.event.selection)return;const e=t.event.sourceEvent.clientX,o=t.event.sourceEvent.clientY,r=t.event.sourceEvent.offsetX,i=t.event.sourceEvent.offsetY;ot(r,i,e,o,n)}).on("end",function(){if(!t.event.sourceEvent)return;if(!t.event.selection)return;O(this),K(n);performance.now();var e=t.event.selection,r=S.get(W(_[n],e[0])),i=S.get(W(_[n],e[1]));let a;a=t.event.sourceEvent.altKey?new l({first:r,last:i,level:n,itemAttr:M[n]?M[n].attrib:"__seqId",getAttrib:Y,getAttribName:H}):new o({first:r,last:i,level:n,itemAttr:M[n]?M[n].attrib:"__seqId",getAttrib:Y,getAttribName:H});t.event.sourceEvent.shiftKey?(z.hasOwnProperty(n)||(z[n]=[]),z[n].push(a)):z[n]=[a];Q(n+1),et(n);performance.now();j(this)});var a=t.select(this).selectAll(".brush").data([{data:e.map(t=>A[t]),level:n}]);a.enter().merge(a).append("g").on("mousemove",rt).on("click",function(){O(this);var e=t.mouse(t.event.target)[1];(function(e,o){K(-1);performance.now();const l=W(_[n],o);performance.now();let a=W(u,e-g(n));if(void 0===a)return void console.log(`navio.selectByValue: error, couldn't find attr in coords ${o}`);a=D.get(a);const s=S.get(l);let d;d=t.event.altKey?new i({sel:s,itemAttr:a,getAttrib:Y,getAttribName:H}):new r({sel:s,itemAttr:a,getAttrib:Y,getAttribName:H});t.event.shiftKey?(z.hasOwnProperty(n)||(z[n]=[]),z[n].push(d)):z[n]=[d];Q(n+1),et(n)})(t.mouse(t.event.target)[0],e),j(this)}).on("mouseout",it).attr("class","brush").call(N[n]).selectAll("rect").attr("width",p(u.domain()[u.domain().length-1],n)+1.1*u.bandwidth()),a.exit().remove()}function ot(t,e,n,o,r){let i;try{i=W(_[r],e)}catch(t){return}let l=W(u,t-g(r));const a=S.get(i);l=D.get(l),a&&void 0!==a?(Z.x=t,Z.y=e,y.select(".tool_id").text(i),y.select(".tool_value_name").text(H(l)),y.select(".tool_value_val").text(Y(a,l)),y.style("display","initial"),h.scheduleUpdate()):console.log("Couldn't find datum for tooltip y",e,a)}function rt(e){const n=t.mouse(t.event.target)[0],o=t.mouse(t.event.target)[1];t.event.clientX,t.event.clientY;e.data&&0!==e.data.length&&ot(n,o,0,0,e.level)}function it(){Z.x=-200,Z.y=-200,y.style("display","none"),h.scheduleUpdate()}function lt(t,e){const n=u.domain()[u.domain().length-1],o=s.select("div.explanations").selectAll("div.filterExplanation").data(w),r=o.enter().append("div").attr("class","filterExplanation").merge(o).style("position","absolute").style("top","0").style("left","0").style("min-width","200px").style("transform",(t,e)=>`translate(${(t=>p(n,t)+u.bandwidth()+2)(e)}px, ${_[e].range()[1]+1.2*b.filterFontSize}px)`).merge(o.select(".filterExplanation")).style("font-size",b.filterFontSize+"pt").selectAll("div").data((t,e)=>z[e]?z[e].map(t=>(t.level=e,t)):[]);r.enter().append("div").merge(r).style("cursor","not-allowed").text(t=>"Ⓧ "+t.toStr()).on("click",(t,e)=>{console.log("Click remove filter",e,t),z[t.level].splice(e,1),et(t.level)}),r.exit().remove(),o.exit().remove()}function at(e,n){var o;b.showAttribTitles&&n.append("text").merge(e.select("text")).style("cursor","point").style("-webkit-user-select","none").style("-moz-user-select","none").style("-ms-user-select","none").style("user-select","none").text(function(t){return"__seqId"===t.attrib?"sequential Index":t.name+(void 0!==M[t.level]&&M[t.level].attrib===t.attrib?M[t.level].desc?" ↓":" ↑":"")}).attr("x",u.bandwidth()/2).attr("y",0).style("font-weight",function(t){return void 0!==M[t.level]&&M[t.level].attrib===t.attrib?"bolder":"normal"}).style("font-family","sans-serif").style("font-size",function(){return Math.min(b.attribFontSize,b.attribWidth)+"px"}).on("click",(o=V,function(t,e,n){O(this),requestAnimationFrame(()=>{o(t,e,n),j(this)})})).call(t.drag().container(n.merge(e).node()).on("start",dt).on("drag",ct).on("end",ut)).on("mousemove",function(){var e=t.select(this);(e=void 0!==e.transition?e.transition().duration(150):e).style("font-size",b.attribFontSizeSelected+"px")}).on("mouseout",function(){var e=t.select(this);(e=void 0!==e.transition?e.transition().duration(150):e).style("font-size",Math.min(b.attribFontSize,b.attribWidth)+"px")}).attr("transform",`rotate(${b.attribRotation})`)}function st(t){var e=f.select(".attribs").selectAll(".levelOverlay").data(w),n=e.enter().append("g");n.attr("class","levelOverlay").attr("id",function(t,e){return"level"+e}),t?n.merge(e).each(nt):n.each(nt),function(t,e){var n=C,o=e.merge(t).selectAll(".attribOverlay").data(function(t,e){return n.map(function(t){return{attrib:t,name:H(t),level:e}})}),r=o.enter().append("g").attr("class","attribOverlay").style("cursor","pointer");r.merge(o).attr("transform",t=>`translate(${p(t.name,t.level)}, ${_[t.level].range()[0]})`),r.append("rect").merge(o.select("rect")).attr("fill","none").attr("x",0).attr("y",0).attr("width",function(){return 1.1*u.bandwidth()}).attr("height",function(t){return _[t.level].range()[1]-_[t.level].range()[0]}),at(o,r),o.exit().remove()}(e,n),function(t,e){e.append("text").merge(t.select("text.numNodesLabel")).attr("class","numNodesLabel").style("font-family","sans-serif").style("pointer-events","none").attr("y",function(t,e){return _[e].range()[1]+15}).attr("x",function(t,e){return g(e)}).text(function(t){return b.fmtCounts(t.length)})}(e,n),lt(),e.exit().remove()}function dt(e){t.event.sourceEvent.shiftKey&&t.select(this.parentNode).attr("transform",function(e){return"translate("+(t.event.x+b.attribFontSize/2)+","+_[e.level].range()[0]+")"})}function ct(){t.event.sourceEvent.shiftKey&&t.select(this.parentNode).attr("transform",function(e){return"translate("+(t.event.x+b.attribFontSize/2)+","+_[e.level].range()[0]+")"})}function ut(e){if(!t.event.sourceEvent.shiftKey)return;let n=W(u,t.event.x+b.attribFontSize/2-g(e.level));var o;n=D.get(n),t.select(this.parentNode).attr("transform",function(t){return"translate("+p(t.name,t.level)+","+_[t.level].range()[0]+")"}),n!==e.attrib&&(o=C.indexOf(n),ht(e.attrib,o),b.updateData(w))}function pt(t){var e=u.domain()[u.domain().length-1],n=p(e,w.length-1)+u.bandwidth()+2,o=_[w.length-1](t.source[R])+_[w.length-1].bandwidth()/2,r=_[w.length-1](t.target[R])+_[w.length-1].bandwidth()/2,i=Math.min(o,r),l=Math.max(o,r),a=l-i;v.moveTo(n,i),v.quadraticCurveTo(n+a/6,i+a/2,n,l)}function gt(t,e,n,o){v.beginPath();for(let e=0;e<t.length;e++){const n=t[e];0===e?v.moveTo(n.x,n.y):v.lineTo(n.x,n.y)}v.lineWidth=e,o?(v.fillStyle=n,v.closePath(),v.fill()):(v.strokeStyle=n,v.stroke())}function ft(t){let e=[];if(w[t].length>B){const n=Math.max(Math.floor(w[t].length/(2*B)),1);w[t].itemsPerpixel=n;for(let o=0;o<w[t].length;o+=n)e.push(w[t][o])}else w[t].itemsPerpixel=1,e=w[t];return w[t].representatives=e,e}function mt(e){let{levelsToUpdate:n,shouldUpdateColorDomains:o}=e||{};performance.now();const r=w.length-1;n=void 0!==n?n:[r],o=void 0!==o&&o,_.splice(r+1,_.length);for(let e of n){_[e]=t.scaleBand().range([b.y0,B-b.margin-30]).paddingInner(0).paddingOuter(0);const n=ft(e);_[e].domain(n.map(function(t){return A[t][R]}))}u.domain(C.map(t=>H(t))).range([0,b.attribWidth*D.keys().length]).paddingInner(.1).paddingOuter(0),g.domain(w.map(function(t,e){return e})).range([b.x0+b.margin,(u.range()[1]+b.levelsSeparation)*w.length+b.x0]).paddingInner(0).paddingOuter(0),o&&function(){for(let n of C)if("selected"!==n){var e=T.get(n);if("seq"===e.__type||"date"===e.__type)e.domain(t.extent(w[0].map(function(t){return Y(A[t],n)})));else if("div"===e.__type){const[o,r]=t.extent(w[0].map(function(t){return Y(A[t],n)})),i=Math.max(-o,r);e.domain([-i,i])}else"text"!==e.__type&&"ordered"!==e.__type||e.domain(w[0].map(t=>Y(A[t],n)));T.set(H(n),e)}}();performance.now()}function vt(t,e,n){if(w.length<=1)return;let{shouldUpdate:o}=n||{},r=void 0!==t?t:w.length-1;if(o=void 0===o||o,!(e=void 0!==e?e:w).hasOwnProperty(r))return e;if(O(this),r>0){J(r-1);for(let t of e[r-1])A[t].selected=!0;if(z.hasOwnProperty(r-1)&&z[r-1].length)for(let t=0;t<z[r-1].length;t++)delete z[r-1][t];z[r-1]=[]}return e.splice(r),o&&(b.updateData(e,T),$(b.getVisible())),j(this),e}function ht(t,e){var n=C.indexOf(t);-1!==n?e>C.length||e<0?console.log("moveAttrToPos pos out of bounds",e,C.length):(C.splice(n,1),C.splice(e,0,t)):console.log("moveAttrToPos attr not found",t)}function yt(t,e){let n,o;for(n=0;n<b.howManyItemsShouldSearchForNotNull&&n<t.length;n++)if(null!=(o="function"==typeof e?e(t[n]):t[n][e])&&""!==o)return o;return o}function bt(){I.length>0&&(x=I.filter(function(t){return t.source.selected&&t.target.selected}))}function At(t,e){!function(t){v.save(),v.beginPath(),v.rect(g(t),_[t].range()[0]-1,u.range()[1]+1,_[t].range()[1]+2-_[t].range()[0]),v.strokeStyle="black",v.lineWidth=1,v.stroke(),v.restore()}(e);for(let n of t.representatives)X(A[n],e);!function(t){if(!(t<=0))for(let l of w[t].representatives){var e=S.get(A[l][R]).__i[t-1],n=Math.floor(e-e%w[t-1].itemsPerpixel),o={x:g(t-1)+u.range()[1],y:_[t-1](A[w[t-1][n]][R])},r={x:g(t),y:_[t](A[l][R])},i=[o,{x:o.x+.3*b.levelsSeparation,y:o.y},{x:r.x-.3*b.levelsSeparation,y:r.y},r,{x:r.x,y:r.y+_[t].bandwidth()},{x:r.x-.3*b.levelsSeparation,y:r.y+_[t].bandwidth()},{x:o.x+.3*b.levelsSeparation,y:o.y+_[t-1].bandwidth()},{x:o.x,y:o.y+_[t-1].bandwidth()},o];gt(i,1,b.levelConnectionsColor),gt(i,1,b.levelConnectionsColor,!0)}}(e)}return b.x0=0,b.y0=100,b.maxNumDistictForCategorical=10,b.maxNumDistictForOrdered=90,b.howManyItemsShouldSearchForNotNull=100,b.margin=10,b.levelsSeparation=40,b.divisionsColor="white",b.nullColor="#ffedfd",b.levelConnectionsColor="rgba(205, 220, 163, 0.5)",b.divisionsThreshold=4,b.fmtCounts=t.format(",.0d"),b.legendFont="14px sans-serif",b.linkColor="#ccc",b.nestedFilters=!0,b.showAttribTitles=!0,b.attribWidth=15,b.attribRotation=-45,b.attribFontSize=13,b.attribFontSizeSelected=32,b.filterFontSize=8,b.tooltipFontSize=12,b.tooltipBgColor="#b2ddf1",b.tooltipMargin=50,b.tooltipArrowSize=10,b.addAllAttribsRecursionLevel=1/0,b.addAllAttribsIncludeObjects=!1,b.addAllAttribsIncludeArrays=!1,b.digitsForText=2,b.defaultColorInterpolator="interpolateBlues"in t?t.interpolateBlues:e.interpolateBlues,b.defaultColorInterpolatorDate="interpolatePurples"in t?t.interpolatePurples:e.interpolatePurples,b.defaultColorInterpolatorDiverging="interpolateBrBG"in t?t.interpolateBrBG:e.interpolateBrBG,b.defaultColorInterpolatorOrdered="interpolateOranges"in t?t.interpolateOranges:e.interpolateOranges,b.defaultColorInterpolatorText="interpolateGreys"in t?t.interpolateGreys:e.interpolateGreys,b.defaultColorRangeBoolean=["#a1d76a","#e9a3c9","white"],b.defaultColorRangeSelected=["white","#b5cf6b"],b.defaultColorCategorical=t.schemeCategory10,b.initData=function(e,n){performance.now();T=n,S=t.map();for(let t=0;t<A.length;t++){const e=A[t];e.__seqId=t,S.set(e[R],e),e.__i=[],e.__i[0]=t}(z=[])[0]=[];performance.now()},b.updateData=function(e,n,o){const{levelsToUpdate:r,shouldUpdateColorDomains:i,shouldDrawBrushes:l,recomputeBrushes:a}=o||{};performance.now();if(typeof e==typeof[]){T=void 0!==n?n:T,w=e,z.splice(e.length),z[e.length]=[],bt(),N.splice(e.length),mt({levelsToUpdate:r,shouldUpdateColorDomains:i}),function(){const e=g.range()[1]+b.margin+b.x0;t.select(m).attr("width",e).attr("height",B).style("width",e).style("height",B+"px"),m.style.width=e+"px",m.style.height=B+"px",f.attr("width",e).attr("height",B)}(),b.update({levelsToUpdate:r,shouldDrawBrushes:l,recomputeBrushes:a});performance.now()}else console.log("navio updateData didn't receive an array")},b.update=function(t){let{recomputeBrushes:e,shouldDrawBrushes:n}=t||{};if(!w.length)return b;e=void 0!==e&&e,n=void 0===n||n;performance.now();var o,r=g.range()[1]+b.margin+b.x0;v.clearRect(0,0,r+1,B+1),function(){if(I.length){v.save(),v.beginPath(),v.strokeStyle=b.linkColor,v.globalAlpha=Math.min(1,Math.max(.1,1e3/I[I.length-1].length));for(let t of x)pt(t);v.stroke(),v.restore()}}();for(let t=0;t<w.length;t++)At(w[t],t);n&&(st(e),o=w.length-1,f.select("#closeButton").style("display",1===w.length?"none":"block").attr("transform","translate("+(g(o)+g.bandwidth()-b.levelsSeparation+15)+","+_[o].range()[0]+")"));performance.now();return b},b.addAttrib=function(e,n){if(void 0===n&&(n=t.scaleOrdinal(t.schemeCategory10)),!D.has(H(e)))return C.push(e),D.set(H(e),e),T.set(e,n),b;console.log(`navio.addAttrib attribute ${e} already added`)},b.addSequentialAttrib=function(e,n){const o=void 0!==A&&A.length>0?t.extent(A,function(t){return Y(t,e)}):[0,1],r=n||t.scaleSequential(b.defaultColorInterpolator).domain(o);return r.__type="seq",b.addAttrib(e,r),b},b.addDateAttrib=function(e,n){const o=void 0!==A&&A.length>0?t.extent(A,function(t){return Y(t,e)}):[0,1],r=n||t.scaleSequential(b.defaultColorInterpolatorDate).domain(o);return b.addAttrib(e,r),r.__type="date",b},b.addDivergingAttrib=function(e,n){const o=void 0!==A&&A.length>0?t.extent(A,function(t){return Y(t,e)}):[-1,1],r=n||t.scaleSequential(b.defaultColorInterpolatorDiverging).domain([o[0],o[1]]);return r.__type="div",b.addAttrib(e,r),b},b.addCategoricalAttrib=function(e,n){const o=n||t.scaleOrdinal(b.defaultColorCategorical);return o.__type="cat",b.addAttrib(e,o),b},b.addTextAttrib=function(e,n){const o=n||function(e,n=1,o){let r=t.scaleSequential(o),i=t.map(),l=t.map();function a(t){"string"!=typeof t&&(t+="");let o=l.get(t.slice(0,n));return void 0===o&&(console.log(`scaleText Couldn't find index for ${t} did you call domain? Using ascii of first letter`),o=t.charCodeAt(0)),r(o)||e}function s(e,n=!0){i=t.map();for(let t of e)i.has(t)||i.set(t,0),i.set(t,i.get(t)+1);const o={counts:i};if(n){l=t.map();let e=0;for(let t of i.keys().sort())l.set(t,e++);o.indexes=l}return o}return a.digits=function(t){return arguments.length?(n=t,a):n},a.scale=function(t){return arguments.length?(r=t,a):r},a.domain=function(t){return arguments.length?(s(t.map(t=>(""+t).slice(0,n))),r.domain([0,i.keys().length]),a):r.domain()},a.computeRepresentatives=s,a.__type="text",a}(b.nullColor,b.digitsForText,b.defaultColorInterpolatorText);return b.addAttrib(e,o),b},b.addOrderedAttrib=function(e,n){const o=n||function(e,n){let o=t.scaleOrdinal();function r(t){return null==t?e:o(t)}function i(t){const e=[];let n=null;for(let o of t.sort((t,e)=>a(t,e)))n!==o&&(e.push(o),n=o);return e}return r.domain=function(t){if(arguments.length){const e=i(t);return o.domain(e).range(e.map((t,o)=>n(o/e.length))),r}return o.domain()},r.computeRepresentatives=i,r.__type="ordered",r}(b.nullColor,b.defaultColorInterpolatorOrdered);return b.addAttrib(e,o),b},b.addBooleanAttrib=function(e,n){const o=n||t.scaleOrdinal().domain([!0,!1,null]).range(b.defaultColorRangeBoolean);return o.__type="bool",b.addAttrib(e,o),b},b.addAllAttribs=function(e){if(!A||!A.length)throw Error("addAllAttribs called without data to guess the attribs. Make sure to call it after setting the data");var n=void 0!==e?e:d(A[0],b.addAllAttribsRecursionLevel);for(let e of n){if("__seqId"===e||"__i"===e||"selected"===e)continue;const n="function"==typeof e?e.name:e,o=yt(A,e);if(null==o||"string"==typeof o){const o=t.set(A.slice(0,b.howManyItemsShouldSearchForNotNull).map(t=>Y(t,e))).values().length;o<b.maxNumDistictForCategorical?(console.log(`Navio: Adding attr ${n} as categorical with ${o} categories`),b.addCategoricalAttrib(e)):o<b.maxNumDistictForOrdered?(b.addOrderedAttrib(e),console.log(`Navio: Attr ${n} has more than ${b.maxNumDistictForCategorical} distinct values (${o}) using orderedAttrib`)):(console.log(`Navio: Attr ${n} has more than ${b.maxNumDistictForOrdered} distinct values (${o}) using textAttrib`),b.addTextAttrib(e))}else"number"==typeof o?t.min(A,t=>Y(t,e))<0?(console.log(`Navio: Adding attr ${n} as diverging`),b.addDivergingAttrib(e)):(console.log(`Navio: Adding attr ${n} as sequential`),b.addSequentialAttrib(e)):o instanceof Date?(console.log(`Navio: Adding attr ${n} as date`),b.addDateAttrib(e)):typeof o==typeof!0?(console.log(`Navio: Adding attr ${n} as boolean`),b.addBooleanAttrib(e)):Array.isArray(o)?b.addAllAttribsIncludeArrays?(console.log(`Navio: Adding ${n} adding as categorical (type=array)`),b.addCategoricalAttrib(e)):console.log(`Navio: AddAllAttribs detected array ${n}, but ignoring it. To include it set nv.addAllAttribsIncludeArrays=true`):b.addAllAttribsIncludeObjects?(console.log(`Navio: Adding object ${n} adding as categorical (type=object)`),b.addCategoricalAttrib(e)):console.log(`Navio: AddAllAttribs detected object ${n}, but ignoring it. To include it set nv.addAllAttribsIncludeObjects=true`)}return b.data(A),b},b.data=function(e){if(E(),T.has("selected")||(b.addAttrib("selected",t.scaleOrdinal().domain([!1,!0]).range(b.defaultColorRangeSelected)),ht("selected",0)),T.has("__seqId")||(b.addSequentialAttrib("__seqId"),ht("__seqId",1)),arguments.length){A=e.slice(0);for(let t of A)t.selected=!0;return w=[A.map(function(t,e){return e})],b.initData(w,T),C.length>2&&b.updateData(w,T,{shouldUpdateColorDomains:!0}),b}return A},b.getSelected=function(){return w[w.length-1].filter(function(t){return A[t].selected}).map(function(t){return A[t]})},b.getVisible=b.getSelected,b.sortBy=function(t,e=!1,n){let o=Math.max(0,void 0!==n&&n<w.length?n:w.length-1);return void 0!==t?(M[o]={attrib:t,desc:e},b.update()):M[o]},b.updateCallback=function(t){return arguments.length?($=t,b):$},b.selectedColorRange=function(t){return arguments.length?(b.defaultColorRangeSelected=t,b):b.defaultColorRangeSelected},b.id=function(t){return arguments.length?(R=t,b):R},b.links=function(t){return arguments.length?(I=t,bt(),b):I},b.getColorScale=function(t){return T.get(t)},b.getAttribs=function(){return C},b.hardUpdate=function(e={}){const n=void 0===e.shouldDrawBrushes||e.shouldDrawBrushes,o=void 0===e.shouldUpdateColorDomains||e.shouldUpdateColorDomains,r=void 0===e.recomputeBrushes||e.recomputeBrushes,i=void 0!==e.levelsToUpdate?e.levelsToUpdate:t.range(w.length);b.updateData(w,T,{shouldDrawBrushes:n,shouldUpdateColorDomains:o,recomputeBrushes:r,levelsToUpdate:i})},function(){(s=void 0===(s="string"==typeof s?t.select(s):s).selectAll?t.select(s):s).selectAll("*").remove();const e=s.on("touchstart",L).on("touchmove",L).style("height",B+"px").attr("class","navio").append("div").style("overflow-x","auto").style("position","relative");e.append("canvas"),f=e.append("svg").style("overflow","visible").style("position","absolute").style("z-index",3).style("top",0).style("left",0),e.append("div").attr("class","explanations").style("overflow","visible").style("position","absolute").style("z-index",5).style("top",b.margin+"px").style("left",b.margin+"px"),t.select("body").on("keydown",U).on("keyup",U),f.append("g").attr("class","attribs"),E(),f.append("g").attr("id","closeButton").style("fill","white").style("stroke","black").style("display","none").append("path").call(function(e){var n=t.path();n.moveTo(0,0),n.lineTo(7,7),n.moveTo(7,0),n.lineTo(0,7),n.moveTo(11.9,3.5),n.arc(3.5,3.5,8.4,0,2*Math.PI),e.attr("d",n.toString())}).on("click",()=>vt()),u=t.scaleBand().range([0,b.attribWidth]).round(!0).paddingInner(.1).paddingOuter(0),g=t.scaleBand().round(!0),T=t.map(),p=function(t,e){return g(e)+u(t)},(m=s.select("canvas").node()).style.top=m.offsetTop+"px",m.style.left=m.offsetLeft+"px",m.style.height=B+"px";const n=window.devicePixelRatio;m.height=B*n,(v=m.getContext("2d")).scale(n,n),v.imageSmoothingEnabled=v.mozImageSmoothingEnabled=v.webkitImageSmoothingEnabled=!1,v.globalCompositeOperation="source-over"}(),b}return c.getAttribsFromObjectRecursive=s,c.getAttribsFromObjectAsFn=d,c});
// https://github.com/john-guerra/Navio#readme v0.0.65 Copyright 2019 John Alexis Guerra Gómez
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("d3"),require("d3-scale-chromatic"),require("popper.js")):"function"==typeof define&&define.amd?define(["d3","d3-scale-chromatic","popper.js"],e):t.navio=e(t.d3,t.d3ScaleChromatic,t.Popper)}(this,function(t,e,n){"use strict";function o(t){const e=t.first,n=t.last,o=t.level,r=t.itemAttr,i=t.getAttrib||(t=>t[r]),l=t.getAttribName||(t=>"function"==typeof t?t.name:t);return{filter:function(t){return t.__i[o]>=e.__i[o]&&t.__i[o]<=n.__i[o]},toStr:function(){let t=`${i(e,r)}`,o=`${i(n,r)}`;return t="string"==typeof t?t.slice(0,5):t,o="string"==typeof o?o.slice(0,5):o,`${l(r)} range including ${t} to ${o}`},type:"range"}}function r(t){const e=t.itemAttr,n=t.sel,o=t.getAttrib||(t=>t[e]),r=t.getAttribName||(t=>"function"==typeof t?t.name:t);return{filter:function(t){return o(t,e)===o(n,e)},toStr:function(){return`${r(e)} == ${o(n,e)}`},type:"value"}}function i(t){const e=t.itemAttr,n=t.sel,o=t.getAttrib||(t=>t[e]),r=t.getAttribName||(t=>"function"==typeof t?t.name:t);return{filter:function(t){return o(t,e)!==o(n,e)},toStr:function(){return`${r(e)} != ${o(n,e)}`},type:"negativeValue"}}function l(t){const e=t.first,n=t.last,o=t.level,r=t.itemAttr,i=t.getAttrib||(t=>t[r]),l=t.getAttribName||(t=>"function"==typeof t?t.name:t);return{filter:function(t){return t.__i[o]<e.__i[o]||t.__i[o]>n.__i[o]},toStr:function(){let t=`${i(e,r)}`,o=`${i(n,r)}`;return t="string"==typeof t?t.slice(0,5):t,o="string"==typeof o?o.slice(0,5):o,`${l(r)} range excluding ${t} to ${o}`},type:"negativeRange"}}function a(t,e){return null==e?null==t?0:1:null==t?-1:(typeof t!=typeof e&&(t=""+t,e=""+e),t<e?-1:t>e?1:t>=e?0:NaN)}n=n&&n.hasOwnProperty("default")?n.default:n;const s=function(t,e=1/0){return function t(n,o){var r,i=[];for(r in n)n.hasOwnProperty(r)&&"__i"!==r&&"__seqId"!==r&&"selected"!==r&&(!(o<e)||Array.isArray(n[r])||null===n[r]||void 0===n[r]||n[r]instanceof Date||typeof n[r]!=typeof{}?i.push([r]):i=i.concat(t(n[r],o+1).map(t=>[r].concat(t))));return i}(t,0)};function d(t,e=1/0){return s(t,e).map(t=>t.length>1?function(t){"string"==typeof t&&(t=t.split("."));let e=t.join("_");const n=t.map(t=>`["${t}"]`).join("");let o=`return function ${e}(d) { try { return d${n} } catch (e) { return undefined }; };`;try{return new Function(o)()}catch(t){return o=`return function ${e=e.replace(/[^a-zA-Z0-9_-]/g,"")}(d) { try { return d${n} } catch (e) { return undefined }; };`,new Function(o)()}}(t):t)}function c(s,c){let u,g,p,f,m,h,v,b,y=this||{},w=[],A=[],I=[],x=[],S=t.map(),C=[],D=t.map(),M=[],z=[],N=[],_=[],B=void 0!==c?c:600,T=t.map(),Z={x:-50,y:-50},R="__seqId",$=function(){},P="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU0LjEgKDc2NDkwKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5jdXJzb3JTdWJzdHJhY3Q8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iY3Vyc29yU3Vic3RyYWN0IiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBkPSJNOSwwLjUgTDcsMC41IEw3LDcgTDAuNSw3IEwwLjUsOSBMNyw5IEw3LDE1LjUgTDksMTUuNSBMOSw5IEwxNS41LDkgTDE1LjUsNyBMOSw3IEw5LDAuNSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHN0cm9rZT0iI0ZGRkZGRiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgICAgIDxyZWN0IGlkPSJSZWN0YW5nbGUiIGZpbGw9IiMwMDAwMDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE1LjAwMDAwMCwgMTUuMDAwMDAwKSByb3RhdGUoLTI3MC4wMDAwMDApIHRyYW5zbGF0ZSgtMTUuMDAwMDAwLCAtMTUuMDAwMDAwKSAiIHg9IjE0IiB5PSIxMSIgd2lkdGg9IjIiIGhlaWdodD0iOCI+PC9yZWN0PgogICAgPC9nPgo8L3N2Zz4=",k="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU0LjEgKDc2NDkwKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5jdXJzb3JBZGQ8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iY3Vyc29yQWRkIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBkPSJNOSwwLjUgTDcsMC41IEw3LDcgTDAuNSw3IEwwLjUsOSBMNyw5IEw3LDE1LjUgTDksMTUuNSBMOSw5IEwxNS41LDkgTDE1LjUsNyBMOSw3IEw5LDAuNSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHN0cm9rZT0iI0ZGRkZGRiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgICAgIDxwYXRoIGQ9Ik0xNiwxNCBMMTksMTQgTDE5LDE2IEwxNiwxNiBMMTYsMTkgTDE0LDE5IEwxNCwxNiBMMTEsMTYgTDExLDE0IEwxNCwxNCBMMTQsMTEgTDE2LDExIEwxNiwxNCBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIGZpbGw9IiMwMDAwMDAiPjwvcGF0aD4KICAgIDwvZz4KPC9zdmc+",E="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU0LjEgKDc2NDkwKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5jdXJzb3I8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iY3Vyc29yIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBkPSJNOSwwLjUgTDcsMC41IEw3LDcgTDAuNSw3IEwwLjUsOSBMNyw5IEw3LDE1LjUgTDksMTUuNSBMOSw5IEwxNS41LDkgTDE1LjUsNyBMOSw3IEw5LDAuNSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHN0cm9rZT0iI0ZGRkZGRiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgPC9nPgo8L3N2Zz4=";function G(){t.event.preventDefault()}function L(){b&&b.remove(),t.select("_nv_popover").remove(),(b=t.select("body").append("div").attr("class","_nv_popover").style("pointer-events","none").style("font-family","sans-serif").style("font-size",y.tooltipFontSize).style("text-align","center").style("background",y.tooltipBgColor).style("position","relative").style("color","black").style("z-index",4).style("border-radius","4px").style("box-shadow","0 0 2px rgba(0,0,0,0.5)").style("padding","10px").style("text-align","center").style("display","none")).append("style").attr("scoped","").text(`\n [x-arrow] {\n width: 0;\n height: 0;\n border-style: solid;\n position: absolute;\n margin: ${y.tooltipArrowSize}px;\n border-color: ${y.tooltipBgColor}\n }\n\n ._nv_popover[x-placement="left"] {\n margin-right: ${y.tooltipArrowSize+y.tooltipMargin}px;\n }\n\n ._nv_popover[x-placement="left"] [x-arrow] {\n border-width: ${y.tooltipArrowSize}px 0 ${y.tooltipArrowSize}px ${y.tooltipArrowSize}px;\n border-top-color: transparent;\n border-right-color: transparent;\n border-bottom-color: transparent;\n right: -${y.tooltipArrowSize}px;\n top: calc(50% - ${y.tooltipArrowSize}px);\n margin-left: 0;\n margin-right: 0;\n }\n\n ._nv_popover[x-placement="right"] {\n margin-left: ${y.tooltipArrowSize+y.tooltipMargin}px;\n }\n\n ._nv_popover[x-placement="right"] [x-arrow] {\n border-width: ${y.tooltipArrowSize}px ${y.tooltipArrowSize}px ${y.tooltipArrowSize}px 0;\n border-left-color: transparent;\n border-top-color: transparent;\n border-bottom-color: transparent;\n left: -${y.tooltipArrowSize}px;\n top: calc(50% - ${y.tooltipArrowSize}px);\n margin-left: 0;\n margin-right: 0;\n }\n\n ._nv_popover[x-placement="bottom"] {\n margin-top: ${y.tooltipArrowSize+y.tooltipMargin}px;\n }\n\n ._nv_popover[x-placement="bottom"] [x-arrow] {\n border-width: 0 ${y.tooltipArrowSize}px ${y.tooltipArrowSize}px ${y.tooltipArrowSize}px;\n border-left-color: transparent;\n border-right-color: transparent;\n border-top-color: transparent;\n top: -${y.tooltipArrowSize}px;\n left: calc(50% - ${y.tooltipArrowSize}px);\n margin-top: 0;\n margin-bottom: 0;\n }\n\n ._nv_popover[x-placement="top"] {\n margin-bottom: ${y.tooltipArrowSize+y.tooltipMargin}px;\n }\n\n ._nv_popover[x-placement="top"] [x-arrow] {\n border-width: ${y.tooltipArrowSize}px ${y.tooltipArrowSize}px 0 ${y.tooltipArrowSize}px;\n border-left-color: transparent;\n border-right-color: transparent;\n border-bottom-color: transparent;\n bottom: -${y.tooltipArrowSize}px;\n left: calc(50% - ${y.tooltipArrowSize}px);\n margin-top: 0;\n margin-bottom: 0;\n }\n\n\n `),b.append("div").attr("class","tool_id"),b.append("div").attr("class","tool_value_name").style("font-weight","bold").style("font-size","120%"),b.append("div").attr("class","tool_value_val").style("max-width","400px").style("max-height","5.5em").style("text-align","left").style("overflow","hidden").style("font-size","90%"),b.append("div").style("font-size","70%").style("margin-top","10px").style("text-align","left").style("color","#777").html("<div>Click to filter a value (<strong>alt</strong> for negative filter).<br>\n Drag for filtering a range.<br> <strong>shift</strong> click for appending to the filters</div>"),b.append("div").attr("x-arrow",""),v=new n({getBoundingClientRect:()=>{const t=f.node().getBoundingClientRect();return{top:Z.y+t.top,right:Z.x+t.left,bottom:Z.y+t.top,left:Z.x+t.left,width:0,height:0}},clientWidth:0,clientHeight:0},b.node(),{placement:"right"})}function U(){"Alt"===t.event.key?t.selectAll(".overlay").attr("cursor",`url(${P}) 8 8, zoom-out`).style("cursor",`url(${P}) 8 8, zoom-out`):"Shift"===t.event.key?t.selectAll(".overlay").attr("cursor",`url(${k}) 8 8, zoom-in`).style("cursor",`url(${k}) 8 8, zoom-in`):t.selectAll(".overlay").style("cursor",`url(${E}) 8 8, crosshair`),"keyup"===t.event.type&&t.selectAll(".overlay").style("cursor",`url(${E}) 8 8, crosshair`)}function O(e){t.select(e).style("cursor","progress"),f.style("cursor","progress")}function j(e){t.select(e).style("cursor",null),f.style("cursor",null)}function F(e,n){var o=e.domain(),r=e.range();return t.scaleQuantize().domain(r).range(o)(n)}function W(t,e){if(!M.hasOwnProperty(t))return;e=void 0!==e?e:A;performance.now();const n=M[t];e[t].sort(function(t,e){return n.desc?function(t,e){return null==e?null==t?0:-1:null==t?1:(typeof t!=typeof e&&(t=""+t,e=""+e),t<e?1:t>e?-1:t>=e?0:NaN)}(Y(w[t],n.attrib),Y(w[e],n.attrib)):a(Y(w[t],n.attrib),Y(w[e],n.attrib))}),q(e[t],t);performance.now()}function V(e){t.event&&t.event.defaultPrevented||(M[e.level]={attrib:e.attrib,desc:void 0!==M[e.level]&&M[e.level].attrib===e.attrib&&!M[e.level].desc},Q(e.level+1),W(e.level),J(e.level),y.updateData(A,T,{levelsToUpdate:[e.level]}),$(y.getVisible()))}function Y(t,e){if("function"!=typeof e)return t[e];try{return e(t)}catch(t){return}}function H(t){return"function"==typeof t&&t.name?t.name:t}function X(t,e){var n,o,r;for(h.save(),o=0;o<C.length;o++){const l=Y(t,n=C[o]),a=H(n);if(r=Math.round(_[e](t[R])+_[e].bandwidth()/2),h.beginPath(),h.moveTo(Math.round(g(a,e)),r),h.lineTo(Math.round(g(a,e)+u.bandwidth()),r),h.lineWidth=Math.ceil(_[e].bandwidth()),h.strokeStyle=null==l||""===l||"none"===l?y.nullColor:T.get(n)(l),h.stroke(),_[e].bandwidth()>2*y.divisionsThreshold){var i=Math.round(_[e](t[R]));h.beginPath(),h.moveTo(g(a,e),i),h.lineTo(g(a,e)+u.bandwidth(),i),h.lineWidth=1,h.strokeStyle=y.divisionsColor,h.stroke()}}h.restore()}function J(e){e<0||t.select("#level"+e).selectAll(".brush").call(z[e].move,null)}function K(t){for(var e=0;e<A.length;e+=1)e!==t&&J(e)}function q(t,e){for(var n=0;n<t.length;n++)w[t[n]].__i[e]=n}function Q(t){for(let e=t;e<N.length;e++)N[e]=N[e].filter(t=>"value"===t.type||"negativeValue"===t.type)}function tt(t,e){let n,o;e=void 0!==e?e:A,n=performance.now();const r=N[t].filter(t=>"negativeValue"===t.type||"negativeRange"===t.type),i=N[t].filter(t=>"negativeValue"!==t.type||"negativeRange"!==t.type);var l=e[t].filter(t=>w[t].selected=i.reduce((e,n)=>e||n.filter(w[t]),!1)&&r.reduce((e,n)=>e&&n.filter(w[t]),!0));return o=performance.now(),l}function et(e){const n=function(){let t=0;for(let e=0;e<N.length&&(t=e,N[e]&&N[e].length);e++);return t}();let o=A;for(let t=e;t<=n;t++){if(!N.hasOwnProperty(t)||!N[t].length){o=ht(t+1,o,{shouldUpdate:!1});break}let e=tt(t,o);q(e,t+1),e.length,y.nestedFilters&&(o[t+1]=e),W(t+1)}y.updateData(o,T,{shouldDrawBrushes:!0,levelsToUpdate:t.range(e,o.length)}),$(y.getVisible())}function nt(e,n){z[n]=t.brushY().extent([[g(u.domain()[0],n),_[n].range()[0]],[g(u.domain()[u.domain().length-1],n)+1.1*u.bandwidth(),_[n].range()[1]]]).on("brush",function(){if(!t.event.sourceEvent)return;if(!t.event.selection)return;const e=t.event.sourceEvent.clientX,o=t.event.sourceEvent.clientY,r=t.event.sourceEvent.offsetX,i=t.event.sourceEvent.offsetY;ot(r,i,e,o,n)}).on("end",function(){if(!t.event.sourceEvent)return;if(!t.event.selection)return;O(this),K(n);performance.now();var e=t.event.selection,r=S.get(F(_[n],e[0])),i=S.get(F(_[n],e[1]));let a;a=t.event.sourceEvent.altKey?new l({first:r,last:i,level:n,itemAttr:M[n]?M[n].attrib:"__seqId",getAttrib:Y,getAttribName:H}):new o({first:r,last:i,level:n,itemAttr:M[n]?M[n].attrib:"__seqId",getAttrib:Y,getAttribName:H});t.event.sourceEvent.shiftKey?(N.hasOwnProperty(n)||(N[n]=[]),N[n].push(a)):N[n]=[a];Q(n+1),et(n);performance.now();j(this)});var a=t.select(this).selectAll(".brush").data([{data:e.map(t=>w[t]),level:n}]);a.enter().merge(a).append("g").on("mousemove",rt).on("click",function(){O(this);var e=t.mouse(t.event.target)[1];(function(e,o){K(-1);performance.now();const l=F(_[n],o);performance.now();let a=F(u,e-p(n));if(void 0===a)return void console.log(`navio.selectByValue: error, couldn't find attr in coords ${o}`);a=D.get(a);const s=S.get(l);let d;d=t.event.altKey?new i({sel:s,itemAttr:a,getAttrib:Y,getAttribName:H}):new r({sel:s,itemAttr:a,getAttrib:Y,getAttribName:H});t.event.shiftKey?(N.hasOwnProperty(n)||(N[n]=[]),N[n].push(d)):N[n]=[d];Q(n+1),et(n)})(t.mouse(t.event.target)[0],e),j(this)}).on("mouseout",it).attr("class","brush").call(z[n]).selectAll("rect").attr("width",g(u.domain()[u.domain().length-1],n)+1.1*u.bandwidth()),a.exit().remove()}function ot(t,e,n,o,r){let i;try{i=F(_[r],e)}catch(t){return}let l=F(u,t-p(r));const a=S.get(i);l=D.get(l),a&&void 0!==a?(Z.x=t,Z.y=e,b.select(".tool_id").text(i),b.select(".tool_value_name").text(H(l)),b.select(".tool_value_val").text(Y(a,l)),b.style("display","initial"),v.scheduleUpdate()):console.log("Couldn't find datum for tooltip y",e,a)}function rt(e){const n=t.mouse(t.event.target)[0],o=t.mouse(t.event.target)[1];t.event.clientX,t.event.clientY;e.data&&0!==e.data.length&&ot(n,o,0,0,e.level)}function it(){Z.x=-200,Z.y=-200,b.style("display","none"),v.scheduleUpdate()}function lt(t,e){const n=u.domain()[u.domain().length-1],o=e.append("g").attr("class","filterExplanation");o.merge(t.select(".filterExplanation")).attr("transform",(t,e)=>`translate(${(t=>g(n,t)+u.bandwidth()+2)(e)}, ${_[e].range()[1]+1.2*y.filterFontSize})`),o.append("rect").merge(t.select("rect.bgExplanation")).attr("class","bgExplanation").style("fill","white").attr("x",0).attr("y",.3*y.filterFontSize).attr("width",p.bandwidth()).attr("height",(t,e)=>N[e]?N[e].length*y.filterFontSize*1.3:0);const r=o.append("text").merge(t.select(".filterExplanation > text")).style("font-size",y.filterFontSize+"pt").selectAll("tspan").data((t,e)=>N[e]?N[e].map(t=>(t.level=e,t)):[]);r.enter().append("tspan").merge(r).attr("dy",1.2*y.filterFontSize+7).attr("x",0).style("cursor","not-allowed").text(t=>"Ⓧ "+t.toStr()).on("click",(t,e)=>{console.log("Click remove filter",e,t),N[t.level].splice(e,1),et(t.level)}),r.exit().remove()}function at(e,n){var o;y.showAttribTitles&&n.append("text").merge(e.select("text")).style("cursor","point").style("-webkit-user-select","none").style("-moz-user-select","none").style("-ms-user-select","none").style("user-select","none").text(function(t){return"__seqId"===t.attrib?"sequential Index":t.name+(void 0!==M[t.level]&&M[t.level].attrib===t.attrib?M[t.level].desc?" ↓":" ↑":"")}).attr("x",u.bandwidth()/2).attr("y",0).style("font-weight",function(t){return void 0!==M[t.level]&&M[t.level].attrib===t.attrib?"bolder":"normal"}).style("font-family","sans-serif").style("font-size",function(){return Math.min(y.attribFontSize,y.attribWidth)+"px"}).on("click",(o=V,function(t,e,n){O(this),requestAnimationFrame(()=>{o(t,e,n),j(this)})})).call(t.drag().container(n.merge(e).node()).on("start",dt).on("drag",ct).on("end",ut)).on("mousemove",function(){var e=t.select(this);(e=void 0!==e.transition?e.transition().duration(150):e).style("font-size",y.attribFontSizeSelected+"px")}).on("mouseout",function(){var e=t.select(this);(e=void 0!==e.transition?e.transition().duration(150):e).style("font-size",Math.min(y.attribFontSize,y.attribWidth)+"px")}).attr("transform",`rotate(${y.attribRotation})`)}function st(t){var e=f.select(".attribs").selectAll(".levelOverlay").data(A),n=e.enter().append("g");n.attr("class","levelOverlay").attr("id",function(t,e){return"level"+e}),t?n.merge(e).each(nt):n.each(nt),function(t,e){var n=C,o=e.merge(t).selectAll(".attribOverlay").data(function(t,e){return n.map(function(t){return{attrib:t,name:H(t),level:e}})}),r=o.enter().append("g").attr("class","attribOverlay").style("cursor","pointer");r.merge(o).attr("transform",t=>`translate(${g(t.name,t.level)}, ${_[t.level].range()[0]})`),r.append("rect").merge(o.select("rect")).attr("fill","none").attr("x",0).attr("y",0).attr("width",function(){return 1.1*u.bandwidth()}).attr("height",function(t){return _[t.level].range()[1]-_[t.level].range()[0]}),at(o,r),o.exit().remove()}(e,n),function(t,e){e.append("text").merge(t.select("text.numNodesLabel")).attr("class","numNodesLabel").style("font-family","sans-serif").style("pointer-events","none").attr("y",function(t,e){return _[e].range()[1]+15}).attr("x",function(t,e){return p(e)}).text(function(t){return y.fmtCounts(t.length)})}(e,n),lt(e,n),e.exit().remove()}function dt(e){t.event.sourceEvent.shiftKey&&t.select(this.parentNode).attr("transform",function(e){return"translate("+(t.event.x+y.attribFontSize/2)+","+_[e.level].range()[0]+")"})}function ct(){t.event.sourceEvent.shiftKey&&t.select(this.parentNode).attr("transform",function(e){return"translate("+(t.event.x+y.attribFontSize/2)+","+_[e.level].range()[0]+")"})}function ut(e){if(!t.event.sourceEvent.shiftKey)return;let n=F(u,t.event.x+y.attribFontSize/2-p(e.level));var o;n=D.get(n),t.select(this.parentNode).attr("transform",function(t){return"translate("+g(t.name,t.level)+","+_[t.level].range()[0]+")"}),n!==e.attrib&&(o=C.indexOf(n),vt(e.attrib,o),y.updateData(A))}function gt(t){var e=u.domain()[u.domain().length-1],n=g(e,A.length-1)+u.bandwidth()+2,o=_[A.length-1](t.source[R])+_[A.length-1].bandwidth()/2,r=_[A.length-1](t.target[R])+_[A.length-1].bandwidth()/2,i=Math.min(o,r),l=Math.max(o,r),a=l-i;h.moveTo(n,i),h.quadraticCurveTo(n+a/6,i+a/2,n,l)}function pt(t,e,n,o){h.beginPath();for(let e=0;e<t.length;e++){const n=t[e];0===e?h.moveTo(n.x,n.y):h.lineTo(n.x,n.y)}h.lineWidth=e,o?(h.fillStyle=n,h.closePath(),h.fill()):(h.strokeStyle=n,h.stroke())}function ft(t){let e=[];if(A[t].length>B){const n=Math.max(Math.floor(A[t].length/(2*B)),1);A[t].itemsPerpixel=n;for(let o=0;o<A[t].length;o+=n)e.push(A[t][o])}else A[t].itemsPerpixel=1,e=A[t];return A[t].representatives=e,e}function mt(e){let{levelsToUpdate:n,shouldUpdateColorDomains:o}=e||{};performance.now();const r=A.length-1;n=void 0!==n?n:[r],o=void 0!==o&&o,_.splice(r+1,_.length);for(let e of n){_[e]=t.scaleBand().range([y.y0,B-y.margin-30]).paddingInner(0).paddingOuter(0);const n=ft(e);_[e].domain(n.map(function(t){return w[t][R]}))}u.domain(C.map(t=>H(t))).range([0,y.attribWidth*D.keys().length]).paddingInner(.1).paddingOuter(0),p.domain(A.map(function(t,e){return e})).range([y.x0+y.margin,(u.range()[1]+y.levelsSeparation)*A.length+y.x0]).paddingInner(0).paddingOuter(0),o&&function(){for(let n of C)if("selected"!==n){var e=T.get(n);if("seq"===e.__type||"date"===e.__type)e.domain(t.extent(A[0].map(function(t){return Y(w[t],n)})));else if("div"===e.__type){const[o,r]=t.extent(A[0].map(function(t){return Y(w[t],n)})),i=Math.max(-o,r);e.domain([-i,i])}else"text"!==e.__type&&"ordered"!==e.__type||e.domain(A[0].map(t=>Y(w[t],n)));T.set(H(n),e)}}();performance.now()}function ht(t,e,n){if(A.length<=1)return;let{shouldUpdate:o}=n||{},r=void 0!==t?t:A.length-1;if(o=void 0===o||o,!(e=void 0!==e?e:A).hasOwnProperty(r))return e;if(O(this),r>0){J(r-1);for(let t of e[r-1])w[t].selected=!0;if(N.hasOwnProperty(r-1)&&N[r-1].length)for(let t=0;t<N[r-1].length;t++)delete N[r-1][t];N[r-1]=[]}return e.splice(r),o&&(y.updateData(e,T),$(y.getVisible())),j(this),e}function vt(t,e){var n=C.indexOf(t);-1!==n?e>C.length||e<0?console.log("moveAttrToPos pos out of bounds",e,C.length):(C.splice(n,1),C.splice(e,0,t)):console.log("moveAttrToPos attr not found",t)}function bt(t,e){let n,o;for(n=0;n<y.howManyItemsShouldSearchForNotNull&&n<t.length;n++)if(null!=(o="function"==typeof e?e(t[n]):t[n][e])&&""!==o)return o;return o}function yt(){I.length>0&&(x=I.filter(function(t){return t.source.selected&&t.target.selected}))}function wt(t,e){!function(t){h.save(),h.beginPath(),h.rect(p(t),_[t].range()[0]-1,u.range()[1]+1,_[t].range()[1]+2-_[t].range()[0]),h.strokeStyle="black",h.lineWidth=1,h.stroke(),h.restore()}(e);for(let n of t.representatives)X(w[n],e);!function(t){if(!(t<=0))for(let l of A[t].representatives){var e=S.get(w[l][R]).__i[t-1],n=Math.floor(e-e%A[t-1].itemsPerpixel),o={x:p(t-1)+u.range()[1],y:_[t-1](w[A[t-1][n]][R])},r={x:p(t),y:_[t](w[l][R])},i=[o,{x:o.x+.3*y.levelsSeparation,y:o.y},{x:r.x-.3*y.levelsSeparation,y:r.y},r,{x:r.x,y:r.y+_[t].bandwidth()},{x:r.x-.3*y.levelsSeparation,y:r.y+_[t].bandwidth()},{x:o.x+.3*y.levelsSeparation,y:o.y+_[t-1].bandwidth()},{x:o.x,y:o.y+_[t-1].bandwidth()},o];pt(i,1,y.levelConnectionsColor),pt(i,1,y.levelConnectionsColor,!0)}}(e)}return y.x0=0,y.y0=100,y.maxNumDistictForCategorical=10,y.maxNumDistictForOrdered=90,y.howManyItemsShouldSearchForNotNull=100,y.margin=10,y.levelsSeparation=40,y.divisionsColor="white",y.nullColor="#ffedfd",y.levelConnectionsColor="rgba(205, 220, 163, 0.5)",y.divisionsThreshold=4,y.fmtCounts=t.format(",.0d"),y.legendFont="14px sans-serif",y.linkColor="#ccc",y.nestedFilters=!0,y.showAttribTitles=!0,y.attribWidth=15,y.attribRotation=-45,y.attribFontSize=13,y.attribFontSizeSelected=32,y.filterFontSize=8,y.tooltipFontSize=12,y.tooltipBgColor="#b2ddf1",y.tooltipMargin=50,y.tooltipArrowSize=10,y.addAllAttribsRecursionLevel=1/0,y.addAllAttribsIncludeObjects=!1,y.addAllAttribsIncludeArrays=!1,y.digitsForText=2,y.defaultColorInterpolator="interpolateBlues"in t?t.interpolateBlues:e.interpolateBlues,y.defaultColorInterpolatorDate="interpolatePurples"in t?t.interpolatePurples:e.interpolatePurples,y.defaultColorInterpolatorDiverging="interpolateBrBG"in t?t.interpolateBrBG:e.interpolateBrBG,y.defaultColorInterpolatorOrdered="interpolateOranges"in t?t.interpolateOranges:e.interpolateOranges,y.defaultColorInterpolatorText="interpolateGreys"in t?t.interpolateGreys:e.interpolateGreys,y.defaultColorRangeBoolean=["#a1d76a","#e9a3c9","white"],y.defaultColorRangeSelected=["white","#b5cf6b"],y.defaultColorCategorical=t.schemeCategory10,y.initData=function(e,n){performance.now();T=n,S=t.map();for(let t=0;t<w.length;t++){const e=w[t];e.__seqId=t,S.set(e[R],e),e.__i=[],e.__i[0]=t}(N=[])[0]=[];performance.now()},y.updateData=function(e,n,o){const{levelsToUpdate:r,shouldUpdateColorDomains:i,shouldDrawBrushes:l,recomputeBrushes:a}=o||{};performance.now();if(typeof e==typeof[]){T=void 0!==n?n:T,A=e,N.splice(e.length),N[e.length]=[],yt(),z.splice(e.length),mt({levelsToUpdate:r,shouldUpdateColorDomains:i}),function(){const e=p.range()[1]+y.margin+y.x0;t.select(m).attr("width",e).attr("height",B).style("width",e).style("height",B+"px"),m.style.width=e+"px",m.style.height=B+"px",f.attr("width",e).attr("height",B)}(),y.update({levelsToUpdate:r,shouldDrawBrushes:l,recomputeBrushes:a});performance.now()}else console.log("navio updateData didn't receive an array")},y.update=function(t){let{recomputeBrushes:e,shouldDrawBrushes:n}=t||{};if(!A.length)return y;e=void 0!==e&&e,n=void 0===n||n;performance.now();var o,r=p.range()[1]+y.margin+y.x0;h.clearRect(0,0,r+1,B+1),function(){if(I.length){h.save(),h.beginPath(),h.strokeStyle=y.linkColor,h.globalAlpha=Math.min(1,Math.max(.1,1e3/I[I.length-1].length));for(let t of x)gt(t);h.stroke(),h.restore()}}();for(let t=0;t<A.length;t++)wt(A[t],t);n&&(st(e),o=A.length-1,f.select("#closeButton").style("display",1===A.length?"none":"block").attr("transform","translate("+(p(o)+p.bandwidth()-y.levelsSeparation+15)+","+_[o].range()[0]+")"));performance.now();return y},y.addAttrib=function(e,n){if(void 0===n&&(n=t.scaleOrdinal(t.schemeCategory10)),!D.has(H(e)))return C.push(e),D.set(H(e),e),T.set(e,n),y;console.log(`navio.addAttrib attribute ${e} already added`)},y.addSequentialAttrib=function(e,n){const o=void 0!==w&&w.length>0?t.extent(w,function(t){return Y(t,e)}):[0,1],r=n||t.scaleSequential(y.defaultColorInterpolator).domain(o);return r.__type="seq",y.addAttrib(e,r),y},y.addDateAttrib=function(e,n){const o=void 0!==w&&w.length>0?t.extent(w,function(t){return Y(t,e)}):[0,1],r=n||t.scaleSequential(y.defaultColorInterpolatorDate).domain(o);return y.addAttrib(e,r),r.__type="date",y},y.addDivergingAttrib=function(e,n){const o=void 0!==w&&w.length>0?t.extent(w,function(t){return Y(t,e)}):[-1,1],r=n||t.scaleSequential(y.defaultColorInterpolatorDiverging).domain([o[0],o[1]]);return r.__type="div",y.addAttrib(e,r),y},y.addCategoricalAttrib=function(e,n){const o=n||t.scaleOrdinal(y.defaultColorCategorical);return o.__type="cat",y.addAttrib(e,o),y},y.addTextAttrib=function(e,n){const o=n||function(e,n=1,o){let r=t.scaleSequential(o),i=t.map(),l=t.map();function a(t){"string"!=typeof t&&(t+="");let o=l.get(t.slice(0,n));return void 0===o&&(console.log(`scaleText Couldn't find index for ${t} did you call domain? Using ascii of first letter`),o=t.charCodeAt(0)),r(o)||e}function s(e,n=!0){i=t.map();for(let t of e)i.has(t)||i.set(t,0),i.set(t,i.get(t)+1);const o={counts:i};if(n){l=t.map();let e=0;for(let t of i.keys().sort())l.set(t,e++);o.indexes=l}return o}return a.digits=function(t){return arguments.length?(n=t,a):n},a.scale=function(t){return arguments.length?(r=t,a):r},a.domain=function(t){return arguments.length?(s(t.map(t=>(""+t).slice(0,n))),r.domain([0,i.keys().length]),a):r.domain()},a.computeRepresentatives=s,a.__type="text",a}(y.nullColor,y.digitsForText,y.defaultColorInterpolatorText);return y.addAttrib(e,o),y},y.addOrderedAttrib=function(e,n){const o=n||function(e,n){let o=t.scaleOrdinal();function r(t){return null==t?e:o(t)}function i(t){const e=[];let n=null;for(let o of t.sort((t,e)=>a(t,e)))n!==o&&(e.push(o),n=o);return e}return r.domain=function(t){if(arguments.length){const e=i(t);return o.domain(e).range(e.map((t,o)=>n(o/e.length))),r}return o.domain()},r.computeRepresentatives=i,r.__type="ordered",r}(y.nullColor,y.defaultColorInterpolatorOrdered);return y.addAttrib(e,o),y},y.addBooleanAttrib=function(e,n){const o=n||t.scaleOrdinal().domain([!0,!1,null]).range(y.defaultColorRangeBoolean);return o.__type="bool",y.addAttrib(e,o),y},y.addAllAttribs=function(e){if(!w||!w.length)throw Error("addAllAttribs called without data to guess the attribs. Make sure to call it after setting the data");var n=void 0!==e?e:d(w[0],y.addAllAttribsRecursionLevel);for(let e of n){if("__seqId"===e||"__i"===e||"selected"===e)continue;const n="function"==typeof e?e.name:e,o=bt(w,e);if(null==o||"string"==typeof o){const o=t.set(w.slice(0,y.howManyItemsShouldSearchForNotNull).map(t=>Y(t,e))).values().length;o<y.maxNumDistictForCategorical?(console.log(`Navio: Adding attr ${n} as categorical with ${o} categories`),y.addCategoricalAttrib(e)):o<y.maxNumDistictForOrdered?(y.addOrderedAttrib(e),console.log(`Navio: Attr ${n} has more than ${y.maxNumDistictForCategorical} distinct values (${o}) using orderedAttrib`)):(console.log(`Navio: Attr ${n} has more than ${y.maxNumDistictForOrdered} distinct values (${o}) using textAttrib`),y.addTextAttrib(e))}else"number"==typeof o?t.min(w,t=>Y(t,e))<0?(console.log(`Navio: Adding attr ${n} as diverging`),y.addDivergingAttrib(e)):(console.log(`Navio: Adding attr ${n} as sequential`),y.addSequentialAttrib(e)):o instanceof Date?(console.log(`Navio: Adding attr ${n} as date`),y.addDateAttrib(e)):typeof o==typeof!0?(console.log(`Navio: Adding attr ${n} as boolean`),y.addBooleanAttrib(e)):Array.isArray(o)?y.addAllAttribsIncludeArrays?(console.log(`Navio: Adding ${n} adding as categorical (type=array)`),y.addCategoricalAttrib(e)):console.log(`Navio: AddAllAttribs detected array ${n}, but ignoring it. To include it set nv.addAllAttribsIncludeArrays=true`):y.addAllAttribsIncludeObjects?(console.log(`Navio: Adding object ${n} adding as categorical (type=object)`),y.addCategoricalAttrib(e)):console.log(`Navio: AddAllAttribs detected object ${n}, but ignoring it. To include it set nv.addAllAttribsIncludeObjects=true`)}return y.data(w),y},y.data=function(e){if(L(),T.has("selected")||(y.addAttrib("selected",t.scaleOrdinal().domain([!1,!0]).range(y.defaultColorRangeSelected)),vt("selected",0)),T.has("__seqId")||(y.addSequentialAttrib("__seqId"),vt("__seqId",1)),arguments.length){w=e.slice(0);for(let t of w)t.selected=!0;return A=[w.map(function(t,e){return e})],y.initData(A,T),C.length>2&&y.updateData(A,T,{shouldUpdateColorDomains:!0}),y}return w},y.getSelected=function(){return A[A.length-1].filter(function(t){return w[t].selected}).map(function(t){return w[t]})},y.getVisible=y.getSelected,y.sortBy=function(t,e=!1,n){let o=Math.max(0,void 0!==n&&n<A.length?n:A.length-1);return void 0!==t?(M[o]={attrib:t,desc:e},y.update()):M[o]},y.updateCallback=function(t){return arguments.length?($=t,y):$},y.selectedColorRange=function(t){return arguments.length?(y.defaultColorRangeSelected=t,y):y.defaultColorRangeSelected},y.id=function(t){return arguments.length?(R=t,y):R},y.links=function(t){return arguments.length?(I=t,yt(),y):I},y.getColorScale=function(t){return T.get(t)},y.getAttribs=function(){return C},y.hardUpdate=function(e={}){const n=void 0===e.shouldDrawBrushes||e.shouldDrawBrushes,o=void 0===e.shouldUpdateColorDomains||e.shouldUpdateColorDomains,r=void 0===e.recomputeBrushes||e.recomputeBrushes,i=void 0!==e.levelsToUpdate?e.levelsToUpdate:t.range(A.length);y.updateData(A,T,{shouldDrawBrushes:n,shouldUpdateColorDomains:o,recomputeBrushes:r,levelsToUpdate:i})},function(){(s=void 0===(s="string"==typeof s?t.select(s):s).selectAll?t.select(s):s).selectAll("*").remove();const e=s.on("touchstart",G).on("touchmove",G).style("height",B+"px").attr("class","navio").append("div").style("overflow-x","auto").style("position","relative");e.append("canvas"),f=e.append("svg").style("overflow","visible").style("position","absolute").style("z-index",3).style("top",0).style("left",0),t.select("body").on("keydown",U).on("keyup",U),f.append("g").attr("class","attribs"),L(),f.append("g").attr("id","closeButton").style("fill","white").style("stroke","black").style("display","none").append("path").call(function(e){var n=t.path();n.moveTo(0,0),n.lineTo(7,7),n.moveTo(7,0),n.lineTo(0,7),n.moveTo(11.9,3.5),n.arc(3.5,3.5,8.4,0,2*Math.PI),e.attr("d",n.toString())}).on("click",()=>ht()),u=t.scaleBand().range([0,y.attribWidth]).round(!0).paddingInner(.1).paddingOuter(0),p=t.scaleBand().round(!0),T=t.map(),g=function(t,e){return p(e)+u(t)},(m=s.select("canvas").node()).style.top=m.offsetTop+"px",m.style.left=m.offsetLeft+"px",m.style.height=B+"px";const n=window.devicePixelRatio;m.height=B*n,(h=m.getContext("2d")).scale(n,n),h.imageSmoothingEnabled=h.mozImageSmoothingEnabled=h.webkitImageSmoothingEnabled=!1,h.globalCompositeOperation="source-over"}(),y}return c.getAttribsFromObjectRecursive=s,c.getAttribsFromObjectAsFn=d,c});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment