How to disable selected node in jstree? - jstree

How can I disable default action for the selected node?
When user selects a node, this node should not be clickable, until another node is selected.
This is a very common feature, but I cannot seem to make it work.
Regards
Dimitris

I solved this by handling the select_node.jstree event and using the types plugin.
var treeConfig = {
plugins: ["ui", "types"],
types: {
valid_children: ["selected"],
types: {
"selected": {
"select_node": false
}
}
}
}
var tree = $("#navtree");
tree.jstree(treeConfig)
.bind("select_node.jstree", function (e, data){
tree.find('[rel="selected"]').removeAttr('rel');
data.rslt.obj.attr("rel", 'selected');
});
Basically, on select_node, I remove any rel=selected attribute in the tree, and then apply a rel=selected attribute to the selected node. In types, I disable the select_node function for the "selected" type.

Related

Make node fixed in echarts force graph

There is a way to set the initial position of nodes in a force graph in echarts. But is there a way to have this node stay at this position?
Of course,there is an attribute named fixed decide a node fix or not.So you can set an event listener on echarts.For example,I set a click event listener like:
myChart.on('click', function (params) {
fixNode(params.data);
});
The params.data is the object that you click on echarts.Then you should write a fixNode method like:
function fixNode(currentNode){
_nodes.forEach(function (node) {
if(node.name==currentNode.name) node.fixed = true;
});
refresh();
}
This method is to traverse the node array named _nodes and find the same node as currentNode in _nodes.when we find it,we can set its attribute fixed true.Finally, we have to rebind data to echarts,so we write a method to refresh echarts:
function refresh(){
option={
series:[
{
data:_nodes
}
]
};
mycharts.setOption(option);
}
Now,the node that you click will fixed in a position.

Select Child nodes when parent is also selected in JSTREE

I am having difficulties by selecting child nodes when parent is also selected , also would like to open subfolders and select all childs (not sure if im making it clear) so I have know how to get all the child nodes by:
selected_nodes = $("#demo").jstree("get_selected", null, true);
var tree = jQuery.jstree._reference('#demo');
var children = tree._get_children(selected_nodes);
but doest really select or open child folder and nodes
This might not be what OP wanted but on JSTree 3.3. I used this to open all nodes under a selected parent.
$(treeContainer).bind("select_node.jstree", function (e, data) {
return data.instance.open_all(data.node);
});
I gave up on this Idea.. now im just doing ajax requests to load the childs and receive a json object, and from there i can see if its a file or directory, if its a directory again another request and like this i have the whole structure
You have to turn on two_state checkboxes to allow parent and child nodes to be selected indepentently. Below I've configured the "two_state" parameter for the checkbox plugin:
$("#docTree").jstree({
"themes": {
"theme": "classic",
"url": "jstree/themes/classic/style.css"
},
"plugins": ["themes", "ui", "checkbox", "json_data"],
"checkbox": { "two_state" : true }
})
Check documentation here: http://www.jstree.com/documentation/checkbox
If I understand this correctly you want to select all of the lowest descendants in a jsTree (the files) when one of their parents (the folders) have been selected.
Unfortunately I haven't found a more direct approach than the one below. I'm using jsTree 3.1.1 and managed to solve this problem using the following:
var $demo = $("#demo");
var nodes = $demo.jstree("get_top_selected", true);
//Selects all of the children of each selected node including folders
if(nodes.length > 0){
nodes.forEach(function(node, i){
$demo.jstree("select_node", node.children_d, true, false);
});
}
var fileNodes = $demo.jstree("get_bottom_selected", false);
//We now need to deselect everything and only select the file nodes
$demo.jstree("deselect_all", true);
$demo.jstree("select_node", fileNodes, true, false);
The above code allows the user to "select" multiple folders and have those files selected.
The parameter with the value true for the "get_top_selected" function returns the full node instead of just ID's. This lets you get access to the node's children.
Function "select_node" takes three parameters. The first is the nodes to select (in this case the descendants of the current parent node). If the second parameter is set to true it prevents the changed.jstree event from firing for each selected node. The third parameter is set to false as setting to true prevents the children folders from opening.
The function "get_bottom_selected" only returns a node if it has both been selected and it itself does not have any children. As we are now only interested in the node ID's we can pass the parameter false (or omit it completely).
Passing a parameter of true to the function "deselect_all" again prevents the changed.jstree event from firing.
If you want to check out the jsTree API docs you can find them here. That list is filtered to only include the select functions and events. A full list of the API can be found here.
I hope this helps but let me know if you require further clarification on any of the code ^_^
select all child nodes when parent selected ,
$(data.rslt.obj).find("li").each( function( idx, listItem ) {
var child = $(listItem); // child object
$.jstree._reference("#associateRightHandTree").check_node(child);
});
unselect all child nodes when parent unselected ,
$(data.rslt.obj).find("li").each( function( idx, listItem ) {
var child = $(listItem); // child object
$.jstree._reference("#associateRightHandTree").uncheck_node(child);
});

