Programmatically Adding Nodes to a JsTree - javascript

I've been doing some troubleshooting and haven't been able to do what I thought would be a fairly simple operation, adding a node to a jstree programmatically. Currently I've been attempting to do this in the simplest way I can imagine:
$('#irrigationClimateStations')
.jstree({
'plugins' : ['themes', 'json_data', 'ui', 'crrm'],
'json_data': {
"data" : [
{
"data" : "A node",
"metadata" : { id : 23 },
"children" : [ "Child 1", "A Child 2" ]
}
]
},
'themes': {
'theme': 'weather'
}
});
The tree is created successfully, but when I attempt to add another node, nothing happens (and I receive no errors from jstree):
var newNode = {
'attr' : { 'id' : this.model.get('id') },
'data': {
'title': this.model.format('station_na'),
'icon': media_url + this.model._iconRootURL + 'weather-station-16x16.png'
}
};
// Add the tree element to the end of the tree
$.jstree._reference('#irrigationClimateStations').create_node("#irrigationClimateStations", "last", newNode);
I haven't been able to decipher the API based on the documentation or the source code> I've also tried creating the node using "Method 2" alluded to in the core documentation:
var parent = $('#irrigationClimateStations').jstree('get_selected');
$('#irrigationClimateStations').jstree("create", parent, "last", newNode, false, false);
Any help? I am running jstree v 1.0-rc3

Related

JSTree not displaying in container

I am trying to incorporate a JSTree structure into my javascript project; however, the tree doesn't seem to be displaying/rendering in its parent container. Here is the code that I am using to display the tree:
let tree=this.tree_div.find('#treeDiv');
tree.jstree(
{
"json_data":
{
"data": [
{
"data": "First",
"children": [{"data": "First"},{"data":"Second"},{"data": "Third"}]
},
{
"data": "Second",
"children": [{"data":"First"},{"data":"Second"},{"data": "Third"}]
},
{
"data": "Third",
"children": []
}
],
},
"plugins": ["checkbox","themes", "html_data", "ui"]
}
).bind("select_node.jstree", function(e, data){});
console.log(tree[0]);
In this example, #treeDiv is the div that is contained by the parent container.
In the last line where the value of the tree is printed, the following line comes up in the console:
To my understanding, this implies that the tree is being successfully initialized and set up, but it still isn't displaying on the web page. Any input would be appreciated. Thanks.
The most plausible explanation here would be that you are initializing the tree using the older jsTree API, while using the newer jsTree library.
Old JSON API: https://old.jstree.com/documentation/json_data
New JSON API: https://www.jstree.com/docs/json/
The newer API has a different object structure for populating the tree. Some of the functions and events remain the same, however many other things including the configuration object has changed.
myTree.jstree({ 'core' : {
'data' : [
'Simple root node',
{
'text' : 'Root node 2',
'state' : {
'opened' : true,
'selected' : true
},
'children' : [
{ 'text' : 'Child 1' },
'Child 2'
]
}
]
} });

manage neo4j cross relationship in d3.js

