jsTree state plugin reloads page continually - jstree

I'm using jsTree as a navigation menu, and after clicking any of the links the page reloads over and over... I've searched all day for an answer to this and would very much appreciate a hand.
$('#NavTreeContainer').jstree({
'core': {
'themes': {
'name': 'default',
'responsive': true,
'stripes': true,
'dots': true,
'icons': false
}
},
'state' : { 'key' : 'navTree' },
'plugins' : [ 'state' ]
}).on('select_node.jstree', function(e, data) {
document.location = data.instance.get_node(data.node, true).children('a').attr('href');
});
$('#ExpandAllNavTreeButton').click(function() {
$('#NavTreeContainer').jstree('open_all');
});
$('#CollapseAllNavTreeButton').click(function() {
$('#NavTreeContainer').jstree('close_all');
});

I was able to get this functionality working by only binding the select node event after the tree state has been restored;
$('#jstree_id').jstree({
"state": { "key": "jstree_id" },
"plugins": ["state"]
}).on('restore_state.jstree', function () {
$('#jstree_id').on('select_node.jstree', function (e, data) {
var href = data.node.a_attr.href;
document.location.href = href;
});
});
If you already solved this I hope it helps someone else.

Related

In jsTree make last child selected after click on in with link open

I can't make my last child node selected after click on it.
Click open this node (href url) but on reloaded page it only select parent node.
Maybe there is also an option to prevent selection of parent node? I don't need it at all.
My tree have only 3 levels and only 3rd/last is used to open links.
jstree config:
$(() => {
$('#jstree').jstree({
core: {
multiple: false,
themes: {
dots: false,
},
data: {
url: '/jsonCats',
dataType: 'json',
},
},
state: {
key: 'navTree',
tree_state: false,
},
types: {
firstfloor: {
icon: false,
selected: false,
},
secfloor: {
icon: false,
},
hidden: {
icon: false,
},
element: {
icon: 'bi bi-file-earmark-text',
},
},
search: {
case_sensitive: false,
show_only_matches: true,
},
plugins: ['search', 'types', 'state', 'changed'],
});
$(document).ready(() => {
$('.search-input').keyup(function () {
const searchString = $(this).val();
$('#jstree').jstree('search', searchString);
});
});
$('#jstree').on('changed.jstree', (e, data) => {
if (data.event === undefined) {
return false;
}
if (data.node.a_attr.href !== '#' && data.event.bubbles) {
location.assign(data.node.a_attr.href);
}
});
});
example json last child:
{
"id": 1001,
"parent": "16",
"text": "Text",
"type": "element",
"li_attr": {
"elem": "element"
},
"a_attr": {
"href": "/KnowledgeBase/1001"
}
localStorage only select parent node:
{"state":{"core":{"open":["1","16"],"scroll":{"left":0,"top":0},"selected":["1"]}},"ttl":false,"sec":1673943166005}

Problems with programmatically selecting node in jsTree on page start-up

I can't select a tree element on page start-up. There is a JSFiddle with the setup: https://jsfiddle.net/voltel/aszn3h46/
My data is JSON array:
const a_data = [
{
"id": "1296",
"text": "Disposable and Single-Use Medical Supplies",
"children": null
},
{
"id": "1275",
"text": "Implantables",
"children": [
{
"id": "1276",
"text": "Defibrillators, Implantable",
"children": null
},
{
"id": "1338",
"text": "Analysers, Laboratory In-Vitro Diagnostic, Clinical Chemistry, Manual",
"children": null
},
]}
];
// Rest of JavaScript code
const $tree = $("#display");
$tree.jstree({
'plugins' : [ "wholerow", "checkbox" ],
'core': {
data : a_data
},
'checkbox': {
three_state: false
},
});
//
// The problem: I can't select/check node with this id
const c_icd_device_type = "1338";
// show initial value
if (c_icd_device_type) {
console.log(`Request to select node with id ${c_icd_device_type}`);
const o_selected_node = $tree.jstree('get_node', c_icd_device_type);
console.log('Selected node: ', o_selected_node);
// Uncomment ONE of the following:
if (o_selected_node) {
$tree.jstree('select_node', o_selected_node, true);
} else {
$tree.jstree(true).select_node(c_icd_device_type);
}//endif
}//endif
Please, help select a node on start-up, and get rid of some suspicious errors in console (see JSFiddle).
Now, I understand from other questions on jsTree here on StackOverflow, that if wrap my code selecting an element in an event handler, it works. I don't quite understand why it is so complicated, provided there are no asynchronous calls. And if it's unavoidable, why not use Promise?
$tree.on('ready.jstree', function (e, data) {
console.log(`Request to select node with id ${c_icd_device_type}`);
const o_selected_node = data.instance.get_node(c_icd_device_type);
//const o_selected_node = $tree.jstree('get_node', c_icd_device_type);
console.log('Selected node: ', o_selected_node);
// Uncomment ONE of the following:
if (o_selected_node) {
$tree.jstree('select_node', o_selected_node, true);
} else {
$tree.jstree(true).select_node(c_icd_device_type);
}//endif
});
I don't see any errors in console on Chrome:
Your code is fine. It just that the tree isn't ready yet. If you wrap your existing code inside ready.jstree event, it'll work.
$tree.on('ready.jstree', function (e, data) {
// Copy line 38 onward and place your existing code here
});

jsTree: with lazy loading the plugin "dnd" is not working

I'm using jsTree (latest version) in my web app. I have a lot of nodes to display in the tree, so I am using lazy loading otherwise I would run into a time out.
When the tree is loaded, the user can pick values from a second tree and move them into the lazy loaded tree (jsTree plugin "dnd"). Both tree have the jsTree plugin "dnd" installed. But I can not drop a element into the lazy loaded tree, when I try to do so the node to be dropped is having an icon with a red cross (indication: not allowed here).
This is the code for the lazy loaded tree:
$('#target_tree').jstree({
'core' : {
'data' : {
"url" : "get_current_hierachy",
"data" : function (node) {
return {'p_parent_id': node.id};
},
"dataType": "json",
"check_callback": true
}
},
"plugins" : ["dnd"]
});
When I load some data in the first tree without the lazy loading, the drag'n'drop is working as expected.
When I load data in the first tree with lazy loading, the drag'n'drop is not working any more.
Any help would be greatly appreciated.
Try this ...
$(document).ready(function () {
$('#target_tree').jstree({
'core': {
'data': {
"url": function (node) {
var url;
if (node.id == '#') {
url = "getRootNode";
} else {
var id = $(node).data("id");
url = "getChildNode?nodeid=" + id;
}
return url;
},
"data": function (node) {
return { "id": node.id };
},
"type": "GET",
"dataType": "json",
"contentType": "application/json charset=utf-8",
},
'check_callback': true,
},
"plugins": ["dnd"]
});
});
I think you need to prepare url

Ext TreePanel: How to add Child Nodes to the expanded node?

I am trying to create a Tree from Ext.tree.Panel with JSON data.
My JSON
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}
I want the first level nodes to be the "firstName: from the above JSON. I am able to achieve this but when any of the node is expanded the same nodes are displayed as children to the expanded node shown below.
- John
---> + John
---> + Anna
---> + Peter
+ Anna
+ Peter
When any of the node is expanded I want to add children from another JSON file. but here the problem is before adding the children to the node i can see the child nodes attached as above.
Is there any way to avoid this behavior ?
Code Snippet
My TreePanel:
Ext.define('MyApp.view.MyTreePanel', {
extend: 'Ext.tree.Panel',
height: 439,
width: 400,
title: 'My Tree Panel',
store: 'MyTreeStore',
displayField: 'firstName',
rootVisible: false,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
viewConfig: {
}
});
me.callParent(arguments);
}
});
TreeStore:
Ext.define('MyApp.store.MyTreeStore', {
extend: 'Ext.data.TreeStore',
requires: [
'MyApp.model.MyModel'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: true,
autoSync: true,
model: 'MyApp.model.MyModel',
storeId: 'MyTreeStore',
proxy: {
type: 'ajax',
url: 'employees.json',
reader: {
type: 'json',
root: 'employees'
}
}
}, cfg)]);
}
});
**Model:**
Ext.define('MyApp.model.MyModel', {
extend: 'Ext.data.Model',
fields: [
{
name: 'firstName'
}
]
});
Thanks in advance....
The url will get called for every node you click on that hasn't been 'loaded' yet. I'm not sure why ExtJS does this as the parameters change per node clicked. What I've done because I needed a lot of extra functionality is override the load() in the tree.Store (sorry, it's a little messy and could use a cleanup):
Ext.define('MyApp.store.MyTreeStore', {
extend: 'Ext.data.TreeStore',
load: function(options) {
options = options || {};
options.params = options.params || {};
var me = this,
node = options.node || me.tree.getRootNode(),
root;
// If there is not a node it means the user hasnt
// defined a rootnode yet. In this case lets just
// create one for them.
if (!node) {
node = me.setRootNode({
expanded: true
});
}
if (me.clearOnLoad) {
node.removeAll();
}
Ext.applyIf(options, {
node: node
});
options.params[me.nodeParam] = node ? node.getId() : 'root';
if (node) {
node.set('loading', true);
}
var root = me.getRootNode();
if (node.isRoot()) {
// put some root option.params here.
// otherwise, don't pass any if you don't need to
} else {
options.params = Ext.JSON.encode({
// or some parameter here for the node to
// get back the correct JSON data
nodeId: node.get('id')
});
}
return me.callParent([options]);
},
model: 'MyApp.model.MyModel',
storeId: 'MyTreeStore',
proxy: {
type: 'ajax',
url: 'employees.json',
reader: {
type: 'json',
root: 'employees'
}
},
autoLoad: false,
listeners: {
append: function(store,node,index) {
// on append depth 1 is first level, beforeappend it is 0
if (node.get('depth') == 1) {
// setting these values here assures that the node knows it's been loaded already.
// node.set('leaf',true); force leaf true, false or whatever you want.
node.set('loaded',true);
node.commit();
}
}
}
});
Also, you can do something like this to your JSON if you need to have the expand / collapse icons there. These are default fields that get added by default.
{
"employees": [
{ "firstName":"John" , "lastName":"Doe", leaf: false, children: []},
{ "firstName":"Anna" , "lastName":"Smith", leaf: false, children: []},
{ "firstName":"Peter" , "lastName":"Jones", leaf: false, children: []}
]
}

Soundmanager 2 events won't fire/trigger

The soundmanager 2 events won't fire. Here is a snippet where the console.logs don't fire at all, therefore any of the different events aren't being triggered when they should.
soundManager.setup({
url: "js/swf/",
preferFlash: false,
useFlashBlock: false,
onready: function() {
soundManager.play(url, id, {
id: id,
url: url,
onplay: function() {
console.log("test");
},
onresume: function() {
console.log("test");
},
onpause: function() {
console.log("test");
},
onfinish: function() {
console.log("test");
next();
},
whileplaying: function() {
console.log("test");
},
});
},
defaultOptions: {
multiShotEvents: true, // allow events (onfinish()) to fire for each shot, if supported.
}
});
Is this because I have flash disabled? There is a bug currently where flash doesan't work in chrome.
Thanks.
You should use the
var sound = soundManager.createSound({id: 'soundId', url: '1.mp3'});
sound.play({
onplay: function() {
...
}
})
you missed "createSound"