jstree prevent moving node into child nodes - javascript

So I've been using jstree for a while now, but still can't get a handle on it, it's pretty much a headache but well, it was decided we were gonna work with it. The data I'm using comes from HTML (no JSON involved). The issue I'm having is that I'm not sure how to set that some nodes are not folders. Every node has a class and based on that class I'm able to change it's icon but if the user tries to send any node inside these nodes that are not supposed to be folders they will be able. I need to prevent this, one way or the other but every thing I've test so far has not work at all.
$("jstree").jstree({
"core": {
"animation": 0,
"check_callback": true
},
rules: { draggable: "all" },
"dnd": {
"drop_finish": function (data) {
if (data.o.attr("rel") === "ds") {
//update chart with new data here?
//using data.o.attr("id")
}
},
"drag_check": function (data) {
if (data.r.attr("rel") != "ds") {
return false;
}
return {
after: false,
before: false,
inside: true
};
}
},
"crrm": {
"move": {
"check_move": function (data) {
// alert(data.r.attr("id"));
if (data.r.attr("id") == "999") {
return false;
}
else {
return true;
}
}
}
},
"plugins": ["dnd", "crrm"]
});
That's what I'm using to create my tree. Also, I cannot disable drag and drop since some items should be moved if the user wants but obviously the user shouldn't be able to drag something into anything that is not a folder.
Thanks in advance for the help,
Regards,
Adrian.

I accomplished this by using the Types plugin jstree plugins. There you can define types of nodes and set the valid_children variable which types are allowed to be children. That means that users also cannot DnD nodes of the restricted type into the node.
In my example below I have a type "book" that could have "folder" and "file" nodes as children. The "file" type cannot have any children at all, because valid_childrenis defined empty.
$('#' + tree_id)
.jstree({
'core' : {
'check_callback' : true, //needed to enable create, remove, rename... events
"themes" : {
"stripes" : true
}
},
"types" : {
"book" : {
"valid_children" : ["folder", "file"],
"icon" : "img/1397762742_book.png"
},
"folder" : {
"valid_children" : ["folder", "file"],
"icon" : "img/1397751666_folder.png"
},
"file" : {
"valid_children" : [],
"icon" : "img/1397752227_page.png"
}
},
"contextmenu" : {
"items" : customMenu
},
"plugins" : ["sort", "dnd", "contextmenu", "types"]
});
The type attribute can be set when adding a new node
tree.create_node("#", {
"text" : "sample node",
"type" : "file"
});
or by using the set_type function. API

Related

How to prevent checkbox from being checked when a node is clicked on JSTree?

I don't want the checkbox to be checked when the node is clicked, only when the checkbox itself is clicked.
The code below was copied from the JSTree website I think, and I copied a few lines from a tutorial to enable checkboxes.
$('#ajaxx').jstree({
'core' : {
'data' : {
"url" : (node)=>{
return node.id === '#' ?
'./dirfilesapi.php?dirID=-1' :
('./dirfilesapi.php?dirID='+node.id);
},
"dataType" : "json" // needed only if you do not supply JSON headers
}
},"checkbox" : {
"keep_selected_style" : false
},
"plugins": ["checkbox"]
});
"checkbox" : {
"keep_selected_style" : false , "whole_node": false, "tie_selection": false
},
Solved. I don't remember if it was whole_node or tie_selection that did it.
I think it was both, with only whole_node set to false it was working only for either selection or deselection.

JSTree Exclude different nodes from selection

In my project I have 3 company root nodes and test children.With Checkboxes.
- []Company1
-- []Test1
-- []Test2
- []Company2
-- []Test1
-- []Test2
-- []Test 3
- []Company3
-- []Test1
The tree is much more complex, but for question I reduced the levels. However, I want to manage, that it is forbidden to select two Companies. As sample, if Test1 from Company2 is selected and the user select Test1 from Company1, then all selections from Company1 and Company3 get unchecked.
My code for the jstree is:
$(function () {
$('#html1').on('select_node.jstree', function(e, data){
var countSelected = data.selected.length;
if (countSelected>1) {
data.instance.deselect_node( [ data.selected[0] ] );
}
});
$.ajax({
type: "get",
url: "/jstreecontent",
dataType: "json",
success: function(data) {
$('#html1').jstree({
'core' : {
'data' : data
},
"checkbox" : {
"keep_selected_style" : false
},
"plugins" : [ "checkbox", "contextmenu"],
"checkbox": {
three_state : true, // to avoid that fact that checking a node also check others
whole_node : false, // to avoid checking the box just clicking the node
tie_selection : false // for checking without selecting and selecting without checking
},
"contextmenu": {
"items": function ($node) {
var tree = $("#html1").jstree(true);
if($node.a_attr.type === 'test')
return getTestContextMenu($node, tree);
}
}
});
},
complete: function() {
// This function will be triggered always, when ajax request is completed, even it fails/returns other status code
console.log("complete");
},
error: function() {
// This will be triggered when ajax request fail.
console.log("Error");
}
});
});
If I remove the part:
"checkbox": {
three_state : true, // to avoid that fact that checking a node also check others
whole_node : false, // to avoid checking the box just clicking the node
tie_selection : false // for checking without selecting and selecting without checking
},
The selection with the root nodes works perfect, just one root node is allowed, but I cannot select a whole root, just its nodes. So I think the
$('#html1').on('select_node.jstree', function(e, data){
var countSelected = data.selected.length;
if (countSelected>1) {
data.instance.deselect_node( [ data.selected[0] ] );
}
});
Is working on all nodes, not only on the top one. Maybe this is wrong.
But it seems, I fail with it, it is the wrong way. I hope someone else had the same problem in the past and give me a hint for this.

