Introduction
jsTree Context Menu plugin will make you right-click the node and show a list of configurable actions in a menu. This article demonstrates how to create a custom menu using jsTree.
What is jsTree?
If you haven’t read the introductory post on jsTree, I would recommend reading the article
jsTree
Include Font Awesome for Icons
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
ContextMenu in jsTree
Add ContextMenu feature in jsTree is a small change. If you read the above jsTree article you can see there will multiple plugins to enable different features.
Below is the line to add the Context Menu feature
"plugins": ["contextmenu"]
Once we add a plugin, you will get the below default menu:
Please note that we have to add “check_callback” as true to work menu functionality.
But here, we are going to override the default menu and we will customize the menu for our requirement.
Here, I have taken the example of setting a field to ascending or descending using the jstree contextmenu plugin.
- <div id="divJsTreeExample"></div>
-
- <script>
- $(document).ready(function () {
- fnLoadJsTreeInstance()
-
- })
- function fnLoadJsTreeInstance() {
- var treeDataSource = [
- { id: 'fields', parent: '#', text: 'Fields', type: 'folder' },
- { id: '1', parent: 'fields', text: 'Field1', type: 'file', field: 'Field1', 'dir': '' },
- { id: '2', parent: 'fields', text: 'Field2', type: 'file', field: 'Field2','dir': '' },
- { id: '3', parent: 'fields', text: 'Field3', type: 'file', field: 'Field3', 'dir': '' },
- ]
-
- $('#divJsTreeExample').jstree({
- "core": {
- "data": treeDataSource
- },
- "types": {
- "folder": {
- "icon": "fa fa-folder"
- },
- "file": {
- "icon": "fa fa-file"
- }
- },
- "contextmenu": {
- items: function ($node) {
- return {
- "asc": {
- "label": "<span class='asc'>Ascending <i class='fa fa-check dir-selected'></i></span>",
- "icon": "fa fa-sort-amount-asc",
- "action": function (obj) {
- fnChangeSortFieldsDirection('asc')
- },
- "_class": "asc"
- },
- "desc": {
- "label": "<span class='desc'>Descending <i class='fa fa-check dir-selected'></i></span>",
- "icon": "fa fa-sort-amount-desc",
- "action": function (obj) {
- fnChangeSortFieldsDirection('desc')
- },
- "_class": "desc"
- }
- }
- },
- },
- "plugins": ["types", "contextmenu"]
- }).bind('ready.jstree', function (e, data) {
- $('#divJsTreeExample').jstree('open_all')
- }).bind("show_contextmenu.jstree", function (e, data) {
- if (data.node.parent == "#") {
- $.vakata.context.hide()
- } else {
- var currentDirection = data.node.original.dir
- if (currentDirection) {
- var hideCheck = currentDirection == "asc" ? "desc" : "asc"
- $('.jstree-contextmenu li.' + hideCheck + ' i.dir-selected').hide()
- } else {
- $('.jstree-contextmenu li i.dir-selected').hide()
- }
- }
- })
- }
-
- function fnChangeSortFieldsDirection(selectedDirection) {
- var nodeObj = $('#divJsTreeExample').jstree('get_selected', true)
- var treeSource = $('#divJsTreeExample').jstree(true).settings.core.data
- if (!nodeObj[0].original.dir || (nodeObj[0].original.dir != selectedDirection)) {
- $.each(treeSource, function (i, treeNode) {
- if (treeNode.id == nodeObj[0].id) {
- treeNode.dir = selectedDirection
- treeNode.text = treeNode.field + "(" + selectedDirection + ")"
- }
- })
- $('#divJsTreeExample').jstree(true).settings.core.data = treeSource
- $('#divJsTreeExample').jstree(true).refresh()
- }
- }
-
- </script>
Code Explanation
In the above code, I have used the JSON datasource to load the tree. You can see that contextmenu will be added in the plugins array under jstree instance configuration. To add Custom Menu, we have to add the menu under items as you can see in the code.
We have used asc and desc for the menu items.
Properties used in the Menu Item:
- label --> The given string or HTML will be displayed when we right-click the node
- icon --> Icon to display before the text.
- action --> Event will be triggered when the menu item is clicked.
- _class --> any custom class can be added here.
Event for context menu shown:
- .bind("show_contextmenu.jstree", function (e, data) {
-
- })
Because we have both the parent and child here, we have to prevent the context menu to open when we right-click the parent node.
So the line $.vakata.context.hide() will do the prevent functionality.
If the selected node is child, then we will update the direction and refresh the tree.
Event fnChangeSortFieldsDirection will get the currently selected node and update the direction and refresh the tree.
Output
Summary
In this article, we have seen how to create a custom context menu using jstree.