@springernature/nn-charts
Version:
Visualization for DAS products
1,316 lines (933 loc) • 87.9 kB
JavaScript
"use strict";
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.addDelaunayInteractionLayer = addDelaunayInteractionLayer;
exports.alertSize = alertSize;
exports.appendAxis = appendAxis;
exports.appendAxisReferenceLines = appendAxisReferenceLines;
exports.appendAxisThickLine = appendAxisThickLine;
exports.appendAxisTitle = appendAxisTitle;
exports.appendBaseGroupForDataElements = appendBaseGroupForDataElements;
exports.appendCategoryLegend = appendCategoryLegend;
exports.appendChartClipRect = appendChartClipRect;
exports.appendDataBoundingRects = appendDataBoundingRects;
exports.appendDataCircles = appendDataCircles;
exports.appendDataLabels = appendDataLabels;
exports.appendMockZoomControlButtons = appendMockZoomControlButtons;
exports.appendQuadrantLabels = appendQuadrantLabels;
exports.appendScaleLegend = appendScaleLegend;
exports.appendScaleLegendHTML = appendScaleLegendHTML;
exports.appendXAxisGridLines = appendXAxisGridLines;
exports.appendYAxisGridLines = appendYAxisGridLines;
exports.appendedEntitiestoSelectionList = appendedEntitiestoSelectionList;
exports.brushended = brushended;
exports.calculateDistance = calculateDistance;
exports.callAxisUpdate = callAxisUpdate;
exports.compareStrings = compareStrings;
exports.createCategorisedData = createCategorisedData;
exports.createCircleRadiusScalingLaw = createCircleRadiusScalingLaw;
exports.createColourPalette = createColourPalette;
exports.createLinearXAxis = createLinearXAxis;
exports.createLinearYAxis = createLinearYAxis;
exports.createUsableID = createUsableID;
exports.deleteJSONArrayElement = deleteJSONArrayElement;
exports.determineMaximumValueOfRequiredScalingAttribute = determineMaximumValueOfRequiredScalingAttribute;
exports.determineUserInteractionMaskedLayerSolution = determineUserInteractionMaskedLayerSolution;
exports.end_brush_tool = end_brush_tool;
exports.generateConsistentLegendSizes = generateConsistentLegendSizes;
exports.getClientBoundingRectForElements = getClientBoundingRectForElements;
exports.getData = getData;
exports.getDataFieldColumns = getDataFieldColumns;
exports.getDataPointBoundaries = getDataPointBoundaries;
exports.getDefaultEntityData = getDefaultEntityData;
exports.getMaxStatedDimensionFromElement = getMaxStatedDimensionFromElement;
exports.getMaxStatedDimensionFromElementsGroup = getMaxStatedDimensionFromElementsGroup;
exports.getMaximumDataValueFromKey = getMaximumDataValueFromKey;
exports.getMinimumDataValueFromKey = getMinimumDataValueFromKey;
exports.idled = idled;
exports.modifyAxisTickClasses = modifyAxisTickClasses;
exports.positionAxis = positionAxis;
exports.repositionWholeChart = repositionWholeChart;
exports.scatterBubbleOnWindowResize = scatterBubbleOnWindowResize;
exports.scatterBubbleUserMouseClick = scatterBubbleUserMouseClick;
exports.scatterBubbleUserMouseMove = scatterBubbleUserMouseMove;
exports.scatterBubbleUserMouseOver = scatterBubbleUserMouseOver;
exports.setChartHeight = setChartHeight;
exports.setChartWidth = setChartWidth;
exports.setContainerWidth = setContainerWidth;
exports.sortData = sortData;
exports.start_brush_tool = start_brush_tool;
exports.submit_selections = submit_selections;
exports.transitionAxis = transitionAxis;
exports.transitionBoundingRects = transitionBoundingRects;
exports.transitionChart = transitionChart;
exports.transitionQuadrantLabels = transitionQuadrantLabels;
exports.updateAttributeOfElement = updateAttributeOfElement;
exports.updateChart = updateChart;
exports.updateChartWithNewSelection = updateChartWithNewSelection;
exports.updateLinearXAxisRange = updateLinearXAxisRange;
exports.updatePreviousXAxisTitleState = updatePreviousXAxisTitleState;
exports.updateScaleBandAxisRange = updateScaleBandAxisRange;
exports.zoom_specific_data = zoom_specific_data;
exports.zoomhandler = zoomhandler;
var d3 = _interopRequireWildcard(require("d3"));
var _config = require("./config");
var _d3Delaunay = require("d3-delaunay");
var _common = require("../../utils/common");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
/*
FUNCTIONS FUNCTIONS FUNCTIONS / METHODS METHODS METHODS
*/
/*
*/
function setContainerWidth(cf) {
// // set the width dimension of the DIV container
return cf.browserWidth;
//
}
/*
*/
function setChartHeight(cf) {
// set the height dimension of the graph
return cf.containerHeight - cf.chartMargin.top - cf.chartMargin.bottom;
}
/*
*/
function setChartWidth(cf, needMargins) {
return needMargins == "margins" ? cf.containerWidth - cf.chartMargin.left - cf.chartMargin.right : cf.containerWidth;
}
/*
browser window screen widths and heights
https://andylangton.co.uk/blog/development/get-viewportwindow-size-width-and-height-javascript
http://ryanve.com/lab/dimensions/
If you are using jQuery, you can get the size of the window or the document using jQuery methods:
$(window).height(); // returns height of browser viewport
$(document).height(); // returns height of HTML document (same as pageHeight in screenshot)
$(window).width(); // returns width of browser viewport
$(document).width(); // returns width of HTML document (same as pageWidth in screenshot)
For screen size you can use the screen object in the following way:
screen.height;
screen.width;
*/
function alertSize() {
var myWidth = 0;
var myHeight = 0;
if (typeof window.innerWidth == "number") {
//Non-IE
myWidth = window.innerWidth;
myHeight = window.innerHeight;
} else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
//IE 6+ in 'standards compliant mode'
myWidth = document.documentElement.clientWidth;
myHeight = document.documentElement.clientHeight;
} else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
//IE 4 compatible
myWidth = document.body.clientWidth;
myHeight = document.body.clientHeight;
}
_config.cf.browserWidth = myWidth;
_config.cf.browserHeight = myHeight;
return;
} // end function
/*
*/
function getData(data) {
return data.slice(0);
}
/*
*/
function getDataFieldColumns(data) {
return data.columns;
}
/*
*/
function determineMaximumValueOfRequiredScalingAttribute(cf) {
return +d3.max(cf.data, function (d) {
return +d[cf.circleRadiusAttributeField];
});
}
/*
*/
function sortData(data, sortOrder, sortField) {
//
return sortOrder == "ascending" ? data.slice(0).sort(function (a, b) {
return d3.ascending(+a[sortField], +b[sortField]);
}) : data.slice(0).sort(function (a, b) {
return d3.descending(+a[sortField], +b[sortField]);
});
}
/*
*/
function createCircleRadiusScalingLaw(cf) {
// [re]calculate CircleRadiusScale if two-integer array is defined in config
if (cf.legend.scaleLegend.circleRadiusScaleRange.length === 2) {
//
// define scaling law to implement on h-index
return d3.scalePow().exponent(0.5).domain([0, cf.maxScalingValue]).range([cf.legend.scaleLegend.circleRadiusScaleRange[0], cf.legend.scaleLegend.circleRadiusScaleRange[1]]);
} // end if ...
}
/*
*/
function createCategorisedData(data, categoryField) {
//
return d3.nest().key(function (d) {
return d[categoryField];
}).entries(data);
}
/*
*/
function createColourPalette(legendCategories, legendCategoryColours) {
return d3.scaleOrdinal().domain(legendCategories).range(legendCategoryColours);
}
/*
*/
function getMinimumDataValueFromKey(data, key) {
return d3.min(data, function (d) {
return +d[key];
});
}
/*
*/
function getMaximumDataValueFromKey(data, key) {
return d3.max(data, function (d) {
return +d[key];
});
}
/*
*/
function createLinearYAxis(domain, range) {
return d3.scaleLinear().domain(domain).range(range).nice();
}
/*
*/
function positionAxis(axisDefinition, axis, chartType) {
var axisPosition = {
bottom: d3.axisBottom,
top: d3.axisTop,
left: d3.axisLeft,
right: d3.axisRight
};
var selectedAxisPosition = axisPosition[axis.position];
// How to force a specific amount of y axis ticks in d3 charts?
// https://stackoverflow.com/questions/51497534/how-to-force-a-specific-amount-of-y-axis-ticks-in-d3-charts
return selectedAxisPosition ? chartType == "scatterBubble" ? selectedAxisPosition().scale(axisDefinition) :
/* .ticks(numberOfTicks)
.tickValues(d3.range(minValue, maxValue + step, step)) */
selectedAxisPosition().scale(axisDefinition) : null;
}
/*
*/
function appendAxis(axisPosition, axis, svgPanel, y, x) {
return d3.selectAll("." + svgPanel).append("g").attr("class", axis.classNames.join(" ")).attr("role", axis.role).attr("aria-hidden", axis.ariaHidden).attr("transform", "translate(".concat(x, ", ").concat(y, ")")).call(axisPosition);
}
/*
*/
function modifyAxisTickClasses(axis, axisCartesian, axisTickFrequency, chartType) {
// initilise count iterator
var counter = 0;
return d3.selectAll("." + axis[axisCartesian].classNames.join(".")).selectAll(".tick").attr("role", axis[axisCartesian].tick.role).attr("aria-hidden", axis[axisCartesian].tick.ariaHidden).attr("class", function (d, i) {
// add additional classes to axis tick labels...
// and update tick label text
d3.select(this).selectAll("text").attr("role", axis[axisCartesian].tick.text.role).attr("aria-hidden", axis[axisCartesian].tick.text.ariaHidden).attr("class", function () {
return "svg__text__tickLabel " + axisCartesian + "AxisTickLabels";
}).style("display", "inline");
//
// add additional classes to axis tick lines...
// d3.select(this)
// .selectAll("line")
// .attr("role", axis[axisCartesian].tick.line.role)
// .attr("aria-hidden", axis[axisCartesian].tick.line.ariaHidden)
// .attr("class", function () {
// return (
// "svg__geometry__line__tickline svg__geometry__line__tickline__" +
// axisCartesian
// );
// });
return "tick group__tick group__tick__" + axisCartesian;
}).style("display", function (d, i) {
return i % axisTickFrequency == 0 ? "inline" : "none";
});
}
/*
*/
function appendAxisTitle(element, dimension, cartesianOffsetValue, axis, axisCartesian, axisTitlesLU, fieldTitle, IDSuffix) {
//
if (axis[axisCartesian].title.enable == true) {
// initialise and append y-axis main title label
d3.selectAll("." + element).append("text").attr("class", "title title__" + axisCartesian + "-axis").attr("id", axisCartesian + "AxisTitle" + IDSuffix).attr("role", axis[axisCartesian].title.role).attr("aria-hidden", axis[axisCartesian].title.ariaHidden).attr("x", function () {
return axisCartesian == "y" ? -dimension / 2 : dimension / 2;
}).attr("y", cartesianOffsetValue).attr("dy", axis[axisCartesian].title.dy) // must be .attr, not .style
.text(axisTitlesLU[fieldTitle]);
}
return;
}
/*
*/
function getMaxStatedDimensionFromElementsGroup(elements, dimension) {
return d3.max(d3.selectAll("." + elements).nodes(), function (n) {
return n.getBBox()[dimension];
});
}
/*
*/
function getMaxStatedDimensionFromElement(element, dimension) {
return d3.selectAll("." + element).node().getBoundingClientRect()[dimension];
}
/*
*/
function updateLinearXAxisRange(axis, range) {
return axis.range([range[0], range[1]]);
}
/*
*/
function createLinearXAxis(domain, range) {
return d3.scaleLinear().domain(domain).range(range).nice();
}
/*
*/
function appendXAxisGridLines(height, gridLines, classNames) {
//
if (gridLines.enable == true) {
//
// remove all y-axis tick gridlines before redraw
d3.selectAll(".tick__grid-line xtick__grid").remove();
//
// draw tick grid lines extending from y-axis ticks on axis across full width of graph
var xticks = d3.selectAll("." + classNames.join(".")).selectAll(".tick");
//
xticks.append("svg:line").attr("class", "tick__grid-line xtick__grid-line").attr("y0", 0).attr("y1", height).attr("x1", 0).attr("x2", 0);
} // end if ...
return;
}
/*
*/
function repositionWholeChart(element, offset) {
return d3.selectAll("." + element).attr("transform", "translate(" + offset + "," + 0 + ")");
}
/*
*/
function updateScaleBandAxisRange(axis, width) {
// update the ranges after working out offset resulting from fitting gap buffer and y-axis tick labels.
// this one is used to map the data bars against.
return axis.rangeRound([width[0], width[1]]);
}
/*
*/
function callAxisUpdate(axisDefinition, axis) {
//
var axisPosition = {
bottom: d3.axisBottom,
top: d3.axisTop,
left: d3.axisLeft,
right: d3.axisRight
};
var selectedAxisPosition = axisPosition[axis.position];
return d3.selectAll("." + axis.classNames.join("."))
// .transition()
// .duration(
// /* chartTransitionDuration */ transitionDefinition.chartTransitionDuration
// )
// .ease(/* d3.easeLinear */ transitionDefinition.chartTransitionEaseMethod)
.call(selectedAxisPosition(axisDefinition));
}
/*
*/
function appendYAxisGridLines(width, gridLines, classNames) {
//
if (gridLines.enable == true) {
//
// remove all y-axis tick gridlines before redraw
d3.selectAll(".tick__grid-line ytick__grid").remove();
//
// draw tick grid lines extending from y-axis ticks on axis across full width of graph
var yticks = d3.selectAll("." + classNames.join(".")).selectAll(".tick");
//
yticks.append("svg:line").attr("class", "tick__grid-line ytick__grid-line").attr("y0", 0).attr("y1", 0).attr("x1", 0).attr("x2", width);
} // end if ...
return;
}
/*
*/
function updatePreviousXAxisTitleState(text) {
return text == "" ? "without" : "with";
}
/*
*/
function getClientBoundingRectForElements(element) {
var node = d3.selectAll("." + element).node();
if (node) return node.getBoundingClientRect();
return {
width: 0
};
}
/*
*/
function appendBaseGroupForDataElements(baseElement, baseGroupForDataElements) {
return d3.selectAll("." + baseElement).append("g").attr("class", baseGroupForDataElements.classNames.join(" ")).attr("aria-label", baseGroupForDataElements.ariaLabel).attr("role", baseGroupForDataElements.role);
}
/*
*/
function appendDataCircles(cf, svg, data, xAxis, yAxis, colours) {
//
return d3.selectAll("." + cf.baseGroupForDataElements.classNames.join(".")).selectAll(".nodeContent.node__circle.node").data(data).enter().append("circle").attr("class", function (d, i) {
return "nodeContent node__circle node node-" + d.nodeIdentierFormatted + " shapeId-" + i + " node-" + i;
}).attr("id", function (d, i) {
return "node-" + d.nodeIdentierFormatted;
}).attr("data-initial-radius", function (d, i) {
if (d[cf.circleRadiusAttributeField] && cf.legend.scaleLegend.circleRadiusScaleRange.length > 1) {
return cf.CircleRadiusScale(d[cf.circleRadiusAttributeField]);
}
return cf.legend.scaleLegend.circleRadiusScaleRange[0];
}).attr("cx", function (d, i) {
d.plottedX = xAxis(d[cf.fieldTitles.x]);
return xAxis(d[cf.fieldTitles.x]);
}).attr("cy", function (d) {
d.plottedY = yAxis(d[cf.fieldTitles.y]);
return yAxis(d[cf.fieldTitles.y]);
}).attr("r", function (d, i) {
if (d[cf.circleRadiusAttributeField]) return cf.CircleRadiusScale(d[cf.circleRadiusAttributeField]);
}).style("fill", function (d) {
if (d[cf.dataObjectLabel]) {
var index = colours.domain().indexOf(d[cf.dataObjectLabel]);
var colourObj = colours.range()[index];
return colourObj && colourObj.fill ? colourObj.fill : "#ccc";
}
}).attr("tabindex", 0).attr("role", "listitem, button").attr("aria-expanded", "false").attr("aria-disabled", "false").attr("aria-label", function (d) {
return d[cf.dataObjectLabel];
}).on("click", function (event, d) {
cf.circleClickCallback(event, d, this);
}).on("mouseenter", function (event, d) {
// d3.select(event.currentTarget).raise();
var element = this;
d3.selectAll(".nodeContent.node__circle.node").classed("css__threeQuarter__transparent", true);
d3.select(element).classed("css__threeQuarter__transparent", false);
cf.hoverNodeCallback(event, d, this);
}).on("mouseout", function (event, d) {
var element = this;
d3.selectAll(".nodeContent.node__circle.node").classed("css__threeQuarter__transparent", false);
cf.hoverNodeOutCallback(event, d, this);
});
}
/*
*/
function appendAxisThickLine(baseElement, yAxis, orientationOfAxisAppendedTo, xAxis) {
//
return orientationOfAxisAppendedTo == "y" ? /* return horizontal */
d3.selectAll("." + baseElement).append("line").attr("class", "svg__geometry__line__axis__domainEqualsZeroThickLine svg__geometry__line__axis__domainEqualsZeroThickLine_y").attr("role", "presentation").attr("y1", yAxis(0)).attr("y2", yAxis(0)).attr("x1", xAxis(d3.min(xAxis.domain()))).attr("x2", xAxis(d3.max(xAxis.domain()))) : /* return vertical */
d3.selectAll("." + baseElement).append("line").attr("class", "svg__geometry__line__axis__domainEqualsZeroThickLine svg__geometry__line__axis__domainEqualsZeroThickLine_x").attr("role", "presentation").attr("y1", yAxis(yAxis.domain()[0])).attr("y2", yAxis(yAxis.domain()[1])).attr("x1", xAxis(0)).attr("x2", xAxis(0));
}
/*
*/
function determineUserInteractionMaskedLayerSolution(cf, xAxis, yAxis, data, svg) {
// https://github.com/d3/d3-voronoi
// https://d3js.org/d3-delaunay/voronoi
// https://gist.github.com/aaizemberg/8063f8c2d1adb7c7ee68 - adapted this for use ...
if (cf.voronoiBoundaryLayer == true) {
addVoronoiLayer(cf, xAxis);
} // end if voronoiBoundaryLayer check/build
else if (cf.delaunayBoundaryLayer == true) {
addDelaunayInteractionLayer(cf, xAxis, yAxis, data, svg);
} // end if delaunayBoundaryLayer check/build
return;
} // end function
/*
*/
function scatterBubbleOnWindowResize(cf, xAxis, yAxis, data, gX, gY, svg) {
//
cf.containerWidth = d3.selectAll(".content-panel.visualisation-panel").style("width").replaceAll("px", "");
cf.chartWidth = setChartWidth(cf, "margins");
// update width of base SVG panel
d3.selectAll("." + cf.svg__chart__container).attr("width", cf.containerWidth - cf.chartMargin.left - cf.chartMargin.right);
// update width of base SVG legend panel
// d3.selectAll(".svg__chart__legend__container").attr(
// "width",
// cf.chartWidth/3,
// );
xAxis.domain(cf.currentxAxisDomain).range([cf.chartMargin.left, cf.chartWidth - cf.chartMargin.right]);
callAxisUpdate(xAxis, cf.axis.x);
yAxis.domain(cf.currentyAxisDomain);
callAxisUpdate(yAxis, cf.axis.y);
yAxis.domain(cf.currentyAxisDomain).range([cf.chartHeight - cf.chartMargin.bottom - cf.chartMargin.top, cf.chartMargin.top]);
callAxisUpdate(yAxis, cf.axis.y);
yAxis.domain(cf.currentyAxisDomain);
callAxisUpdate(yAxis, cf.axis.y);
//
/* cf.bottomXAxis = */
d3.axisBottom(xAxis).scale(cf.currentTransform.rescaleX(xAxis));
// cf.currentxAxisDomain = xAxis.scale().domain();
/* cf.leftYAxis = */
d3.axisLeft(yAxis).scale(cf.currentTransform.rescaleY(yAxis));
// cf.currentyAxisDomain = yAxis.scale().domain();
var newXScale = gX.call(xAxis);
var newYScale = gY.call(yAxis);
// modify axis tick classname declarations too allow appedning of chart height grid lines
var xAxisTickClasses = modifyAxisTickClasses(cf.axis, "x", cf.axis.x.axisTickFrequency, cf.chartType);
// append vertical gridlines to x axis
var appendedXAxisGridLines = appendXAxisGridLines(-(d3.max(yAxis.range()) - d3.min(yAxis.range())), cf.axis.x.gridLines, cf.axis.x.classNames);
var updatedHorizontalPositionOfXAxisTitle = updateAttributeOfElement("title__x-axis", "x", d3.max(xAxis.range()) / 2);
d3.selectAll(".svg__geometry__line__axis__domainEqualsZeroThickLine_y")
// .attr("x1", 0)
// .attr("x2", xAxis.range()[1] - xAxis.range()[0]);
.attr("x1", xAxis(d3.min(xAxis.domain()))).attr("x2", xAxis(d3.max(xAxis.domain())));
d3.selectAll(".svg__geometry__line__axis__domainEqualsZeroThickLine_x").attr("x1", xAxis(0)).attr("x2", xAxis(0));
// update widths of tick grid lines extending from y-axis ticks on axis across graph
d3.selectAll(".tick__grid-line.ytick__grid-line").attr("x1", -5).attr("x2", xAxis.range()[1] - xAxis.range()[0]);
d3.selectAll(".nodeContent.node__circle.node").attr("cx", function (d, i) {
d.plottedX = xAxis(d[cf.fieldTitles.x]);
return xAxis(d[cf.fieldTitles.x]);
}).attr("cy", function (d) {
d.plottedY = yAxis(d[cf.fieldTitles.y]);
return yAxis(d[cf.fieldTitles.y]);
});
// resize delaunay polygon interaction layer
d3.selectAll(".svg__geometry__delaunay__group__rect").attr("width", d3.max(xAxis.range()) - cf.chartMargin.left);
//const determinedUserInteractionMaskedLayerSolution = determineUserInteractionMaskedLayerSolution(cf, xAxis, yAxis, data, svg);
// get bounding box limits for all entities.
var allEntitiesBoundingBoxInfo = cf.dataPointBoundaries.filter(function (d, i) {
return d.type == "allEntities";
})[0];
// resize y-axis reference line
d3.selectAll(".svg__geometry__line__axis__referenceLine_y").attr("x1", xAxis(d3.min([allEntitiesBoundingBoxInfo.xMin, allEntitiesBoundingBoxInfo.xMax]))).attr("x2", xAxis(d3.max([allEntitiesBoundingBoxInfo.xMin, allEntitiesBoundingBoxInfo.xMax]))).attr("y1", function (d, i) {
return d == "dynamic-to-axis" ? yAxis((d3.max(yAxis.domain()) - d3.min(yAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? yAxis((allEntitiesBoundingBoxInfo.yMax - allEntitiesBoundingBoxInfo.yMin) / 2) : yAxis(d);
}).attr("y2", function (d, i) {
return d == "dynamic-to-axis" ? yAxis((d3.max(yAxis.domain()) - d3.min(yAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? yAxis((allEntitiesBoundingBoxInfo.yMax - allEntitiesBoundingBoxInfo.yMin) / 2) : yAxis(d);
});
// resize x-axis reference line
d3.selectAll(".svg__geometry__line__axis__referenceLine_x").attr("x1", function (d, i) {
return d == "dynamic-to-axis" ? xAxis((d3.max(xAxis.domain()) - d3.min(xAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? xAxis((allEntitiesBoundingBoxInfo.xMax - allEntitiesBoundingBoxInfo.xMin) / 2) : yAxis(d);
}).attr("x2", function (d, i) {
return d == "dynamic-to-axis" ? xAxis((d3.max(xAxis.domain()) - d3.min(xAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? xAxis((allEntitiesBoundingBoxInfo.xMax - allEntitiesBoundingBoxInfo.xMin) / 2) : yAxis(d);
}).attr("y1", yAxis(d3.min([allEntitiesBoundingBoxInfo.yMin, allEntitiesBoundingBoxInfo.yMax]))).attr("y2", yAxis(d3.max([allEntitiesBoundingBoxInfo.yMin, allEntitiesBoundingBoxInfo.yMax])));
// resize both bounding boxes.
d3.selectAll(".svg__rect__scatter__data__boundingBox").attr("x", function (d, i) {
return xAxis(d.xMin);
}).attr("y", function (d, i) {
return yAxis(d.yMax);
}).attr("width", function (d, i) {
return xAxis(d.xMax) - xAxis(d.xMin);
}).attr("height", function (d, i) {
return yAxis(d.yMin) - yAxis(d.yMax);
});
// resize invisible clip rect to ensure no plotted chart elements are visible outside chart area.
d3.select("#clipRect").attr("width", d3.max(xAxis.range()) - cf.chartMargin.left);
// resize chart frame rect.
d3.selectAll(".svg__rect__chart__frame").attr("width", d3.max(xAxis.range()) - cf.chartMargin.left);
// reposition quadrant labels.
d3.selectAll(".quadrant__Labels").attr("x", function (d, i) {
return i == 0 || i == 2 ? xAxis(Number(allEntitiesBoundingBoxInfo.xMax - allEntitiesBoundingBoxInfo.xMin) * 0.25) : xAxis(Number(allEntitiesBoundingBoxInfo.xMax - allEntitiesBoundingBoxInfo.xMin) * 0.75);
});
// do not delete this commmented out line. May need to reintroduce it to fix window resize bug.
// svg.call(zoom.transform, cf.currentTransform);
return;
}
/*
*/
function addDelaunayInteractionLayer(cf, xAxis, yAxis, data, svg) {
d3.selectAll(".svg__geometry__delaunay__group").remove();
// empty array to store data point values
cf.dataVertices = [];
// repopulate stoage array with pltted coords for all data points. needed for user interaction.
cf.dataVertices = data.map(function (d, i) {
return [d.plottedX, d.plottedY];
});
// set up delaunay layer ..
cf.delaunay = _d3Delaunay.Delaunay.from(cf.dataVertices);
cf.chartMargin.leftAdjusted = 0;
// append base group element and rect element onto this to become interaction layer
svg.append("g").attr("class", "svg__geometry__delaunay__group").attr("role", "presentation").attr("transform", "translate(" + cf.chartMargin.leftAdjusted + "," + 0 + ")").append("rect").attr("class", "svg__geometry__delaunay__group__rect").attr("id", "svg__geometry__delaunay__group__rect").attr("role", "presentation").attr("x", cf.chartMargin.left).attr("y", cf.chartMargin.top).attr("width", d3.max(xAxis.range()) - cf.chartMargin.left).attr("height", d3.max(yAxis.range()) - d3.min(yAxis.range())).on("mouseover", function (event) {
// d3.select(event.currentTarget).raise();
var element = this;
//scatterBubbleUserMouseOver(cf);
}).on("mousemove", function () {
var element = this;
//scatterBubbleUserMouseMove(cf, element, data);
}).on("mouseup", function () {}).on("click", function () {
d3.event.preventDefault();
var element = this;
// scatterBubbleUserMouseClick(cf, element, xAxis, yAxis);
}).on("mouseout", function () {
d3.selectAll(".nodeContent.node__circle.node").classed("css__threeQuarter__transparent", false);
// remove clone copy of selected entity node
d3.selectAll(".node__clone").remove();
// scatterBubbleUserMouseOut(cf);
}).on("touchstart", function () {
// d3.event.preventDefault();
// const element = this;
// scatterBubbleUserMouseMove(cf, element, xAxis, yAxis, "1 mousemove");
// scatterBubbleUserMouseClick(cf, element, xAxis, yAxis);
return;
});
return;
} // end function
/*
*/
function updateAttributeOfElement(element, attribute, value) {
return d3.selectAll("." + element).attr(attribute, value);
}
/*
*/
function appendAxisReferenceLines(dataPointBoundaries, element, xAxis, yAxis, orientationOfAxisAppendedTo, referenceLines) {
//
// localise limits information for allentities bouding box.
var allEntitiesBoundingBoxInfo = dataPointBoundaries.filter(function (d, i) {
return d.type == "allEntities";
})[0];
// append new reference axis bisector/ing reference line
return orientationOfAxisAppendedTo == "y" ? d3.selectAll("." + element).selectAll(".svg__geometry__line__axis__referenceLine_y").data(referenceLines).enter().append("line").attr("class", "framing__context_element svg__geometry__line__axis__referenceLine svg__geometry__line__axis__referenceLine_y").attr("role", "presentation").attr("y1", function (d, i) {
return d == "dynamic-to-axis" ? yAxis((d3.max(yAxis.domain()) - d3.min(yAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? yAxis((allEntitiesBoundingBoxInfo.yMax - allEntitiesBoundingBoxInfo.yMin) / 2) : yAxis(d);
}).attr("y2", function (d, i) {
return d == "dynamic-to-axis" ? yAxis((d3.max(yAxis.domain()) - d3.min(yAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? yAxis((allEntitiesBoundingBoxInfo.yMax - allEntitiesBoundingBoxInfo.yMin) / 2) : yAxis(d);
}).attr("x1", xAxis(d3.min([allEntitiesBoundingBoxInfo.xMin, allEntitiesBoundingBoxInfo.xMax]))).attr("x2", xAxis(d3.max([allEntitiesBoundingBoxInfo.xMin, allEntitiesBoundingBoxInfo.xMax]))) : d3.selectAll("." + element).selectAll(".svg__geometry__line__axis__referenceLine_x").data(referenceLines).enter().append("line").attr("class", "framing__context_element svg__geometry__line__axis__referenceLine svg__geometry__line__axis__referenceLine_x").attr("role", "presentation").attr("y1", yAxis(d3.min([allEntitiesBoundingBoxInfo.yMin, allEntitiesBoundingBoxInfo.yMax]))).attr("y2", yAxis(d3.max([allEntitiesBoundingBoxInfo.yMin, allEntitiesBoundingBoxInfo.yMax]))).attr("x1", function (d, i) {
return d == "dynamic-to-axis" ? xAxis((d3.max(xAxis.domain()) - d3.min(xAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? xAxis((allEntitiesBoundingBoxInfo.xMax - allEntitiesBoundingBoxInfo.xMin) / 2) : xAxis(d);
}).attr("x2", function (d, i) {
return d == "dynamic-to-axis" ? xAxis((d3.max(xAxis.domain()) - d3.min(xAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? xAxis((allEntitiesBoundingBoxInfo.xMax - allEntitiesBoundingBoxInfo.xMin) / 2) : xAxis(d);
});
}
/*
*/
function getDataPointBoundaries(dataPointBoundaries, data, xField, yField, rectType) {
//
return dataPointBoundaries.push({
type: rectType,
yMin: d3.min(data, function (d) {
return +d[yField];
}),
yMax: d3.max(data, function (d) {
return +d[yField];
}),
xMin: d3.min(data, function (d) {
return +d[xField];
}),
xMax: d3.max(data, function (d) {
return +d[xField];
})
});
}
/*
*/
function appendDataBoundingRects(dataLimits, baseElement, xAxis, yAxis) {
//
d3.selectAll(".svg__rect__scatter__data__boundingBox").remove();
//
return d3.selectAll("." + baseElement).selectAll(".svg__rect__scatter__data__boundingBox").data(dataLimits).enter().append("rect").attr("class", function (d, i) {
return "framing__context_element svg__rect__scatter__data__boundingBox " + d.type;
}).attr("x", function (d, i) {
return xAxis(d.xMin);
}).attr("y", function (d, i) {
return yAxis(d.yMax);
}).attr("width", function (d, i) {
return xAxis(d.xMax) - xAxis(d.xMin);
}).attr("height", function (d, i) {
return yAxis(d.yMin) - yAxis(d.yMax);
});
}
/*
*/
function appendedEntitiestoSelectionList(entityData) {
//
//
d3.selectAll(".multi-select-options").selectAll(".multi-select-option").data(entityData).enter().append("div").attr("class", "multi-select-option").attr("value", function (d, i) {
return d.institutionId;
}).attr("data-value", function (d, i) {
return d.institutionId;
});
d3.selectAll(".entityOption").append("span").attr("class", "multi-select-option-text").attr("text", function (d, i) {
return d.institutionName;
});
return;
}
/*
NAME: compareStrings
DESCRIPTION: local function called to logicall compare two strings. helps sorting of data
ARGUMENTS TAKEN:a - first string to compare
b - second string to compare
ARGUMENTS RETURNED: none
CALLED FROM: nestData
CALLS: none
*/
function compareStrings(a, b) {
// Assuming you want case-insensitive comparison
a = a.toLowerCase();
b = b.toLowerCase();
return a < b ? -1 : a > b ? 1 : 0;
}
/*
desc: deletes single element from JSON array based on key value
*/
function deleteJSONArrayElement(array, key, value) {
//
return array.filter(function (item) {
return item[key] !== value;
});
}
/*
*/
function scatterBubbleUserMouseMove(cf_developer, element, data) {
// determine if interacted element came from mouse, touch or focus
var mx = 0,
my = 0;
var selected = null;
cf_developer.isTouched = false;
if (element.classList.contains("node__circle")) {
selected = circleObjectToData(cf_developer, element);
var _ref = [selected.plottedX, selected.plottedY];
mx = _ref[0];
my = _ref[1];
} else if (d3.touches(element).length == 1) {
var _ref2 = [d3.touches(element)[0][0], d3.touches(element)[0][1]];
mx = _ref2[0];
my = _ref2[1];
cf_developer.isTouched = true;
} else {
var _d3$mouse = d3.mouse(d3.select(element).node());
var _d3$mouse2 = _slicedToArray(_d3$mouse, 2);
mx = _d3$mouse2[0];
my = _d3$mouse2[1];
}
if (d3.touches(element).length == 0) {
if (!cf_developer.isHovered || cf_developer.isClicked == true) return;
}
cf_developer.thisisNearestDistance = Infinity;
cf_developer.thisisNearestPoint = [null, null];
cf_developer.dataVertices.forEach(function (d, i) {
//
var calculatedDistance = calculateDistance(Number(d[0] - cf_developer.chartMargin.leftAdjusted), Number(d[1] + cf_developer.svg__chart__container_position.y), mx, my + cf_developer.svg__chart__container_position.y);
if (calculatedDistance < cf_developer.thisisNearestDistance) {
cf_developer.thisisNearestDistance = calculatedDistance;
cf_developer.thisisNearestPoint = [d[0], d[1]];
} // end if ...
}); // end forEach loop ...
if (cf_developer.thisisNearestDistance < cf_developer.delaunayLimitedRadius) {
//
selected = data.filter(function (d, i) {
return cf_developer.thisisNearestPoint[0] == d.plottedX && cf_developer.thisisNearestPoint[1] == d.plottedY;
})[0];
cf_developer.selected = selected;
var UID = cf_developer.selected.nodeIdentierFormatted;
var UIname = cf_developer.selected[cf_developer.dataObjectLabel];
var UIXvalue = cf_developer.chartType == "scatterBubble" ? cf_developer.selected[cf_developer.fieldTitles.x] : cf_developer.selected[cf_developer.fieldTitles];
var UIYvalue = cf_developer.chartType == "scatterBubble" ? cf_developer.selected[cf_developer.fieldTitles.y] : cf_developer.selected[cf_developer.fieldTitles];
var UIScaleValue = cf_developer.selected[cf_developer.circleRadiusAttributeField];
// apply styling to make all shape geometries semi-transparent.
d3.selectAll(".nodeContent.node__circle.node").classed("css__threeQuarter__transparent", true);
// remove styling to make selected shape geometry fully opaque
// https://stackoverflow.com/questions/36326683/d3-js-how-can-i-set-the-cursor-to-hand-when-mouseover-these-elements-on-svg-co
d3.select(element).style("cursor", "pointer");
d3.select("#node-" + UID).classed("css__threeQuarter__transparent", false);
d3.selectAll(".nodeLabels").style("visibility", "hidden");
d3.select("#node-" + UID).classed("hovered", true);
d3.select("#node-label-group-" + UID).style("visibility", "visible");
} else {
//
// if user has not currently clicked on any data point ..
if (cf_developer.isClicked == false) {
// return all data dots to full view.
d3.selectAll(".nodeContent.node__circle.node").classed("css__threeQuarter__transparent", false);
}
d3.select(element).style("cursor", "default");
d3.selectAll(".nodeContent.node__circle.node").classed("hovered", false);
d3.selectAll(".nodeLabels").style("visibility", "hidden");
cf_developer.selected = null;
}
if (_config.cf.selected) {
//
// example to try to replicate for DOM.element.raise()
// https://stackoverflow.com/questions/71500659/go-back-to-previous-children-order-after-calling-raise
// circles.on("mouseover", event => d3.select(event.currentTarget).raise())
// .on("mouseout", () => circles.order());
d3.selectAll(".node__clone").remove();
// raise selected data circle to op of DOM, to make it clearly visible.
var nodeCircleCopy = d3.select("#node-" + _config.cf.selected[_config.cf.nodeIdentierFormatted]).clone(true).attr("class", "nodeContent node__circle node__clone").attr("id", "node__clone-" + _config.cf.selected[_config.cf.nodeIdentierFormatted]).style("fill-opacity", 1).style("stroke-width", 4).raise();
} else {
d3.selectAll(".node__clone").remove();
}
return cf_developer.selected;
} // end
/*
*/
function calculateDistance(px, py, mx, my) {
var a = px - mx;
var b = py - my;
return Math.sqrt(a * a + b * b);
}
/*
*/
function scatterBubbleUserMouseOver(cf) {
cf.isHovered = true;
return;
} // end function
/*
*/
function createUsableID(unusableID) {
return unusableID.replaceAll(".", "_").replaceAll(" ", "_").replaceAll("-", "_");
}
/*
*/
function scatterBubbleUserMouseClick(cf_developer, element, xAxis, yAxis, cf_user) {
if (cf_developer.selected == null) return;
//
// remove data circle from plot ..
d3.select("#node-" + cf_developer.selected.nodeIdentierFormatted).remove();
d3.select(element).style("cursor", "default");
d3.selectAll(".nodeContent.node__circle.node").classed("css__threeQuarter__transparent", false);
// select entity name chip on selection list header
var selected_Multi_select_header_option = document.querySelector('[data-value="' + cf_developer.selected.nodeIdentierFormatted + '"]');
// select entity name chip on selection list header
var multi_select_option = document.querySelectorAll('div[data-value="' + cf_developer.selected.nodeIdentierFormatted + '"]');
// modify classlist to uncheck selection option in selection list
multi_select_option[0].classList.remove("multi-select-selected");
// removed entity's JSON element from array of selected/displayed entities
_config.cf.selectedEntityData = deleteJSONArrayElement(_config.cf.selectedEntityData, _config.cf.nodeIdentierFormatted, cf_developer.selected.nodeIdentierFormatted);
// delete boundary rect JSON info for 'selectedEntities' bound rect.
_config.cf.dataPointBoundaries = deleteJSONArrayElement(_config.cf.dataPointBoundaries, "type", "selectedEntities");
// get new boundaries details.
getDataPointBoundaries(_config.cf.dataPointBoundaries, _config.cf.selectedEntityData, _config.cf.fieldTitles.x, _config.cf.fieldTitles.y, "selectedEntities");
var transitionedBoundingRects = transitionBoundingRects(_config.cf.dataPointBoundaries, _config.cf.chartTransitionDuration, _config.cf.chartTransitionEaseMethod, xAxis, yAxis);
// update counter text in selection list header
d3.selectAll(".multi-select-header-max").text(_config.cf.selectedEntityData.length + "/" + cf_developer.maxNSelectedEntities);
// update delaunary for new entity selection set
var updatedDelaunayLayer = addDelaunayInteractionLayer(_config.cf, xAxis, yAxis, _config.cf.selectedEntityData, svg);
// reset user interaction boolean vars.
cf_developer.isTouched = false;
cf_developer.isClicked = false;
return;
}
/*
*/
function transitionChart(fieldTitles, /* currentChart, */
xAxis, yAxis, data, /* selectedEntityData, */
chartTransitionEaseMethod, chartTransitionDuration, /* dataPointBoundaries, */
axis, chartType, axisTitlesLU) {
// determine y-axis minimum and maximum values from data
// https://stackoverflow.com/questions/11488194/how-to-use-d3-min-and-d3-max-within-a-d3-json-command
var YAxisMin = getMinimumDataValueFromKey(data, fieldTitles /* [currentChart] */.y);
var YAxisMax = getMaximumDataValueFromKey(data, fieldTitles /* [currentChart] */.y);
yAxis.domain([0, Math.ceil(YAxisMax / axis.y.axisRounding /* [currentChart] */) * axis.y.axisRounding /* [currentChart] */]).nice();
var axisPosition = {
bottom: d3.axisBottom,
top: d3.axisTop,
left: d3.axisLeft,
right: d3.axisRight
};
//
var selectedYAxisPosition = axisPosition[axis.y.position];
d3.selectAll("." + axis.y.classNames.join(".")).transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).call(selectedYAxisPosition(yAxis));
var XAxisMin = getMinimumDataValueFromKey(data, fieldTitles /* [currentChart] */.x);
var XAxisMax = getMaximumDataValueFromKey(data, fieldTitles /* [currentChart] */.x);
xAxis.domain([0, Math.ceil(XAxisMax / axis.x.axisRounding /* [currentChart] */) * axis.x.axisRounding /* [currentChart] */]).nice();
//
var selectedXAxisPosition = axisPosition[axis.x.position];
d3.selectAll("." + axis.x.classNames.join(".")).transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).call(selectedXAxisPosition(xAxis));
d3.selectAll(".title.title__y-axis").text(function () {
return axisTitlesLU[_config.cf.fieldTitles /* [currentChart] */.y];
});
d3.selectAll(".title.title__x-axis").text(function () {
return axisTitlesLU[_config.cf.fieldTitles /* [currentChart] */.x];
});
// const plottedEntities = d3
// .selectAll(".nodeContent.node__circle.node")
// .data(selectedEntityData);
// plottedEntities.exit().remove(); //remove unneeded data points plotted
// plottedEntities.enter().append("circle");
// transition all data circles
d3.selectAll(".nodeContent.node__circle").transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).attr("cx", function (d, i) {
d.plottedX = xAxis(d[_config.cf.fieldTitles /* [currentChart] */.x]);
return xAxis(d[_config.cf.fieldTitles /* [currentChart] */.x]);
}).attr("cy", function (d) {
d.plottedY = yAxis(d[_config.cf.fieldTitles /* [currentChart] */.y]);
return yAxis(d[_config.cf.fieldTitles /* [currentChart] */.y]);
});
// transition all data circles
d3.selectAll(".nodeContentElement.nodeLabels").transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).attr("x", function (d, i) {
d.plottedX = xAxis(d[_config.cf.fieldTitles.x]);
var nodeRadius = _config.cf.CircleRadiusScale(d[_config.cf.circleRadiusAttributeField]);
return xAxis(d[_config.cf.fieldTitles.x]) + nodeRadius;
}).attr("y", function (d) {
d.plottedY = yAxis(d[_config.cf.fieldTitles.y]);
var nodeRadius = _config.cf.CircleRadiusScale(d[_config.cf.circleRadiusAttributeField]);
return yAxis(d[_config.cf.fieldTitles.y]) - nodeRadius;
});
var transitionedBoundingRects = transitionBoundingRects(_config.cf.dataPointBoundaries, _config.cf.chartTransitionDuration, _config.cf.chartTransitionEaseMethod, xAxis, yAxis);
// modify axis tick classname declarations too allow appending of chart height grid lines
var yAxisTickClasses = modifyAxisTickClasses(axis, "y", axis.y.axisTickFrequency, chartType);
// append vertical gridlines to x axis
var appendedYAxisGridLines = appendYAxisGridLines(xAxis.range()[1] - xAxis.range()[0], _config.cf.axis.y.gridLines, _config.cf.axis.y.classNames);
// modify axis tick classname declarations too allow appedning of chart height grid lines
var xAxisTickClasses = modifyAxisTickClasses(axis, "x", axis.x.axisTickFrequency, chartType);
// append vertical gridlines to x axis
var appendedXAxisGridLines = appendXAxisGridLines(-(d3.max(yAxis.range()) - d3.min(yAxis.range())), _config.cf.axis.x.gridLines, _config.cf.axis.x.classNames);
var allEntitiesBoundingBoxInfo = _config.cf.dataPointBoundaries.filter(function (d, i) {
return d.type == "allEntities";
})[0];
d3.selectAll(".svg__geometry__line__axis__referenceLine_y").transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).attr("y1", function (d, i) {
return d == "dynamic-to-axis" ? yAxis((d3.max(yAxis.domain()) - d3.min(yAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? yAxis((allEntitiesBoundingBoxInfo.yMax - allEntitiesBoundingBoxInfo.yMin) / 2) : yAxis(d);
}).attr("y2", function (d, i) {
return d == "dynamic-to-axis" ? yAxis((d3.max(yAxis.domain()) - d3.min(yAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? yAxis((allEntitiesBoundingBoxInfo.yMax - allEntitiesBoundingBoxInfo.yMin) / 2) : yAxis(d);
}).attr("x1", xAxis(d3.min([allEntitiesBoundingBoxInfo.xMin, allEntitiesBoundingBoxInfo.xMax]))).attr("x2", xAxis(d3.max([allEntitiesBoundingBoxInfo.xMin, allEntitiesBoundingBoxInfo.xMax])));
d3.selectAll(".svg__geometry__line__axis__referenceLine_x").transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).attr("y1", yAxis(d3.min([allEntitiesBoundingBoxInfo.yMin, allEntitiesBoundingBoxInfo.yMax]))).attr("y2", yAxis(d3.max([allEntitiesBoundingBoxInfo.yMin, allEntitiesBoundingBoxInfo.yMax]))).attr("x1", function (d, i) {
return d == "dynamic-to-axis" ? xAxis((d3.max(xAxis.domain()) - d3.min(xAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? xAxis((allEntitiesBoundingBoxInfo.xMax - allEntitiesBoundingBoxInfo.xMin) / 2) : xAxis(d);
}).attr("x2", function (d, i) {
return d == "dynamic-to-axis" ? xAxis((d3.max(xAxis.domain()) - d3.min(xAxis.domain())) / 2) : d == "dynamic-to-boundingRect" ? xAxis((allEntitiesBoundingBoxInfo.xMax - allEntitiesBoundingBoxInfo.xMin) / 2) : xAxis(d);
});
d3.selectAll(".svg__geometry__line__axis__domainEqualsZeroThickLine_y").transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).attr("y1", newY(0)).attr("y2", newY(0));
d3.selectAll(".svg__geometry__line__axis__domainEqualsZeroThickLine_x").transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).attr("x1", newX(0)).attr("x2", newX(0));
// update delaunary for new entity selection set
var updatedDelaunayLayer = addDelaunayInteractionLayer(_config.cf, newX, newY, _config.cf.selectedEntityData, svg);
var transitionedAppendedQuadrantLabels = appendQuadrantLabels(_config.cf.baseGroupForDataElements.classNames.join("."), _config.cf.quadrantLabels.labels[_config.cf.quadrantLabels.axisSet], xBottom, yLeft, _config.cf.dataPointBoundaries.filter(function (d, i) {
return d.type == "allEntities";
})[0], _config.cf.quadrantLabels.verticalOffset);
svg.transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).call(zoom.transform, d3.zoomIdentity);
return;
}
/*
*/
function transitionAxis(classnames, chartTransitionDuration, chartTransitionEaseMethod, axis, position) {
//
var axisPosition = {
bottom: d3.axisBottom,
top: d3.axisTop,
left: d3.axisLeft,
right: d3.axisRight
};
//
var selectedAxisPosition = axisPosition[position];
//
return d3.selectAll("." + classnames.join(".")).transition().duration(chartTransitionDuration).ease(chartTransitionEaseMethod).call(selectedAxisPosition(axis));
}
/*
*/
function appendChartClipRect(baseGroupForDataElements) {
return d3.selectAll("." + baseGroupForDataElements.classNames.join(".")).attr("clip-path", "url(#clip)");
}
/*
*/
function submit_selections(selectedContinents, selectedCountries, cf, baseGroupForDataElements, xAxis, yAxis, createdColourPalette, dataPointBoundaries, fieldTitles, data) {
var entitiesFilteredByContinents = data.filter(function (d, i) {
return selectedContinents.indexOf(d.continent) != -1;
});
var entitiesFilteredByCountries = data.filter(function (d, i) {
return selectedCountries.indexOf(d.country) != -1;
});
// first round of array deduplicating: concatenating CONTINENT and COUNTRY
var mergedArray1 = entitiesFilteredByContinents.concat(entitiesFilteredByCountries.filter(function (item2) {
return !entitiesFilteredByContinents.some(function (item1) {
return item1.id === item2.id;
});
}));
// first round of array deduplicating: concatenating CONTINENT and COUNTRY
cf.selectedEntityData = cf.selectedEntityData.concat(mergedArray1.filter(function (item2) {
return !cf.selectedEntityData.some(function (item1) {
return item1.id === item2.id;
});
}));
var updatedChart = updateChartWithNewSelection(cf, baseGroupForDataElements, xAxis, yAxis, createdColourPalette, dataPointBoundaries, fieldTitles);
var newTransform = d3.zoomIdentity.translate(cf.currentTransform.x, c