I'm struggling with a dijit.Tree and I can't find what I need in the dojo documentation...
I want to change the style of a few elements in my tree, according to some conditions.
I am able to identify the elements through a combination of for loops and if evaluations :
itemList = this.tree.model.store._arrayOfAllItems;
for (var index in itemList) {
item = itemList[index];
if (item.<property> == ...) {
...
//This is where I want to change the style
...
}
...
}
But then, I fail to get the node id to call dojo.addClass(nodeId, newClass).
Am I parsing through the proper list, with the model.store._arrayOfAllItems? Is there a way to parse through the node list instead, and still access the data properties?
Thank you very much for your help!
Edit on 2015-11-23
With Richard's comments, I was able to obtain the result I was looking for. I have added a handler that connects the tree's onOpen event to a method that gets the open node map (from tree._itemNodesMap) and then fetch through the store. For every item in the store, it adjust the css if the id of the item being validated has an associated node in the open node map. It then looks recursively for children.
Thanks Richard for your help!
If you have the id of the node inside the tree, you can use the getNodesByItem function that tree has.
Although if your tree is dynamic and the contents can change, I would suggest writing a function that not only adds to your store but also adds to a class for the node formed in the tree.
Related
I'm editing a plugin that creates filters on an table like excel(drop-down), the problem is when I use it on a table that uses a table inside it, in fact the plugin will also take the values of the sub-table.
I therefore decided to exclude from the initial array, made up of all the rows, those elements that have a parent with a table that does not have an id.
So i forEach array and see if have id like:
this.tds.forEach((el) =>{
console.log(el.parentElement.parentElement.parentElement.id);
});
I was wondering if using parentElement three times like this is correct or there is another way
It's perfectly fine, as long as you're sure that the structure will always be the same.
But let's assume that you don't know if the structure will always be like this, but you do know the class of the parent you're looking for (or any other CSS query), then you could use the Element.closest() method to query your way up.
So let's say you want to find the closest table with an id value.
this.tds.forEach((el) => {
const parent = el.closest('table:not([id=""])');
if (parent !== null) {
console.log(parent.id);
}
});
This will walk up the DOM tree from the el as starting point, doing something in the likes of parentElement.parentElement.parentElement... until it reaches an element that has a value in the id attribute.
There's nothing wrong with the code.
But if you want to make the code a little more robust you can use Optional Chaining.
this.tds.forEach((el) =>{
console.log(el?.parentElement?.parentElement?.parentElement?.id);
});
So, I really love this example from Jake Zieve shown here: https://bl.ocks.org/jjzieve/a743242f46321491a950
Basically, on search for a term, the path to that node is highlighted. I would like to accomplish something similar but with the following caveats:
I would like to stay in D3 v4.
I'm concerned about cases where the path doesn't clear out on next node pick OR what happens when there are two nodes of the same
name (I would ideally like to highlight all paths)
I would like to AVOID using JQuery
Given a set search term (assume you're already getting the string from somewhere) I know I need to make use of the following lines specifically (you can see my stream of consciousness in the comments) but I'm just not quite sure where to start.
// Returns array of link objects between nodes.
var links1 = root.descendants().slice(1); //slice to get rid of company.
console.log(links1); //okay, this one is nice because it gives a depth number, this describes the actual link info, including the value, which I am setting link width on.
var links2 = root.links(); // to get objects with source and target properties. From here, I can pull in the parent name from a selected target, then iterate again back up until I get to source. Problem: what if I have TWO of the same named nodes???
console.log(links2);
Thoughts on this? I'll keep trying on my own, but I keep hitting roadblocks. My code can be found here: https://jsfiddle.net/KateJean/7o3suadx/
[UPDATE]
I was able to add a filter to the links2 to call back a specific entry. See
For example:
var searchTerm = "UX Designer"
var match = links2.filter(el => el.target.data.name === searchTerm); //full entry
console.log(match);
This single entry gives me all associated info, including the full list of all points back up to "COMPANY"
So, I can GET the data. I think the best way to accomplish what I want is to somehow add a class to each of these elements and then style on that "active" class.
Thank you!
I am new this ivh tree, https://github.com/iVantage/angular-ivh-treeview
I have been successfully able to configure this library, however I am not able to get the list of selected nodes, is there a way to get list of selected nodes programmatically?
The easiest way is to use ivhTreeviewBfs to collect selected nodes.
var selectedNodes = []
ivhTreeviewBfs(myTree, function(node) {
if(node.selected) {
selectedNodes.push(node)
}
})
Note that you can use ivhTreeviewOptions to get the appropriate "selected" attribute if you want to be fully generic. Also, folks will often want to only collect the top-most selected node for a given tree branch. In this case you can return false in the callback passed to ivhTreeviewBfs and that node's children will not be visited.
You can read more about the bfs service here.
I have an undirected graph in Vis.js and I would like to change the color and size of the adjacent nodes (scaling them according to values in a JS array) when a certain node is selected. How would I go about doing this? The documentation for vis.js network objects is unenlightening beyond the source for this example.
You can listen for click events to know when a user clicked a node.
network.on("click", function (params) {
console.log(params);
});
If you have creates your nodes in a DataSet, you can simply update them and Network will be automatically updated accordingly:
nodes.update({id: 4, label: "changed label"});
Elaborating on this answer in response to this question. The vis.js->Network documentation has all the details, you just have to put them in order.
You use the "on" method of the network instance in order to listen for events. See "Method Reference -> Global" at the link above. This "on" method takes two inputs. The first is the event to be listened for; the second is a function that specifies the action to be taken when the event occurs.
To understand how to use this information, see the "Events" section in the documentation link above. For click events, your code will look something like
network.on("click", function (params) {
console.log(params);
});
The first argument is always a string; in this case we are interested in the "click" event. The second argument is a callback function that takes a single argument (I called this argument "params" in the example above). The "Events" documentation (again, see link above) summarizes this structure for you. Specifically, if the click event is associated with a node, then the ID of the node that was clicked is accessible as params.nodes[0].
Back to the original question. To change the color of adjacent nodes, you first need an array of the adjacent nodes. You do this using the "getConnectedNodes" method (see "Method Reference -> Information" at the link above). This will give you an array of node IDs. Next, for each ID in that array, you need to update the properties you wish to change.
The easiest way to update node properties is to create your nodes using a DataSet. You are probably already doing so. See this example, and notice the lines
var nodes = new vis.DataSet([...]);
This nodes variable has its own update method. So if you have (e.g.,) a variable CurrentID that holds the node ID of a node you wish to modify, and you want to (e.g.,) change the label of that node to the text string stored in another variable newLabel, you would do
nodes.update({id:CurrentID, label:newLabel});
Thanks much for these helpful responses; one of the gotchas is that the assertion that one is probably already creating one's own dataset is likely false if using the Network documentation examples, which mostly do something like the following:
var nodeArr = [...];
var edgeArr = [...];
data = {nodeArr, edgeArr}
network = new vis.Network(container, data, options);
The update function is only available if the nodes are a Dateset rather than an array:
var nodeArr = [...];
var edgeArr = [...];
data = {new vis.DataSet(nodeArr), new vis.DataSet(edgeArr)}
network = new vis.Network(container, data, options);
When you are using the clientside javascript for a TreeView, there is a lot of information which i am unsure. I dont have a sample to test with, but i was wondering if the getNodeByText will recursively search for the first occurance, or just search the children under the selected node.
Some documentation is located at http://www.telerik.com/help/aspnet-ajax/treeview-client-objects-radtreeview.html but it doesnt answer my specific question.
From my experience, every Node function only affects 1 Level at the time.
So this code would only affect the first level of nodes (A Node at the root of the TreeView):
var firstLevelNode = yourTreeView.getNodeByText('someText');
then you can call this fonction on any Node, so:
var secondLevelNode = firstLevelNode.getNodeByText('someOtherText');
You see? If you want to search for underlying children nodes, you must iterate for every root Node, and if you're looking for a 3rd level Node, you have to iterate thru every 2nd level Node, and so on...