jstree move, drag and drop

I want to implement the move functionality for a node in jstree. Is it the move that needs to be implemented or the drag and drop? Also, it would be nice to have working code for binding the container to event and the event code.
You only need to use the dnd plugin if you don't need to enforce any move rules(don't allow certain nodes to be moved to other nodes etc)
If you need to enforce move rules, you can add the crrm plugin.
See the Reorder only demo of the dnd pluign documentation for an example of this. The documentation is very poor, so you will have to use the developer tool on your browser to see what the properties of the parameter for the check_move callback are. For the example in the documentation, m.o refers to your dragged node and m.r refers to your destination node.
You will also likely need to be notified when a node is moved, so bind to the move_node.jstree event when you initialize the tree:
$("#treeHost").jstree({
// ...
}).bind("move_node.jstree", function (e, data) {
// data.rslt.o is a list of objects that were moved
// Inspect data using your fav dev tools to see what the properties are
});
$("#demo1").jstree({
....
.bind("move_node.jstree", function (e, data) {
/*
requires crrm plugin
.o - the node being moved
.r - the reference node in the move
.ot - the origin tree instance
.rt - the reference tree instance
.p - the position to move to (may be a string - "last", "first", etc)
.cp - the calculated position to move to (always a number)
.np - the new parent
.oc - the original node (if there was a copy)
.cy - boolen indicating if the move was a copy
.cr - same as np, but if a root node is created this is -1
.op - the former parent
.or - the node that was previously in the position of the moved node */
var nodeType = $(data.rslt.o).attr("rel");
var parentType = $(data.rslt.np).attr("rel");
if (nodeType && parentType) {
// TODO!
}
})
});
The above approaches do not work with the latest versions of jstree (3.3.7 as of today).
The first line of Bojin's answer still holds true. To implement rules, you can use core.check_callback or possibly, the types plugin; the crrm plugin doesn't exist anymore. Bind to move_node.jstree to perform some action on completion of move (drop). By default, the dnd plugin allows re-ordering (dropping between two nodes) and copying (Ctrl + drag), in addition to moving a node. The code snippet below shows how to disable these additional behaviors.
$('#treeElement').jstree({
'core': {
'check_callback': CheckOperation,
...
},
'plugins': ['dnd']
})
.bind("move_node.jstree", function(e, data) {
//data.node was dragged and dropped on data.parent
});
function CheckOperation(operation, node, parent, position, more) {
if (operation == "move_node") {
if (more && more.dnd && more.pos !== "i") { // disallow re-ordering
return false;
}
... more rules if needed ...
else {
return true;
}
}
else if (operation == "copy_node") {
return false;
}
return true;
}

jquery selection with .not()