I start recently to work with Neo4j database and i'm trying to display a graph using d3js (i'm new with it too!).
For my test i used the movie example data include in neo4j.
Using JQuery ajax and neo4j REST API, i find a way to make it more or less work.
But currently i can't make an actor link to several movie (or i duplicate them!).
here is currently my Cypher request:
match (a)-[r]->(m) RETURN {id: id(m), name: m.title}, collect({name : a.name, id: id(a)})
and the answer i get look like this:
{
"columns" : [ "{id: id(m), name: m.title}", "collect({name : a.name, id: id(a)})" ],
"data" :
[
[
{ "id" : 3, "name" : "The Matrix Reloaded" },
[
{ "id" : 5, "name" : "Keanu Reeves" },
{ "id" : 6, "name" : "Laurence Fishburne" },
{ "id" : 7, "name" : "Carrie-Anne Moss" }
]
],
[
{ "id" : 4, "name" : "The Matrix Revolutions" },
[
{ "id" : 5, "name" : "Keanu Reeves" },
{ "id" : 6, "name" : "Laurence Fishburne" },
{ "id" : 7, "name" : "Carrie-Anne Moss" }
]
],
[
{ "id" : 2, "name" : "The Matrix" },
[
{ "id" : 5, "name" : "Keanu Reeves" },
{ "id" : 6, "name" : "Laurence Fishburne" },
{ "id" : 7, "name" : "Carrie-Anne Moss" }
]
]
]
}
So i'm thinking of 2 workarounds : either i find a way in d3 to do it (but i have a real hard time to understand d3js for this) or i change my cypher request to get the relationship in a different way.
i can of course make a huge workaround in javascript but my objective is to keep the code as much effective as possible (at the end i want to use it to get a lot of data).
i use the example here : http://bl.ocks.org/mbostock/1093130
where i modify the flatten function like this (and some other minor change) :
// Returns a list of all nodes under the root.
function flatten(root) {
var nodes = [], i = 0;
root.data.forEach(function(l) {
var childrenlist = [];
l[1].forEach(function(actor) {
var ac = { name: actor.name, id: actor.id };
childrenlist.push(ac);
nodes.push(ac);
});
var movie = { id: l[0].id, name: l[0].name, children: childrenlist };
nodes.push(movie);
});
return nodes;
}
/*! end of flatten */
So ! since i have a hard time with d3js, i'm looking a way to make my cypher request to give me the relationship info in a different way. more like this example : http://bl.ocks.org/mbostock/4062045
i'm really stuck because i don't know how to build my cypher request!
i'm looking for a way to get the relationship source and destination node id and the node list but i don't know how to do both!
i want to mix this 2 requests:
match (a)-[r]->(m) RETURN {id: id(m), name: m.title}}
and something like this (but i don't know how to get relationship source and dest):
match (a)-[r]->(m) RETURN {src: id(r.src), dst: id(r.dst)}
if you could help me it would be awesome ! i hope i'm clear enough.
of course i'm open to any other suggestions or leads!
Thanks in advance!

Knockout mapping does represent wished for html

I have a problem with knockout mapping. I'm using knockout mapping plugin to represent a form that is serialized in JSON. It was working before using the knockout mapping but I need to use knockout mapping since I want my properties to be observable.
You can see the working html here : http://jsfiddle.net/etiennenoel/wG9SZ
Here's my not working javascript code:
var formData =
{"data":
[
{
"groupName" : "Properties",
"content" :
[
{
"title" : "Calculation Method",
"formType" : "select",
"value" :
[
{
"title" : "Voltage Drop - Unbalanced",
"selected" : true
},
{
"title" : "Voltage Drop - Balanced"
}
]
},
{
"title" : "Tolerance (% V)",
"formType" : "textBox",
"value" : 0.01
},
{
"title" : "Calculation Options",
"formType" : "radio",
"value" :
[
{
"title" : "Flat Start (at Nominal Conditions",
"checked" : false
} ,
{
"title" : "Assume Line Transposition",
"checked" : true
}
]
},
{
"title" : "Adjust Conductor Resistance at",
"formType" : "textBox",
"disabled" : true,
"value" : 77,
"appendLabel" : true,
"appendLabelText" : "°F"
}
]
},
{
"groupName" : "Properties",
"content" :
[
{
"title" : "Calculation Method",
"formType" : "select",
"value" :
[
{
"title" : "Voltage Drop - Unbalanced",
"selected" : true
},
{
"title" : "Voltage Drop - Balanced"
}
]
},
{
"title" : "Tolerance (% V)",
"formType" : "textBox",
"value" : 0.01
},
{
"title" : "Calculation Options",
"formType" : "radio",
"value" :
[
{
"title" : "Flat Start (at Nominal Conditions",
"checked" : false
} ,
{
"title" : "Assume Line Transposition",
"checked" : true
}
]
},
{
"title" : "Adjust Conductor Resistance at",
"formType" : "textBox",
"disabled" : true,
"value" : 77,
"appendLabel" : true,
"appendLabelText" : "°F"
}
]
}
]
};
ko.mapping.fromJS(formData);
Here's the jsfiddle of the same code: http://jsfiddle.net/etiennenoel/wG9SZ/3/
What is the problem between when I use mapping and when I don't use it ?
In your second case you forgot to ApplyBindings.
ko.applyBindings(formData);
I don't know if this is the case with your scenario, but it's worth a post.
I had issues with the mapping plugin, when I had a more complex viewmodel with nested properties or lists. It turned out that after mapping to an already constructed viewmodel, the sub-objects were no more observables. With this issue, for me this code worked, what I've found somewhere (unfortunately I already really don't know where). I called this function for my viewmodel after mapping to that.
function makeAllObservables(observable) {
// Loop through its children
for (var child in observable()) {
// If this child is not an observable and is an object
if ((!ko.isObservable(observable()[child])) && (typeof observable()[child] === "object")) {
// Make it an observable
observable()[child] = ko.observable(observable()[child]);
// Make all of its children observables
makeAllObservables(observable()[child]);
}
}
};
Usage (when updating the model from server response, the first line should not be there):
var model = ko.observable({});
ko.mapping.fromJS(myJSObject, {}, model);
makeAllObservables(model);
ko.applyBindings(model);
I ment mapping to an already constructed viewmodel for example, when you want to update your viewmodel with new JSON data from server. In that case I lost nested bindings without the code above.
UPDATE: I've found the source where I borrowed the technique from, here. Note that I slightly modified that code in that post, because somehow that was not working for me.
You need to bind the mapped viewmodel to the view:
ko.applyBindings(ko.mapping.fromJS(formData));
and since everything is now an observable the logic in the view needs to be changed to use the method syntax:
<!-- ko if: $data.formType() === "select" -->
To get the options to display, you need to tell knockout what the property name is on the object:
<select data-bind="options: $data.value, optionsText: 'title'"></select>

