I have to work on a jstree so that it saves what nodes are checked, but also opens checked nodes and their parents on load. This is the code i have to work with:
initializeGeoLevelTree: function () {
var GeoLevelTree = $('#geoLevelTree');
GeoLevelTree.jstree({
"core": {
"multiple": false,
"themes": {
"responsive": false
},
"check_callback": true,
"data":
CreateAdministrator.TreeGeoLevelArray
},
"types": {
"default": {
"icon": "fa fa-folder icon-warning icon-lg"
},
"file": {
"icon": "fa fa-file icon-warning icon-lg"
},
"disabled": {
"check_node": false,
"uncheck_node": false
}
},
"state": { "key": "createAdministrator" },
"checkbox": {
"three_state": false,
"whole_node": false,
"tie_selection": false
},
"plugins": ["checkbox", "wholerow", "types", "themes", "state"]
});
GeoLevelTree.bind("loaded.jstree", function (e, data) {
GeoLevelTree.bind("select_node.jstree", function (e, data) {
$("#lblName").text(data.node.original.Name);
$("#lblType").text(data.node.original.GeoLevelType);
if (data.node.original.IdGeoLevelType == 4) {
$("#officeDetail").show();
$("#lblAddress").text("");
CreateAdministrator.getOfficelDetail(data.node.id);
} else {
$("#officeDetail").hide();
}
});
CreateAdministrator.SelectGeoLevelAdministratorSavedNode();
});
CreateAdministrator.hideLoadingPage();
},
SelectGeoLevelAdministratorSavedNode: function () {
for (var i = 0, l = CreateAdministrator.GeoLevelAdministratorSavedArray.length; i < l; i++) {
var option = CreateAdministrator.GeoLevelAdministratorSavedArray[i];
$.jstree.reference("#geoLevelTree").check_node(option.IdGeoLevel);
jQuery.jstree._reference("#geoLevelTree")._open_to(option.IdGeoLevel);
}
},
The checked nodes adre stored on an external array, which is processed to find which ones are checked. Is there a way to set those nodes to opened as well? using the open_node or the _open_to methods doesn't seem to work. Thanks in advance
_open_to seems to do the trick. Here is a demo:
http://jsfiddle.net/DGAF4/1267/
Maybe the problem is the format of the IDs you pass to both functions - notice the ID is a string and has no # prefix.
Best regards,
Ivan
Related
In the image i have the block. When a username/tag is selected it should remove the fields but it just doesn't. When the else code block runs the fields exist, but it still doesnt remove anything it just stays there.
everything works except the field remover.
Thanks, for your support!
block data:
const blockData = {
"message0": "%1 %2 %3",
"args0": [
{
"type": "input_dummy"
},
{
"type": "field_dropdown",
"name": "MODE",
"options": [
["username", "USERNAME"],
["tag", "TAG"],
["avatarURL", "AVATARURL"],
["bannerURL", "BANNERURL"],
["createDM", "CREATEDM"],
["deleteDM", "DELETEDM"]
]
},
{
"type": "input_dummy",
"name": "test",
},
],
"previousStatement": null,
"nextStatement": null,
"colour": "#40BF4A",
"tooltip": "Set the timestamp of an embed.",
"helpUrl": "",
};
const stringArr = [ "AVATARURL", "DELETEDM", "CREATEDM", "BANNERURL"]
function removeInputs(exclude, block) {
for(let str of stringArr) {
if(str != exclude) if(block.getField(str)) block.removeInput(str)
}
}
Blockly.Blocks[blockName] = {
init: function() {
this.jsonInit(blockData);
},
onchange: function(ev) {
let field = ev.newValue
if(stringArr.includes(field)) {
switch(field) {
case "AVATARURL":
if(!this.getField("AVATARURL")) this.appendValueInput("AVATARURL").setCheck("Boolean").setAlign(Blockly.ALIGN_RIGHT);
removeInputs("AVATARURL", this)
break;
case "CREATEDM":
if(!this.getField("CREATEDM")) this.appendValueInput("CREATEDM").setCheck("Boolean").setAlign(Blockly.ALIGN_RIGHT);
removeInputs("CREATEDM", this)
break;
case "DELETEDM":
if(!this.getField("DELETEDM")) this.appendValueInput("DELETEDM").setCheck("Boolean").setAlign(Blockly.ALIGN_RIGHT);
removeInputs("DELETEDM", this)
break;
case "BANNERURL":
if(!this.getField("BANNERURL")) this.appendValueInput("BANNERURL").setCheck("Boolean").setAlign(Blockly.ALIGN_RIGHT);
removeInputs("BANNERURL", this)
break;
}
}
else {
if(this.getField("BANNERURL")) this.removeInput("BANNERURL")
if(this.getField("DELETEDM")) this.removeInput("DELETEDM")
if(this.getField("CREATEDM")) this.removeInput("CREATEDM")
if(this.getField("AVATARURL")) this.removeInput("AVATARURL")
}
}
};
Block image
I am using the jstree to build up tasks on a calender. I have set the div on which the tree is initialised to a min height of 50px, which means when I am dragging the first node onto an empty tree I can drop it anywhere within that 50px which is great.
However if I then want to drop another node (onto main tree branch) I now much drop it almost on top of the previous node, which means the user needs to be very exact about where they are dropping
Here is the div container

