Public
Edited
Oct 26, 2024
Paused
Fork of Navio
8 forks
15 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
nv = {
data; // This is to force this cell to redraw when data changes. Only for observable

const nv = navio(d3.select(div), height);

nv.y0 = 180;
nv.margin = 30;
nv.attribWidth = attribWidth;
if (pinnataMode) {
nv.defaultColorCategorical = d3.schemeCategory10
.concat(d3.schemeAccent)
.concat(d3.schemePastel1)
.concat(d3.schemeSet2)
.concat(d3.schemeSet3);
nv.maxNumDistictForCategorical = nv.defaultColorCategorical.length;
}
console.log("data");
// Add the data
nv.data(data);
// Add these attribs, based on their types
nv.addAllAttribs(selectedAttributes.map(attr => dAttribs.get(attr)));
// Set the initial visible elements, and setup a callback for when selecting new items
mutable selected = nv.getVisible();
nv.updateCallback(() => mutable selected = nv.getVisible());
return nv;
}
Insert cell
// {
// 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 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 = d3.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 = 55; // 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 = 10; // 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.id("attribName"); // Shows this id on the tooltip, should be unique
// }
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof x_attrib = select({
title: "x_attrib",
options: selectedAttributes,
value: selectedAttributes[0]
})
Insert cell
viewof y_attrib = select({
title: "y_attrib",
options: selectedAttributes,
value: selectedAttributes[1]
})
Insert cell
viewof c_attrib = select({
title: "color_attrib",
options: selectedAttributes,
value: selectedAttributes[2]
})
Insert cell
viewof x_type = select({
title: "x_type",
options: ["quantitative", "ordinal", "nominal"],
value: typeof(data[0][x_attrib]) === typeof(0) ? "quantitative": "nominal"
})
Insert cell
viewof y_type = select({
title: "y_type",
options: ["quantitative", "ordinal", "nominal", "temporal"],
value: typeof(data[0][y_attrib]) === typeof(0) ? "quantitative": "nominal"
})
Insert cell
viewof c_type = select({
title: "color_type",
options: ["quantitative", "ordinal", "nominal"],
value: typeof(data[0][c_attrib]) === typeof(0) ? "quantitative": "nominal"
})
Insert cell
onDemandVisualization = ({
data : { values: selected},
mark: "circle",
title: "Selected rows",
encoding: {
x : { field: x_attrib, type: x_type},
y : { field: y_attrib, type: y_type},
color : { field: c_attrib, type: c_type}
}
})
Insert cell
Insert cell
Insert cell
dAttribs = {

const dAttribs = new Map();
// Try to get the attributes from the first 100 records
const attributes = data.slice(0,100)
.reduce((res,d) =>
res.concat(checkRecursive ? navio.getAttribsFromObjectAsFn(d, recursionLevel) : Object.keys(d)), [])
.filter(a => ["__seqId", "selected", "__i"].indexOf(a)===-1);

// console.log("***attribs", attributes, data[0]);
for (let attr of attributes) {
if (typeof(attr)==="function")
dAttribs.set(attr.name, attr);
else
dAttribs.set(attr, attr);
}
return dAttribs;
}
Insert cell
attributes = Array.from(dAttribs.keys());
Insert cell
viewof selectedAttributes = searchCheckbox(attributes, {
value: attributes,
label: "Attributes"
})
Insert cell
viewof noneButton = {
const button = html`<button>None</button>`;
d3.select(button)
.on("click", () => {
console.log("click");
d3.select(viewof selectedAttributes).selectAll("input").property("checked", false);
(viewof selectedAttributes).dispatchEvent(new Event('change'));
});
return button;
}
Insert cell
viewof allButton = {
const button = html`<button>All</button>`;
d3.select(button)
.on("click", () => {
console.log("click");
d3.select(viewof selectedAttributes).selectAll("input").property("checked", true);
(viewof selectedAttributes).dispatchEvent(new Event('change'));
});
return button;
}
Insert cell
viewof attribWidth = slider({
min: 1,
max: 50,
value: 15,
step: 1,
title: "Attribute width"
})
Insert cell
viewof pinnataMode = checkbox({
title: "More categorical Colors (Piñata mode 🎉)",
options:[{value:true, label:"☢️"}]
})
Insert cell
Insert cell
viewof delimiter = select({
title: "Delimiter",
options:[
",",
";",
"¬",
{value:"\t", label:"Tab"}],
value:","
})
Insert cell
viewof checkRecursive = checkbox({
options:[{value:false, label:"Exand object attributes recursively"}]
})
Insert cell
viewof recursionLevel = slider({
value:1,
max:10,
step:1,
title: "Recursion Level"
})
Insert cell
viewof save = DOM.download(
new Blob([d3.csvFormat(copyOnlySelectedAttrs(selected))], {type: "text/csv"}),
"export.csv",
`Export ${selected.length} selected rows`
)
Insert cell
viewof saveJSON = DOM.download(
new Blob([JSON.stringify(copyOnlySelectedAttrs(selected))], {type: "text/json"}),
"export.json",
`Export ${selected.length} selected rows as JSON`
)
Insert cell
copyOnlySelectedAttrs = (data) => data.map((d) => {
let res = {};
for (let att in d) {
if (d.hasOwnProperty(att) && selectedAttributes.indexOf(att)!=-1)
res[att] = d[att];
}
return res;
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// import {dataInput} from "@john-guerra/file-input-with-default-value"
Insert cell
import {searchCheckbox} from "@john-guerra/search-checkbox"
Insert cell
import {dataInput} from "@john-guerra/data-input"
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more