Dojo - Dijit.Tree - Updating Tree

I created a simple tree based on a TreeStoreModel which is backed by ItemFileWriteStore.
I tried updating my tree by deleting and adding items to the store as below, but could not.
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.Tree");
dojo.addOnLoad(function () {
var tmpData = [{
"name" : "Dell",
"type" : "business",
"businessid" : "1",
"projectid" : "1",
"submenu" : [{
"name" : "OTP",
"type" : "product",
"productid" : "100"
}
]
}
];
var tmpData1 = [{
"name" : "Lenovo",
"type" : "business",
"businessid" : "1",
"projectid" : "1",
"submenu" : [{
"name" : "OTP",
"type" : "product",
"productid" : "100"
}
]
}
];
var store = new dojo.data.ItemFileWriteStore({
data : {
label : 'name',
items : tmpData
}
});
var treeModel = new dijit.tree.TreeStoreModel({
store : store,
query : {
type : 'business'
},
childrenAttrs : ["submenu"]
});
var divTestTree = dojo.create("div", null, dojo.body(), "first");
var mytree = new dijit.Tree({
model : treeModel
},
divTestTree);
/* Tree is created at this point */
/* Delete the item from the store, for some reason tempData is being reset*/
store.deleteItem(tmpData[0]);
/* save */
store.save();
/* Tree shows up no more at this point */
/* Try adding new item to the store */
store.newItem(tmpData1[0]);
/* save */
store.save();
/*nothing happens! */
});
I followed the lead from here, I must be missing something very trivial here. Please help.
Taken from that page
How do I refresh a Tree from the store?
This isn’t supported. The store needs to notify the tree of any changes to the data. Currently this is really only supported (out of the box) by dojo.data.ItemFileWriteStore, as setting up a client-server dojo.data source where the server notifies the client whenever the data has changed is quite complicated, and beyond the scope of dojo, which is a client-only solution.
The only way to update the tree is to re-draw it again :(
For anyone coming here looking for a solution the problem, 'I suspect there is a bug' is the only answer I got in the forum, so may be this is a bug - goo.gl/M7xg7

Dynamically creating nodes in a jstree tree structure

I have to retrieve a list of menu item from a database and display it in a tree structure I want to use the menu name as the node name and menu id as the id of the node.
The method I used was to retrieve the data using an ajax call and put them into a list and then display it as a tree.But I think dynamically creating nodes depending on the data is more efficient.
function createNodeList(){
$('#menuCPanel #contentData #tree').jstree({
"json_data" : {
/*"data" : [{
"data" : {title : "menuName"},
"attr" : {id : "menuId"},
"state" : "closed"
}
],*/
"ajax" :{
"type" : "POST",
"url" : "?m=admin?action=getNodeList",
"dataType" : "json",
"data" : function(result){
return {
id : result.attr ? result.attr("id") : result['menuId'],
title : result.attr ? result.attr("title") : result['menuName']
};
},
},
},
"callback" : {
},
"themes" : {
"theme" : "classic",
"dots" : true,
"icons" : true
},
"plugins" : ["json_data", "themes"]
}).bind("select_node.jstree", function (e, data) { alert(jQuery.data(data.rslt.obj[0], "jstree").id) });
}
}
this is the stucture of my json data
"data":[{"menuId":"1","menuName":"Top Menu"},{"menuId":"2","menuName":"Main Menu"},{"menuId":"3","menuName":"Bottom Menu"},{"menuId":"4","menuName":"Main Menu"}]}
I would like to know what is wrong with the above result and how to dynamically create a node within in the ajax.success();
I went through some examples but all of them use the jstree.cretate() which i can't invoke inside jstree.json_data.ajax.success()
thanks in advance :)
This is a standard jstree with json data, which also binds select_node to do actions when a node is selected. Nodes must not have an ID which are plain numbers or contain jquery special selector characters. Number IDs must have a standard character first. so 1 should be N1, 2 should be N2 for example.
$('#MyTreeDiv').jstree({
"json_data": {
"ajax": {
"type": "POST",
"url": "/MyServerPage.aspx?Action=GetNodes",
"data": function (n) { return { id: n.attr ? n.attr("id") : 0} },
}
},
"themes": {
"theme": "default",
"url": "/Content/Styles/JSTree.css",
"dots": false
},
"plugins": ["themes", "json_data", "ui", "crrm"]
}).bind("select_node.jstree", function (e, data) {
var selectedObj = data.rslt.obj;
alert(selectedObj.attr("id"));
});
The json returned from your server must be in the correct format as defined in the jstree documentation, and must no include several special characters, unless those characters are escaped or the json created using serialization.

Categories

Resources