here is the code where the JSTree is attached:
dayTree = moment.format('DD-MM-YYYY');
$('#' + dayTree).jstree({
"core": {
"id": moment.format('DD-MM-YYYY'),
"animation": 150,
'check_callback': function (operation, node, node_parent, node_position, more) {
return true; //allow all other operations
},
"themes": {"stripes": false},
"data": {
async: false,
"url": APIURL+"/shiftassignments?asg_date=" + moment.format('YYYY-MM-DD'),
"dataType": "json",
"success": function (data) {
}
}
},
"rules": {
droppable: ["tree-drop"],
multiple: true,
deletable: "all",
draggable: "all"
},
"contextmenu": {
'items' : getContextMenu
},
"types": {
"#": {
"valid_children": ["SH_LS", "SH_AS", "TO_LS", "TO_AS"]
},
"SH_AS": {
"valid_children": ["ST_LS", "ST_AS"]
},
"TO_AS" : {
"valid_children" : ["ST_LS", "ST_AS"]
},
"TO_LS" : {
"valid_children" : [""]
},
"SH_LS": {
"valid_children": [""]
},
"ST_LS": {
"valid_children": [""]
},
"ST_AS": {
"valid_children": [""]
}
},
"dnd": {
open_timeout: 100,
always_copy: true,
large_drop_target: true
},
"plugins": ["contextmenu", "dnd", "types"]
})
attached is a screenshot to explain!
I guess effectively I would like to increase the drop-zone and have a 'snap-to' effect to the main '#' node. Maybe its not possible?
Screenshot
I would listen to events on the div container for the second tree and if a dragged item is then dropped on that container and second tree has only the root, then just add it there.
The code could look something like below. See demo - Fiddle.
var overSecondTree = false;
$(document).on('dnd_move.vakata', function(e, data) {
// change icon to `allow drop` if from first tree and over second tree with a single root node
if ( $('#tree2 li').length === 1 && overSecondTree ) {
// change icon to `allow drop`
$('#vakata-dnd').find('i').removeClass('jstree-er').addClass('jstree-ok');
} else {
// change icon to `restrict drop`
$('#vakata-dnd').find('i').removeClass('jstree-ok').addClass('jstree-er');
}
});
$(document).on('dnd_stop.vakata', function(e, data) {
// allow drop to tree2 only if single root node
if ( $('#tree2 li').length === 1 && overSecondTree) {
$("#tree2").jstree().create_node('#rootTree2', data.element.text);
}
})
$("#tree2").mouseenter(function(event){
overSecondTree = true;
if ( $('#tree2 li').length === 1 ) {
$('#rootTree2').addClass('highlighted');
}
})
$("#tree2").mouseleave(function(event){
overSecondTree = false;
$('#rootTree2').removeClass('highlighted');
})
Hi I am currently having an issue with the jsTree Context menu.
I would like to grab the id of the selected node however I've looked at a number of solutions and none have worked. My code is below.
The function I have which uses tree.get_selected($node) does return an object of the selected node but I'm struggling to access the id parameter of the object. Below I used tree.get_selected($node).id but it says it's undefined but its clearly not when I look at the console.
Can anyone help as to where I'm going wrong?
$("#tree_1").jstree({
"core" : {
"themes" : {
"responsive": false
},
// so that create works
"check_callback" : true,
'data' : {
'url' : function (node) {
if(node.id=='#') {
var id = 0;
} else {
var id = node.id;
}
return 'organisation/getOrganisationLocations/'+id;
}
}
},
"types" : {
"default" : {
"icon" : "fa fa-folder icon-state-warning icon-lg"
},
"file" : {
"icon" : "fa fa-file icon-state-warning icon-lg"
}
},
"state" : { "key" : "demo3" },
"plugins" : [ "dnd", "state", "types", "contextmenu" ],
"contextmenu":{
"items": function($node) {
var tree = $("#tree_1").jstree(true);
return {
"Create": {
"separator_before": false,
"separator_after": false,
"label": "Create",
"action": function (obj) {
$node = tree.create_node($node);
tree.edit($node);
console.log(tree.get_selected($node).id);
}
},
"Rename": {
"separator_before": false,
"separator_after": false,
"label": "Rename",
"action": function (obj) {
tree.edit($node);
}
},
"Remove": {
"separator_before": false,
"separator_after": false,
"label": "Remove",
"action": function (obj) {
tree.delete_node($node);
}
}
};
}
}
});
This approach worked for me:
$(node).attr('id')
Declare your id above the jstree declaration (at line 1, put var id;)
Then, in the data.url function, remove var from before each line that assignes to id.
My jstree function is here.
I have set 'select_limit' : 3, but is not working. when I run, I am able to select more than 3 nodes, but I need to select no more than 3 nodes.
var j1 = jQuery.noConflict();
j1("#utree_activity").jstree({
"plugins": ["themes", "html_data", "ui", "crrm", "checkbox"],
"html_data": {
"ajax": {
"url": urlGlobal + "jstrees/activitytree/",
"asynchronous": "false",
"data": function (n) {
return {
id: n.attr ? n.attr("id") : 0,
default_activities: default_activities
};
},
"success": function (gb) {
},
}
},
"ui": {
"select_limit": 3,
},
"cookies": {
cookie_options: {
path: "/"
}
},
"checkbox": {
two_state: true,
real_checkboxes: false
}
});
select_limit doens't handle checkbox you must roll your own before.jstree method.
j1.bind("before.jstree", function (e, data) {
if (data.func === "check_node") {
if (j1.jstree('get_checked').length >= 1) {
e.preventDefault();
return false;
}
}
});
Note that this code if for example only, and doesn't handle child nodes
Working fiddle: http://jsfiddle.net/cfb9J/1/
There is another option missing, probably need to add the ui module, try this:
j1("#utree_activity").jstree({
"plugins" : ["html_data","ui"],
//the rest of your code
});
I have been searching the interent for an age and couldnt find an answer. I was trying to change node text colour dependant on the type of the particular node. So in this example i wanted to change the text colour of every node that is a "Role" type defined in data.
$("#roleTree").jstree({
json_data: {
data: roleTreeData
},
"themes": {
"theme": "default",
"dots": true,
"icons": false
},
"ui": {
"select_limit": 1,
"select_multiple_modifier": "none"
},
"types": {
"types": {
"AM": {
"hover_node": false,
"select_node": false
},
"AF": {
"hover_node": false,
"select_node": false
},
"Role": {
// i dont know if possible to be done here? add class?
// this.css("color", "red")
//{ font-weight:bold}
}
}
},
plugins: ["themes", "json_data", "ui", "Select", "types", "crrm"]
}).bind("loaded.jstree", function (event, data)
{
$("#roleTree").jstree("open_all");
data.inst.select_node('ul > li:first');
}).bind("select_node.jstree", function (event, data)
{
selectedRoleId = data.rslt.obj.attr("id");
window.selectedRole = GetRole(selectedRoleId);
});
}
Or any other method to highlight or tell users that only the role is selectable.
This can be done using the following CSS, assuming you are using the default classic theme.
.jstree-classic li[rel="Role"] > a { color:red; }
Get jstree-classic class, where child li has rel attribute of Role, get the first child a of that li and assign color to red.