I have some troubles with jQuery.
I have a set of Divs with .square classes. Only one of them is supposed to have an .active class. This .active class may be activated/de-activated onClick.
Here is my code :
jQuery().ready(function() {
$(".square").not(".active").click(function() {
//initialize
$('.square').removeClass('active');
//activation
$(this).addClass('active');
// some action here...
});
$('.square.active').click(function() {
$(this).removeClass('active');
});
});
My problem is that the first function si called, even if I click on an active .square, as if the selector was not working. In fact, this seems to be due to the addClass('active') line...
Would you have an idea how to fix this ?
Thanks
Just to give something different from the other answers. Lonesomeday is correct in saying the function is bound to whatever they are at the start. This doesn't change.
The following code uses the live method of jQuery to keep on top of things. Live will always handle whatever the selector is referencing so it continually updates if you change your class. You can also dynamically add new divs with the square class and they will automatically have the handler too.
$(".square:not(.active)").live('click', function() {
$('.square').removeClass('active');
$(this).addClass('active');
});
$('.square.active').live('click', function() {
$(this).removeClass('active');
});
Example working: http://jsfiddle.net/jonathon/mxY3Y/
Note: I'm not saying this is how I would do it (depends exactly on your requirement) but it is just another way to look at things.
This is because the function is bound to elements that don't have the active class when you create them. You should bind to all .square elements and take differing actions depending on whether the element has the class active:
$(document).ready(function(){
$('.square').click(function(){
var clicked = $(this);
if (clicked.hasClass('active')) {
clicked.removeClass('active');
} else {
$('.square').removeClass('active');
clicked.addClass('active');
}
});
});

Wanted: Directions/ideas for a custom tree-to-tree drag'n'drop implementation in ExtJS

I need some combined functionality regarding drag'n'drop between two trees in ExtJS.
The first required feature is very simple and is just the builtin drag'n'drop features isolated to a single tree only.
The second required feature is that I wan't the user to be able to drag a node from the left tree and drop it at any node in the right tree.
The action should not remove the node from the left tree, thus creating the possibility of dragging the same node from the left tree to multiple places in the right tree.
My question is: Which approach should I take to combine these two functionalities, utilizing the existing possibilities in the TreePanel object without inventing the wheel again? I am not looking for a complete solution (it would be nice though ;-) ), but rather how to handle drag/drop-zones, events and so on.
Okay. I have been thinking about this some time now, and the following approach seems to work for me :)
I have configured the left tree as this:
listeners:
{
beforenodedrop: function (dropEvent) {
// Does this node come from the right tree?
if (dropEvent.source.tree.id !== dropEvent.tree.id) {
// The node should be discarded.
dropEvent.dropNode.parentNode.removeChild(dropEvent.dropNode, true);
// The node has been discarded, return drop succeeded.
dropEvent.dropStatus = true;
return false;
}
return true;
},
nodedragover: function (dragevent) {
// If the node comes from the right tree, it is allowed to be dropped here.
if (dragevent.source.tree.id !== dragevent.tree.id) {
return true;
}
// A node from this tree is not allowed to be dropped.
return false;
}
}
The right tree is configured like this:
listeners:
{
beforenodedrop: function (dropEvent) {
// Does this node come from the left tree?
if (dropEvent.source.tree.id !== dropEvent.tree.id) {
// The node should be cloned and inserted in the right tree.
// Copy the node.
var node = dropEvent.dropNode; // the node that was dropped
var nodeCopy = new Ext.tree.TreeNode( // copy it
Ext.apply({}, node.attributes)
);
// Match the id's.
nodeCopy.id = Ext.id(null,'newnode') + '_' + node.id;
// Find the right place to put it.
if (dropEvent.target.parentNode === dropEvent.tree.getRootNode()) {
// The node is placed on a folder, thus drop it there.
dropEvent.target.appendChild(nodeCopy);
} else {
// The node is placed inside a folder, thus place it in there.
dropEvent.target.parentNode.appendChild(nodeCopy);
}
// The node has been dropped, return okay and stop further process.
dropEvent.dropStatus = true;
return false;
}
// Just use the normal builtin drag and drop.
return true;
}
}
Both trees has been set to enable Drag'n'Drop:
enableDD: true
All leaf nodes have the following configuration:
allowDrop: true,
draggable: true
All folders are set to:
allowDrop: true,
draggable: false
The conclusion is, that I have chosen to override some of the builtin drag'n'drop methods in the treepanel while still maintaining the builtin functionality.