|
@@ -35,13 +35,13 @@ ko.bindingHandlers.pieChart = {
|
|
|
$(element).width(Math.min($(element).parent().width(), _max));
|
|
$(element).width(Math.min($(element).parent().width(), _max));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if ($(element).find('svg').length > 0 && _data.length == 0) {
|
|
|
|
|
- $(element).find('svg').empty();
|
|
|
|
|
|
|
+ if ($(element).find("svg").length > 0 && _data.length == 0) {
|
|
|
|
|
+ $(element).find("svg").empty();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (_data.length > 0 && isNaN(_data[0].value)) {
|
|
if (_data.length > 0 && isNaN(_data[0].value)) {
|
|
|
_data = [];
|
|
_data = [];
|
|
|
- $(element).find('svg').empty();
|
|
|
|
|
|
|
+ $(element).find("svg").empty();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if ($(element).is(":visible")) {
|
|
if ($(element).is(":visible")) {
|
|
@@ -56,7 +56,7 @@ ko.bindingHandlers.pieChart = {
|
|
|
.height($(element).width())
|
|
.height($(element).width())
|
|
|
.showLabels(true).showLegend(false);
|
|
.showLabels(true).showLegend(false);
|
|
|
|
|
|
|
|
- var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
|
|
|
|
|
|
|
+ var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
|
|
|
|
|
|
|
|
_d3.datum(_data)
|
|
_d3.datum(_data)
|
|
|
.transition().duration(150)
|
|
.transition().duration(150)
|
|
@@ -83,8 +83,8 @@ ko.bindingHandlers.pieChart = {
|
|
|
|
|
|
|
|
return _chart;
|
|
return _chart;
|
|
|
}, function () {
|
|
}, function () {
|
|
|
- var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
|
|
|
|
|
- _d3.selectAll(".nv-slice").on('click',
|
|
|
|
|
|
|
+ var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
|
|
|
|
|
+ _d3.selectAll(".nv-slice").on("click",
|
|
|
function (d, i) {
|
|
function (d, i) {
|
|
|
if (typeof _options.onClick != "undefined") {
|
|
if (typeof _options.onClick != "undefined") {
|
|
|
chartsUpdatingState();
|
|
chartsUpdatingState();
|
|
@@ -177,7 +177,7 @@ ko.bindingHandlers.leafletMapChart = {
|
|
|
if (_map == null) {
|
|
if (_map == null) {
|
|
|
_map = L.map(element);
|
|
_map = L.map(element);
|
|
|
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
|
|
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
|
|
|
- attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributorss'
|
|
|
|
|
|
|
+ attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
|
|
}).addTo(_map);
|
|
}).addTo(_map);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -370,12 +370,12 @@ ko.bindingHandlers.mapChart = {
|
|
|
function lineChartBuilder(element, options) {
|
|
function lineChartBuilder(element, options) {
|
|
|
var _datum = options.transformer(options.datum);
|
|
var _datum = options.transformer(options.datum);
|
|
|
$(element).height(300);
|
|
$(element).height(300);
|
|
|
- if ($(element).find('svg').length > 0 && (_datum.length == 0 || _datum[0].values.length == 0)) {
|
|
|
|
|
- $(element).find('svg').empty();
|
|
|
|
|
|
|
+ if ($(element).find("svg").length > 0 && (_datum.length == 0 || _datum[0].values.length == 0)) {
|
|
|
|
|
+ $(element).find("svg").empty();
|
|
|
}
|
|
}
|
|
|
if (_datum.length > 0 && _datum[0].values.length > 0 && (isNaN(_datum[0].values[0].x) || isNaN(_datum[0].values[0].y))) {
|
|
if (_datum.length > 0 && _datum[0].values.length > 0 && (isNaN(_datum[0].values[0].x) || isNaN(_datum[0].values[0].y))) {
|
|
|
_datum = [];
|
|
_datum = [];
|
|
|
- $(element).find('svg').empty();
|
|
|
|
|
|
|
+ $(element).find("svg").empty();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if ($(element).is(":visible")) {
|
|
if ($(element).is(":visible")) {
|
|
@@ -394,9 +394,9 @@ function lineChartBuilder(element, options) {
|
|
|
_chart.xAxis.showMaxMin(false);
|
|
_chart.xAxis.showMaxMin(false);
|
|
|
|
|
|
|
|
_chart.yAxis
|
|
_chart.yAxis
|
|
|
- .tickFormat(d3.format(',0f'));
|
|
|
|
|
|
|
+ .tickFormat(d3.format(",0f"));
|
|
|
|
|
|
|
|
- var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
|
|
|
|
|
|
|
+ var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
|
|
|
_d3.datum(_datum)
|
|
_d3.datum(_datum)
|
|
|
.transition().duration(150)
|
|
.transition().duration(150)
|
|
|
.each("end", options.onComplete != null ? options.onComplete : void(0))
|
|
.each("end", options.onComplete != null ? options.onComplete : void(0))
|
|
@@ -406,8 +406,8 @@ function lineChartBuilder(element, options) {
|
|
|
|
|
|
|
|
return _chart;
|
|
return _chart;
|
|
|
}, function () {
|
|
}, function () {
|
|
|
- var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
|
|
|
|
|
- _d3.selectAll(".nv-line").on('click',
|
|
|
|
|
|
|
+ var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
|
|
|
|
|
+ _d3.selectAll(".nv-line").on("click",
|
|
|
function (d, i) {
|
|
function (d, i) {
|
|
|
if (typeof options.onClick != "undefined") {
|
|
if (typeof options.onClick != "undefined") {
|
|
|
chartsUpdatingState();
|
|
chartsUpdatingState();
|
|
@@ -425,13 +425,13 @@ function barChartBuilder(element, options, isTimeline) {
|
|
|
|
|
|
|
|
var _isPivot = options.isPivot != null ? options.isPivot : false;
|
|
var _isPivot = options.isPivot != null ? options.isPivot : false;
|
|
|
|
|
|
|
|
- if ($(element).find('svg').length > 0 && (_datum.length == 0 || _datum[0].values.length == 0)) {
|
|
|
|
|
- $(element).find('svg').empty();
|
|
|
|
|
|
|
+ if ($(element).find("svg").length > 0 && (_datum.length == 0 || _datum[0].values.length == 0)) {
|
|
|
|
|
+ $(element).find("svg").empty();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (_datum.length > 0 && _datum[0].values.length > 0 && isNaN(_datum[0].values[0].y)) {
|
|
if (_datum.length > 0 && _datum[0].values.length > 0 && isNaN(_datum[0].values[0].y)) {
|
|
|
_datum = [];
|
|
_datum = [];
|
|
|
- $(element).find('svg').empty();
|
|
|
|
|
|
|
+ $(element).find("svg").empty();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if ($(element).is(":visible")) {
|
|
if ($(element).is(":visible")) {
|
|
@@ -444,19 +444,19 @@ function barChartBuilder(element, options, isTimeline) {
|
|
|
var _mom = moment(d);
|
|
var _mom = moment(d);
|
|
|
if (_mom != null && _mom.isValid()) {
|
|
if (_mom != null && _mom.isValid()) {
|
|
|
var _words = _mom.format("hh:mm:ss YYYY-MM-DD").split(" ");
|
|
var _words = _mom.format("hh:mm:ss YYYY-MM-DD").split(" ");
|
|
|
- _el.text('');
|
|
|
|
|
|
|
+ _el.text("");
|
|
|
for (var i = 0; i < _words.length; i++) {
|
|
for (var i = 0; i < _words.length; i++) {
|
|
|
var tspan = _el.append("tspan").text(_words[i]);
|
|
var tspan = _el.append("tspan").text(_words[i]);
|
|
|
if (i > 0) {
|
|
if (i > 0) {
|
|
|
- tspan.attr("x", 0).attr("dy", '15');
|
|
|
|
|
|
|
+ tspan.attr("x", 0).attr("dy", "15");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
if (isTimeline) {
|
|
if (isTimeline) {
|
|
|
- if ($(element).find('svg').length > 0 && $(element).find('.nv-discreteBarWithAxes').length > 0) {
|
|
|
|
|
- $(element).find('svg').empty();
|
|
|
|
|
|
|
+ if ($(element).find("svg").length > 0 && $(element).find(".nv-discreteBarWithAxes").length > 0) {
|
|
|
|
|
+ $(element).find("svg").empty();
|
|
|
}
|
|
}
|
|
|
_chart = nv.models.multiBarWithBrushChart();
|
|
_chart = nv.models.multiBarWithBrushChart();
|
|
|
if (_datum.length > 0 && _datum[0].values.length > 10) {
|
|
if (_datum.length > 0 && _datum[0].values.length > 10) {
|
|
@@ -485,8 +485,8 @@ function barChartBuilder(element, options, isTimeline) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if (_isDiscrete && ! _isPivot) {
|
|
if (_isDiscrete && ! _isPivot) {
|
|
|
- if ($(element).find('svg').length > 0 && $(element).find('.nv-multiBarWithLegend').length > 0) {
|
|
|
|
|
- $(element).find('svg').empty();
|
|
|
|
|
|
|
+ if ($(element).find("svg").length > 0 && $(element).find(".nv-multiBarWithLegend").length > 0) {
|
|
|
|
|
+ $(element).find("svg").empty();
|
|
|
}
|
|
}
|
|
|
_chart = nv.models.growingDiscreteBarChart()
|
|
_chart = nv.models.growingDiscreteBarChart()
|
|
|
.x(function (d) {
|
|
.x(function (d) {
|
|
@@ -498,8 +498,8 @@ function barChartBuilder(element, options, isTimeline) {
|
|
|
.staggerLabels(true);
|
|
.staggerLabels(true);
|
|
|
}
|
|
}
|
|
|
else {
|
|
else {
|
|
|
- if ($(element).find('svg').length > 0 && $(element).find('.nv-discreteBarWithAxes').length > 0) {
|
|
|
|
|
- $(element).find('svg').empty();
|
|
|
|
|
|
|
+ if ($(element).find("svg").length > 0 && $(element).find(".nv-discreteBarWithAxes").length > 0) {
|
|
|
|
|
+ $(element).find("svg").empty();
|
|
|
}
|
|
}
|
|
|
_chart = nv.models.multiBarWithBrushChart();
|
|
_chart = nv.models.multiBarWithBrushChart();
|
|
|
if (_datum.length > 0 && _datum[0].values.length > 10) {
|
|
if (_datum.length > 0 && _datum[0].values.length > 10) {
|
|
@@ -510,7 +510,7 @@ function barChartBuilder(element, options, isTimeline) {
|
|
|
_chart.hideSelection();
|
|
_chart.hideSelection();
|
|
|
}
|
|
}
|
|
|
else {
|
|
else {
|
|
|
- _chart.xAxis.showMaxMin(false).tickFormat(d3.format(',0f'));
|
|
|
|
|
|
|
+ _chart.xAxis.showMaxMin(false).tickFormat(d3.format(",0f"));
|
|
|
}
|
|
}
|
|
|
_chart.multibar.hideable(true);
|
|
_chart.multibar.hideable(true);
|
|
|
_chart.multibar.stacked(typeof options.stacked != "undefined" ? options.stacked : false);
|
|
_chart.multibar.stacked(typeof options.stacked != "undefined" ? options.stacked : false);
|
|
@@ -524,9 +524,9 @@ function barChartBuilder(element, options, isTimeline) {
|
|
|
_chart.transitionDuration(0);
|
|
_chart.transitionDuration(0);
|
|
|
|
|
|
|
|
_chart.yAxis
|
|
_chart.yAxis
|
|
|
- .tickFormat(d3.format(',0f'));
|
|
|
|
|
|
|
+ .tickFormat(d3.format(",0f"));
|
|
|
|
|
|
|
|
- var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
|
|
|
|
|
|
|
+ var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
|
|
|
_d3.datum(_datum)
|
|
_d3.datum(_datum)
|
|
|
.transition().duration(150)
|
|
.transition().duration(150)
|
|
|
.each("end", function () {
|
|
.each("end", function () {
|
|
@@ -554,7 +554,7 @@ function barChartBuilder(element, options, isTimeline) {
|
|
|
|
|
|
|
|
return _chart;
|
|
return _chart;
|
|
|
}, function () {
|
|
}, function () {
|
|
|
- var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
|
|
|
|
|
|
|
+ var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
|
|
|
_d3.selectAll(".nv-bar").on("click",
|
|
_d3.selectAll(".nv-bar").on("click",
|
|
|
function (d, i) {
|
|
function (d, i) {
|
|
|
if (typeof options.onClick != "undefined") {
|
|
if (typeof options.onClick != "undefined") {
|
|
@@ -566,6 +566,441 @@ function barChartBuilder(element, options, isTimeline) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ko.bindingHandlers.partitionChart = {
|
|
|
|
|
+ update: function (element, valueAccessor) {
|
|
|
|
|
+
|
|
|
|
|
+ var MIN_HEIGHT_FOR_TOOLTIP = 24;
|
|
|
|
|
+
|
|
|
|
|
+ var _options = valueAccessor();
|
|
|
|
|
+ var _data = _options.transformer(valueAccessor().datum);
|
|
|
|
|
+
|
|
|
|
|
+ var _w = $(element).width(),
|
|
|
|
|
+ _h = 300,
|
|
|
|
|
+ _x = d3.scale.linear().range([0, _w]),
|
|
|
|
|
+ _y = d3.scale.linear().range([0, _h]);
|
|
|
|
|
+
|
|
|
|
|
+ var _tip = d3.tip()
|
|
|
|
|
+ .attr("class", "d3-tip")
|
|
|
|
|
+ .html(function (d) {
|
|
|
|
|
+ if (d.depth < 2) {
|
|
|
|
|
+ return d.name + " (" + d.value + ")";
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ return d.parent.name + " - " + d.name + " (" + d.value + ")";
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .offset([-12, 0])
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ var _svg = d3.select(element).append("svg:svg");
|
|
|
|
|
+ _svg.call(_tip);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ var _vis = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
|
|
|
|
|
+ _vis.attr("class", "partitionChart")
|
|
|
|
|
+ .style("width", _w + "px")
|
|
|
|
|
+ .style("height", _h + "px")
|
|
|
|
|
+ .append("svg:svg")
|
|
|
|
|
+ .attr("width", _w)
|
|
|
|
|
+ .attr("height", _h);
|
|
|
|
|
+
|
|
|
|
|
+ var _partition = d3.layout.partition()
|
|
|
|
|
+ .value(function (d) {
|
|
|
|
|
+ return d.size;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ var g = _vis.selectAll("g")
|
|
|
|
|
+ .data(_partition.nodes(_data))
|
|
|
|
|
+ .enter().append("svg:g")
|
|
|
|
|
+ .attr("transform", function (d) {
|
|
|
|
|
+ return "translate(" + _x(d.y) + "," + _y(d.x) + ")";
|
|
|
|
|
+ })
|
|
|
|
|
+ .on("click", click)
|
|
|
|
|
+ .on("dblclick", function (d, i) {
|
|
|
|
|
+ if (typeof _options.onClick != "undefined") {
|
|
|
|
|
+ chartsUpdatingState();
|
|
|
|
|
+ _options.onClick(d);
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .on("mouseover", function (d, i) {
|
|
|
|
|
+ if (element.querySelectorAll("rect")[i].getBBox().height < MIN_HEIGHT_FOR_TOOLTIP) {
|
|
|
|
|
+ _tip.attr("class", "d3-tip").show(d);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (this.__data__.parent == undefined) return;
|
|
|
|
|
+ d3.select(this).select("rect").classed("mouseover", true)
|
|
|
|
|
+ })
|
|
|
|
|
+ .on("mouseout", function (d, i) {
|
|
|
|
|
+ if (element.querySelectorAll("rect")[i].getBBox().height < MIN_HEIGHT_FOR_TOOLTIP) {
|
|
|
|
|
+ _tip.attr("class", "d3-tip").show(d);
|
|
|
|
|
+ _tip.hide();
|
|
|
|
|
+ }
|
|
|
|
|
+ d3.select(this).select("rect").classed("mouseover", false)
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ var _kx = _w / _data.dx,
|
|
|
|
|
+ _ky = _h / 1;
|
|
|
|
|
+
|
|
|
|
|
+ var _colors = HueColors.scale(HueColors.DARK_BLUE, HueColors.BLUE, 5)
|
|
|
|
|
+
|
|
|
|
|
+ g.append("svg:rect")
|
|
|
|
|
+ .attr("width", _data.dy * _kx)
|
|
|
|
|
+ .attr("height", function (d) {
|
|
|
|
|
+ return d.dx * _ky;
|
|
|
|
|
+ })
|
|
|
|
|
+ .attr("class", function (d) {
|
|
|
|
|
+ return d.children ? "parent" : "child";
|
|
|
|
|
+ })
|
|
|
|
|
+ .attr("stroke", HueColors.DARK_BLUE)
|
|
|
|
|
+ .attr("fill", function (d, i) {
|
|
|
|
|
+ return _colors[d.depth];
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ g.append("svg:text")
|
|
|
|
|
+ .attr("transform", transform)
|
|
|
|
|
+ .attr("dy", ".35em")
|
|
|
|
|
+ .style("opacity", function (d) {
|
|
|
|
|
+ return d.dx * _ky > 12 ? 1 : 0;
|
|
|
|
|
+ })
|
|
|
|
|
+ .text(function (d) {
|
|
|
|
|
+ if (d.depth < 2) {
|
|
|
|
|
+ return d.name + " (" + d.value + ")";
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ return d.parent.name + " - " + d.name + " (" + d.value + ")";
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ d3.select(window)
|
|
|
|
|
+ .on("click", function () {
|
|
|
|
|
+ click(_data);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ function click(d) {
|
|
|
|
|
+ _tip.hide();
|
|
|
|
|
+ if (!d.children) return;
|
|
|
|
|
+
|
|
|
|
|
+ _kx = (d.y ? _w - 40 : _w) / (1 - d.y);
|
|
|
|
|
+ _ky = _h / d.dx;
|
|
|
|
|
+ _x.domain([d.y, 1]).range([d.y ? 40 : 0, _w]);
|
|
|
|
|
+ _y.domain([d.x, d.x + d.dx]);
|
|
|
|
|
+
|
|
|
|
|
+ var t = g.transition()
|
|
|
|
|
+ .duration(d3.event.altKey ? 7500 : 750)
|
|
|
|
|
+ .attr("transform", function (d) {
|
|
|
|
|
+ return "translate(" + _x(d.y) + "," + _y(d.x) + ")";
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ t.select("rect")
|
|
|
|
|
+ .attr("width", d.dy * _kx)
|
|
|
|
|
+ .attr("height", function (d) {
|
|
|
|
|
+ return d.dx * _ky;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ t.select("text")
|
|
|
|
|
+ .attr("transform", transform)
|
|
|
|
|
+ .style("opacity", function (d) {
|
|
|
|
|
+ return d.dx * _ky > 12 ? 1 : 0;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ d3.event.stopPropagation();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function transform(d) {
|
|
|
|
|
+ return "translate(8," + d.dx * _ky / 2 + ")";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
function chartsUpdatingState() {
|
|
function chartsUpdatingState() {
|
|
|
$(document).find("svg").css("opacity", "0.5");
|
|
$(document).find("svg").css("opacity", "0.5");
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+var tipBuilder = function () {
|
|
|
|
|
+ var direction = d3_tip_direction,
|
|
|
|
|
+ offset = d3_tip_offset,
|
|
|
|
|
+ html = d3_tip_html,
|
|
|
|
|
+ node = initNode(),
|
|
|
|
|
+ svg = null,
|
|
|
|
|
+ point = null,
|
|
|
|
|
+ target = null
|
|
|
|
|
+
|
|
|
|
|
+ function tip(vis) {
|
|
|
|
|
+ svg = getSVGNode(vis)
|
|
|
|
|
+ point = svg.createSVGPoint()
|
|
|
|
|
+ document.body.appendChild(node)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Public - show the tooltip on the screen
|
|
|
|
|
+ //
|
|
|
|
|
+ // Returns a tip
|
|
|
|
|
+ tip.show = function () {
|
|
|
|
|
+ var args = Array.prototype.slice.call(arguments)
|
|
|
|
|
+ if (args[args.length - 1] instanceof SVGElement) target = args.pop()
|
|
|
|
|
+
|
|
|
|
|
+ var content = html.apply(this, args),
|
|
|
|
|
+ poffset = offset.apply(this, args),
|
|
|
|
|
+ dir = direction.apply(this, args),
|
|
|
|
|
+ nodel = d3.select(node), i = 0,
|
|
|
|
|
+ coords
|
|
|
|
|
+
|
|
|
|
|
+ nodel.html(content)
|
|
|
|
|
+ .style({ opacity: 1, "pointer-events": "all" })
|
|
|
|
|
+
|
|
|
|
|
+ while (i--) nodel.classed(directions[i], false)
|
|
|
|
|
+ coords = direction_callbacks.get(dir).apply(this)
|
|
|
|
|
+ nodel.classed(dir, true).style({
|
|
|
|
|
+ top: (coords.top + poffset[0]) + "px",
|
|
|
|
|
+ left: (coords.left + poffset[1]) + "px"
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return tip
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Public - hide the tooltip
|
|
|
|
|
+ //
|
|
|
|
|
+ // Returns a tip
|
|
|
|
|
+ tip.hide = function () {
|
|
|
|
|
+ nodel = d3.select(node)
|
|
|
|
|
+ nodel.style({ opacity: 0, "pointer-events": "none" })
|
|
|
|
|
+ return tip
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
|
|
|
|
|
+ //
|
|
|
|
|
+ // n - name of the attribute
|
|
|
|
|
+ // v - value of the attribute
|
|
|
|
|
+ //
|
|
|
|
|
+ // Returns tip or attribute value
|
|
|
|
|
+ tip.attr = function (n, v) {
|
|
|
|
|
+ if (arguments.length < 2 && typeof n === "string") {
|
|
|
|
|
+ return d3.select(node).attr(n)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ var args = Array.prototype.slice.call(arguments)
|
|
|
|
|
+ d3.selection.prototype.attr.apply(d3.select(node), args)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return tip
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
|
|
|
|
|
+ //
|
|
|
|
|
+ // n - name of the property
|
|
|
|
|
+ // v - value of the property
|
|
|
|
|
+ //
|
|
|
|
|
+ // Returns tip or style property value
|
|
|
|
|
+ tip.style = function (n, v) {
|
|
|
|
|
+ if (arguments.length < 2 && typeof n === "string") {
|
|
|
|
|
+ return d3.select(node).style(n)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ var args = Array.prototype.slice.call(arguments)
|
|
|
|
|
+ d3.selection.prototype.style.apply(d3.select(node), args)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return tip
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Public: Set or get the direction of the tooltip
|
|
|
|
|
+ //
|
|
|
|
|
+ // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
|
|
|
|
|
+ // sw(southwest), ne(northeast) or se(southeast)
|
|
|
|
|
+ //
|
|
|
|
|
+ // Returns tip or direction
|
|
|
|
|
+ tip.direction = function (v) {
|
|
|
|
|
+ if (!arguments.length) return direction
|
|
|
|
|
+ direction = v == null ? v : d3.functor(v)
|
|
|
|
|
+
|
|
|
|
|
+ return tip
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Public: Sets or gets the offset of the tip
|
|
|
|
|
+ //
|
|
|
|
|
+ // v - Array of [x, y] offset
|
|
|
|
|
+ //
|
|
|
|
|
+ // Returns offset or
|
|
|
|
|
+ tip.offset = function (v) {
|
|
|
|
|
+ if (!arguments.length) return offset
|
|
|
|
|
+ offset = v == null ? v : d3.functor(v)
|
|
|
|
|
+
|
|
|
|
|
+ return tip
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Public: sets or gets the html value of the tooltip
|
|
|
|
|
+ //
|
|
|
|
|
+ // v - String value of the tip
|
|
|
|
|
+ //
|
|
|
|
|
+ // Returns html value or tip
|
|
|
|
|
+ tip.html = function (v) {
|
|
|
|
|
+ if (!arguments.length) return html
|
|
|
|
|
+ html = v == null ? v : d3.functor(v)
|
|
|
|
|
+
|
|
|
|
|
+ return tip
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function d3_tip_direction() {
|
|
|
|
|
+ return "n"
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function d3_tip_offset() {
|
|
|
|
|
+ return [0, 0]
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function d3_tip_html() {
|
|
|
|
|
+ return " "
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var direction_callbacks = d3.map({
|
|
|
|
|
+ n: direction_n,
|
|
|
|
|
+ s: direction_s,
|
|
|
|
|
+ e: direction_e,
|
|
|
|
|
+ w: direction_w,
|
|
|
|
|
+ nw: direction_nw,
|
|
|
|
|
+ ne: direction_ne,
|
|
|
|
|
+ sw: direction_sw,
|
|
|
|
|
+ se: direction_se
|
|
|
|
|
+ }),
|
|
|
|
|
+
|
|
|
|
|
+ directions = direction_callbacks.keys()
|
|
|
|
|
+
|
|
|
|
|
+ function direction_n() {
|
|
|
|
|
+ var bbox = getScreenBBox()
|
|
|
|
|
+ return {
|
|
|
|
|
+ top: bbox.n.y - node.offsetHeight,
|
|
|
|
|
+ left: bbox.n.x - node.offsetWidth / 2
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function direction_s() {
|
|
|
|
|
+ var bbox = getScreenBBox()
|
|
|
|
|
+ return {
|
|
|
|
|
+ top: bbox.s.y,
|
|
|
|
|
+ left: bbox.s.x - node.offsetWidth / 2
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function direction_e() {
|
|
|
|
|
+ var bbox = getScreenBBox()
|
|
|
|
|
+ return {
|
|
|
|
|
+ top: bbox.e.y - node.offsetHeight / 2,
|
|
|
|
|
+ left: bbox.e.x
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function direction_w() {
|
|
|
|
|
+ var bbox = getScreenBBox()
|
|
|
|
|
+ return {
|
|
|
|
|
+ top: bbox.w.y - node.offsetHeight / 2,
|
|
|
|
|
+ left: bbox.w.x - node.offsetWidth
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function direction_nw() {
|
|
|
|
|
+ var bbox = getScreenBBox()
|
|
|
|
|
+ return {
|
|
|
|
|
+ top: bbox.nw.y - node.offsetHeight,
|
|
|
|
|
+ left: bbox.nw.x - node.offsetWidth
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function direction_ne() {
|
|
|
|
|
+ var bbox = getScreenBBox()
|
|
|
|
|
+ return {
|
|
|
|
|
+ top: bbox.ne.y - node.offsetHeight,
|
|
|
|
|
+ left: bbox.ne.x
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function direction_sw() {
|
|
|
|
|
+ var bbox = getScreenBBox()
|
|
|
|
|
+ return {
|
|
|
|
|
+ top: bbox.sw.y,
|
|
|
|
|
+ left: bbox.sw.x - node.offsetWidth
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function direction_se() {
|
|
|
|
|
+ var bbox = getScreenBBox()
|
|
|
|
|
+ return {
|
|
|
|
|
+ top: bbox.se.y,
|
|
|
|
|
+ left: bbox.e.x
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function initNode() {
|
|
|
|
|
+ var node = d3.select(document.createElement("div"))
|
|
|
|
|
+ node.style({
|
|
|
|
|
+ position: "absolute",
|
|
|
|
|
+ opacity: 0,
|
|
|
|
|
+ pointerEvents: "none",
|
|
|
|
|
+ boxSizing: "border-box"
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return node.node()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function getSVGNode(el) {
|
|
|
|
|
+ el = el.node()
|
|
|
|
|
+ if (el != null) {
|
|
|
|
|
+ if (el.tagName != null && el.tagName.toLowerCase() == "svg")
|
|
|
|
|
+ return el
|
|
|
|
|
+
|
|
|
|
|
+ return el.ownerSVGElement
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Private - gets the screen coordinates of a shape
|
|
|
|
|
+ //
|
|
|
|
|
+ // Given a shape on the screen, will return an SVGPoint for the directions
|
|
|
|
|
+ // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
|
|
|
|
|
+ // sw(southwest).
|
|
|
|
|
+ //
|
|
|
|
|
+ // +-+-+
|
|
|
|
|
+ // | |
|
|
|
|
|
+ // + +
|
|
|
|
|
+ // | |
|
|
|
|
|
+ // +-+-+
|
|
|
|
|
+ //
|
|
|
|
|
+ // Returns an Object {n, s, e, w, nw, sw, ne, se}
|
|
|
|
|
+ function getScreenBBox() {
|
|
|
|
|
+ var targetel = target || d3.event.target,
|
|
|
|
|
+ bbox = {},
|
|
|
|
|
+ matrix = targetel.getScreenCTM(),
|
|
|
|
|
+ tbbox = targetel.getBBox(),
|
|
|
|
|
+ width = tbbox.width,
|
|
|
|
|
+ height = tbbox.height,
|
|
|
|
|
+ x = tbbox.x,
|
|
|
|
|
+ y = tbbox.y,
|
|
|
|
|
+ scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
|
|
|
|
|
+ scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ point.x = x + scrollLeft
|
|
|
|
|
+ point.y = y + scrollTop
|
|
|
|
|
+ bbox.nw = point.matrixTransform(matrix)
|
|
|
|
|
+ point.x += width
|
|
|
|
|
+ bbox.ne = point.matrixTransform(matrix)
|
|
|
|
|
+ point.y += height
|
|
|
|
|
+ bbox.se = point.matrixTransform(matrix)
|
|
|
|
|
+ point.x -= width
|
|
|
|
|
+ bbox.sw = point.matrixTransform(matrix)
|
|
|
|
|
+ point.y -= height / 2
|
|
|
|
|
+ bbox.w = point.matrixTransform(matrix)
|
|
|
|
|
+ point.x += width
|
|
|
|
|
+ bbox.e = point.matrixTransform(matrix)
|
|
|
|
|
+ point.x -= width / 2
|
|
|
|
|
+ point.y -= height / 2
|
|
|
|
|
+ bbox.n = point.matrixTransform(matrix)
|
|
|
|
|
+ point.y += height
|
|
|
|
|
+ bbox.s = point.matrixTransform(matrix)
|
|
|
|
|
+
|
|
|
|
|
+ return bbox
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return tip
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+d3.tip = tipBuilder;
|