I have similar code to
D3.js Collapsible Force Layout: Links are not being generated
and I need to be able to use Hierarchy.links with an accessor function for the children of my data. IE.
links = d3.layout.tree()
.children(function(d) { return d.children() })
.links(nodes)
I have to use this accessor function because i'm dynamically getting the children in the function children().
Should I simply monkey patch d3 and change the d3_layout_hierarchyLinks(nodes); function to use an accessor?
?
I ended up just using a different method of calcuating the links. Given by mbostock on github
Calculate links by hand:
function computeLinks(nodes) {
return d3.merge(nodes.map(function(parent) {
return parent.computeChildren().map(function(child) {
return {source: parent, target: child};
});
}));
}
Related
I'm using the Tippy.js v6 library, and I'm struggling to work out how to change the content of any one of my instances using the delegate method. All the answers I've found on SO reference methods that are no longer available in v6.
I'm using v6 via the CDN.
Current delegate code
// Delegate tippy
const delegateInstances = tippy.delegate("#order__lines-table", {
target: "[data-tippy-content]"
});
If I console.log(delegateInstances) this I get an array with my items, but I can't seem to work out how to target 1 single instance inside here.
An example of what I'm doing is when you click a button its state toggles and I want the tippy content to update. I had done this like follows, but they just stack on top of each other, the old content doesn't get removed.
const viewBtnIcon = viewBtn.querySelector('i');
viewBtnIcon.dataset.tippyContent = `View ${data.name}`;
tippy(viewBtnIcon, {
content: `View ${data.name}`
});
Basically I need to know how to target a specific instance and update the content. I have to use the delegate method (from what I understand) as content is dynamically added to the page.
The following code is how I got it to work based on issue #767 and issue #774 on the original GitHub repo
const viewBtnIcon = viewBtn.querySelector('i');
if (viewBtnIcon._tippy) {
viewBtnIcon._tippy.setContent(`View ${data.name}`);
} else {
viewBtnIcon.dataset.tippyContent = `View ${data.name}`;
}
I have a similar use and this is how I change the tip content dynamically:
the content property will be replaced with the content you set onShown, this will work even with async calls.
delegate("#tippyRoot", {
target: "[data-tippy-content]",
content: 'loading',
animation: "scale",
theme: "light",
trigger:'hover',
allowHTML: true,
onShown(instance) {
let cont = instance.reference.dataset.tippyContent;
//do something...
instance.setContent(cont);
},
});
This is an instance of Rappid Toolkit which uses jointJS for building visual tools as for web development. http://i.stack.imgur.com/6XSis.png
In this toolkit you can make a graph which can become a website.
My problem is the following one:
In every single element of this graph there is a box below it with:x,y,width,height,angle.
I want to change this information of this boxcontent and to display some info from this element but the code in which I have to add my snippet is the following(var Halo is the var for my element in the graph):
var halo = new joint.ui.Halo({
cellView: cellView,
boxContent: function(cellView) {
return"Here I want to display my box content info instead of x,y,width,height, angle";
}
}).render();
If I try to add my code inside it to access in JSON format my current element info my full code is:
var halo = new joint.ui.Halo({
cellView: cellView,
boxContent: function(cellView) {
// Drawing
var selectedObjectDataText = JSON.stringify(this.cellView.toJSON());
var selectedObjectDataJSON = JSON.parse(selectedObjectDataText);
return(selectedObjectDataJSON[0].wi_name);
}
}).render();
where wi_name is the name of my element but in the first line I can't access the specific element of my graph.
var selectedObjectDataText = JSON.stringify(this.cellView.toJSON());
Is there any global way to access my halo(my graph element) since this.cellView.toJSON() doesn't work?
I tried this.model.toJSON() this.cellView.model.toJSON() etc with no result
Note that JointJS links and elements are Backbone Models (linkView and elementView are Backbone Views).
To get the current value of an attribute use get() method.
boxContent: function(cellView) {
return cellView.model.get('wi_name');
}
Alternatively you can use prop(), that can return also nested properties of a model.
boxContent: function(cellView) {
return cellView.model.prop('wi_name');
}
It worked for var selectedObjectDataText = JSON.stringify(cellView.model.toJSON());
Thank you all for your support.
I'm creating a map using the modules system. I'm more or less used to D3.js v3 but I am still getting used to v4.
I am trying to add a dispatch but I don't know how to rebind the exports in V4, as this function is not available now.
So for my dispatch (_dis) and my particular event ("changetype"), the rebind in d3 v3 would be right before returning the exports, for example:
d3.mapDots = function (districts){
var _dis = d3.dispatch('changetype');
(...)
exports.color = function(_c){
if(!arguments.length) return color;
color = _c;
return this;
};
d3.rebind(exports,_dis,"on");
return exports
};
Does anyone know how to do this in v4? I've been trying dispatch.apply but it doesn't work.
Thanks!
Good question. Looks like the dispatch object has somewhat changed, and that d3.rebind no longer exists. Because the latter is gone, it appears that there's no way to "copy" (via d3.rebind) the .on() method. Instead you must implement your own. See here how bostock implemented d3-brush.
I put together this jsFiddle to demonstrate how to achieve with D3 v4 what you're asking.
The important bit is implementing the .on method:
instance.on = function() {
var value = dispatcher.on.apply(dispatcher, arguments);
return value === dispatcher ? instance : value;
}
And, dispatching is like this
dispatcher.call("was_clicked", this, "Hello, Foo!");
I previously asked a similar question before, however it seemed that I wasn't being precise enough about my question - hopefully this is.
Many examples of the Tree Layout format their hierarchy data set as this: https://gist.github.com/tchaymore/1249394#file-math_map_compact-json
However I wanted to change the "children" node in the json to "children1" for example
var flare = {
"Name": "Example",
"children1": [
{
"BName":"Ja",
"Email":"",
"children1":[
{
"NickName":"NC",
"id":2
}
],
}
]};
When I had changed the name of that node, I then used the children function:
var tree = d3.layout.tree()
.size([height, width])
.children(function(d) { return d.children1; });
After that I changed all of the "children" references to "children1" & so on.
However, now I have the problem of not being able to collapse the tree back into its parent. I've tried to use this example as a reference, but no luck: http://blog.pixelingene.com/2011/07/building-a-tree-diagram-in-d3-js/
Here's a example of my current problem: http://jsfiddle.net/mEyQW/1/
.. I apologize for the previous confusion
I don't really get what you wanted to do with your collapse() function and the _children1 but if you remove it, then everything works fine:
jsFiddle: http://jsfiddle.net/chrisJamesC/mEyQW/2/
I am trying to use a jQuery extension I came across (handsontable). I am having no problem creating the table
var spreadsheet = $("#dataTable").handsontable({
rows: 3,
cols: 15,
minSpareRows: 2
});
However after I create the table I want to call various helper functions I see declared in the javascript for the Handsontable object. The problem is the extension seems to return this.each(function() { ... }); and I don't understand how I can access the underlaying Handsontable object from this. The js for the extension can be found here and I put a small demo together on the following link
http://jsfiddle.net/7JTG2/7/
as you can see I would like get the data of one of the cells when I click a button.
The relevant code is in the end:
$.fn.handsontable = function (action, options) {
if (typeof action !== 'string') { //init
options = action;
return this.each(function () {
if($(this).data("handsontable")) {
instance = $(this).data("handsontable");
...
} else {
...
instance = new Handsontable($(this), currentSettings);
$(this).data("handsontable", instance);
}
});
}
}
That means, the code sets the Handsontable instances as a data attribute to the elements (and returns the selected set to be chainable). Having one element, you can easily extract it with instance = $el.data("handsontable"). If you have a set of elements, you will need to loop over it - e.g. with each().
Looks like you could just use the onChange method of the plugin to capture data every time it is entered automatically. No need for a button. A simple example to add to your code above.
onChange: function(data) {
$("#data").append(JSON.stringify(data));
}