Echarts : Uncaught Error: Component series.force not exists. Load it first

I want to use the echarts to make a Data Visualization Force layout, when i follow the step to setup all option, it has an error, said
Uncaught Error: Component series.force not exists. Load it first
i think it might be javascript goes wrong, so i change another version of the echarts.js, but the error still exist, and anyone help me ?
btw, this is my second post on stackoverflow, still learning how to use this platform, so if anywhere that you think i can describe the problem better, pls tell me, thanks.
here is my javascript cdn
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.1.0-release/echarts.js"></script>
and here is my main code
<div id="main" style="width: 1280px;height:800px;"></div>
<script>
// init
var myChart = echarts.init(document.getElementById('main'));
// if the website is still loading, show the animation
// myChart.showLoading();
var data = data_format(jdata);
var option = {
title : {
text : 'test', // this field will connect to the book name
},
tooltip : {},
toolbox : {
show : true,
feature : {
saveAsImage : {
title : 'save as image',
show : true,
type : 'png'
}
}
},
legend : {},
series : [
{
type : 'force',
name : 'test',
ribbonType : false,
categories : [
{
name : 'person'
}
],
itemStyle : {
normal : {
label : {
show : true,
textStyle : {
color : 'black'
}
},
nodeStyle : {
}
}
},
minRadius : 15,
maxRadius : 25,
gravity : 1,
scaling : 1,
linkSymbol : 'arrow',
steps : 10,
coolDown : 1,
nodes : data.nodes,
links : data.links
}
]
}
// setup all option
myChart.setOption(option);
</script>
According to the docs (click on the series node on the left menu to open it and see all types) series has no force type
Valid types are: e.g. bar, graph, etc.
Maybe this example will help you. It uses a series of type graph which has a force object.
e.g. from the example:
series : [
{
type: 'graph',
layout: 'force',
force: {
repulsion: 100
}
...

Re-bind calendar to get new data

I am using the "events" elements of fullcalendar to get data dynamically. This works fine and I'm happy with it, however, I need to be able to pass a GET / POST parameter to the PHP page, and I'm unsure how to refresh the call to include the changed variable... My code is like this:
function redrawMe() {
var resource_array = get_resources();
$("#calendar").fullCalendar({
"cache" : true,
"editable" : true,
"events" : {
"url" : "/ajax/get_calendar_entries.php",
"data" : function() {
return { "resources" : resource_array }
}
}
});
}
function get_resources() {
let view_id = $("#view_id").val();
let promise = $.ajax({
"url" : "/ajax/get_resources.php",
"data" : { "view_id" : view_id },
"dataType" : "json"
});
promise.done(function(data) {
return data;
});
}
Tl;Dr:
I have a dropdown ("view_id") that just needs to fire redrawMe() and redraw the calendar dynamically.
Currently, I can see in the network tab of the developer tools, that the "events" url isn't being fired, and I think its probably because the #calendar div is "already" a calendar?
Make sense?
As recommended by #ADyson - I pass the view_id in the ajax call and use that, rather than multiple calls.
function redrawMe() {
$("#calendar").fullCalendar({
"cache" : true,
"editable" : true,
"eventClick" : function(calEvent, jsEvent, view) {
showJob(calEvent.job_id);
},
"data" : function() {
return {
"view_id" : $("#view_id").val(),
});
});
}
The above works fine
When I want to force a refresh I use this:
$("#calendar").fullCalendar("refetchEvents");

cellEditableCondition always returning false

I'm trying to get a grid on a website to allow the user the ability to edit cell values for only certain properties. I'm sorry if this is basic level, but I'm new to this type of advanced website design.
I've been looking around and found two previous questions that I tried to draw my functionality from:
How to find if an array contains a specific string in JavaScript/jQuery?
nggrid how can I disable/enable individual column
Combining these, I created the following code so that any row that has "Value" equal to anything in my noneditable list will not be open for the user to change:
noneditable = [ "hamburger", "fries" ]
$scope.gridOptions = {
data : 'gridData',
enableRowSelection : false,
enableCellEditOnFocus : true,
showFooter : true,
columnDefs : [ {
field : 'name',
displayName : 'Parameter',
enableCellEdit : false
}, {
field : 'value',
displayName : 'Value',
/**enableCellEdit : true**/
cellEditableCondition : '$.inArray(row.getProperty(\'value\'), noneditable) == -1'
} ]
};
I'm running this, and its compiling, but all cells in column "Value" are noneditable, even the ones contained in the list (tried both > -1 and == -1 to see if I had just gotten the logic wrong, but both produce the same results). Any thoughts? And thank you in advance.
UPDATE (3/27/15):
I was unable to find the solution to this problem, instead I worked around it by just adding another property on the list of values to be displayed. My operational code is:
$scope.gridOptions = {
data : 'gridData',
enableRowSelection : false,
enableCellEditOnFocus : true,
showFooter : true,
columnDefs : [ {
field : 'name',
displayName : 'Parameter',
enableCellEdit : false
}, {
field : 'value',
displayName : 'Value',
cellEditableCondition : 'row.getProperty(\'editable\')'
}]
};
I'm just posting this code in case it helps someone else out.

Categories

Resources