So I found this piece of code online which computes the dijkstra's shortest path algorithm on nodes in a d3 graph. The problem is that d3.rebind has been removed and I haven't found a way to fix this piece of code to make it work. Any suggestions? Also I know this code is not mine so that's why I'm having some problems understanding how to change the code. Thanks
d3.dijkstra = function () {
var dijkstra = {};
var nodes;
var edges;
var source;
var dispatch = d3.dispatch("start", "tick", "step", "end");
dijkstra.run = function (src) {
source = src;
var unvisited = [];
nodes.forEach(function (d) {
if (d != src) {
d.distance = Infinity;
unvisited.push(d);
d.visited = false;
}
});
var current = src;
current.distance = 0;
function tick() {
current.visited = true;
current.links.forEach(function(link) {
var tar = link.target;
if (!tar.visited) {
var dist = current.distance + link.value;
tar.distance = Math.min(dist, tar.distance);
}
});
if (unvisited.length == 0 || current.distance == Infinity) {
dispatch.end()
return true;
}
unvisited.sort(function(a, b) {
return b.distance - a.distance
});
current = unvisited.pop()
dispatch.tick();
return false;
}
d3.timer(tick);
};
dijkstra.nodes = function (_) {
if (!arguments.length)
return nodes;
else {
nodes = _;
return dijkstra;
}
};
dijkstra.edges = function (_) {
if (!arguments.length)
return edges;
else {
edges = _;
return dijkstra;
}
};
dijkstra.source = function(_) {
if (!arguments.length)
return source;
else {
source = _;
return dijkstra;
}
};
dispatch.on("start.code", dijkstra.run);
return d3.rebind(dijkstra, dispatch, "on", "end", "start", "tick");
};
As you know, d3.rebind()
was removed in D3 v4. According to Mike Bostock (D3 creator):
If you need such functionality you can copy the implementation from v3.
This is the source code from v3:
// Copies a variable number of methods from source to target.
d3.rebind = function(target, source) {
var i = 1, n = arguments.length, method;
while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
return target;
};
// Method is assumed to be a standard D3 getter-setter:
// If passed with no arguments, gets the value.
// If passed with arguments, sets the value and returns the target.
function d3_rebind(target, source, method) {
return function() {
var value = method.apply(source, arguments);
return value === source ? target : value;
};
}
As you'll see, its use is very straightforward.
So, suppose we have this code, running D3 v3:
var foo = {
hello: function() {
console.log("hello");
return this;
},
world: function() {
console.log("world");
return this;
}
};
var bar = {};
d3.rebind(bar, foo, "hello", "world")
bar.hello().world()
<script src="https://d3js.org/d3.v3.min.js"></script>
For having the same code using rebind
without D3 v3 you just need to copy the original function.
Here is it:
var foo = {
hello: function() {
console.log("hello");
return this;
},
world: function() {
console.log("world");
return this;
}
};
var bar = {};
rebind(bar, foo, "hello", "world");
bar.hello().world()
function rebind(target, source) {
var i = 1,
n = arguments.length,
method;
while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
return target;
};
function d3_rebind(target, source, method) {
return function() {
var value = method.apply(source, arguments);
return value === source ? target : value;
};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With