Is there any way to order the items in the context menu (context.menu.items)? (also items a submenu (contextmenu.items.submenu) - if this if diffrent from the context menu).
The menu items is not rendererd in the order I have them in my code.
I can not find anything about that in the documentation: https://www.jstree.com/api/#/?q=contextmenu&f=$.jstree.defaults.contextmenu.items
I've found out this to be kind of overlooked in jstree. The short answer is there seems to be no nice and reliable way to achieve this. Your options are:
to control the order in which you declare the context menu items and hope that browser that you target will agree with you.
Yes, I've read that you tried this but please check again precisely what you see in the console, not in Chrome dev tools context menu. I've found out that the ordering we see in dev tools is different than the actual one. If in doubt, debug and pause on the context menu object final state and then try to iterate on its properties using for...in
loop. That's what happens behind the scenes in jstree too (see below).
It matters a lot also if your configuration starts with a completely fresh object or you reuse and override what you get from $.jstree.defaults.contextmenu.items()
. To be in complete control of the properties definition order, make sure you start with a plain object literal and copy what you need from $.jstree.defaults.contextmenu.items()
in it in the order you want it to appear. Here is a suggestion that renders a custom menu item "Open" on top:
"contextmenu": { "items" : function(node) { var _ctxmenu = $.jstree.defaults.contextmenu.items(); var ctxmenu = { "open": { "label": "Open" "action" function(){....}, "separator_after" : true, }, "rename": _ctxmenu.rename, "remove": _ctxmenu.remove, }; return ctxmenu; } }If we used directly the context menu obtained from
$.jstree.defaults.contextmenu.items()
and added the "open" object to it, it would render somewhere below "remove" and "rename" because they have already been defined. $(document).on("context_parse.vakata", function(evt, data){ //process the data.element.children('li') array })In the event handler you write your own reordering logic, considering the grouping and separator elements.
Like I said, no simple solution here such as a simple ordering/weight property.
A few details on the implementation that explain why we are here in case you are interested.
The whole context menu generation magic happens in the $.vakata.context._parse
method. It will take as argument the context menu object you've constructed and will iterate on its properties using $.each
, and that's the ordering on which jstree relies currently. Now this one ($.each
) internally uses the for..in loop. What MDN has to say about this loop is that it will iterate on enumerable properties in arbitrary order. So if it happens that browsers do this in order of declaration, that's a happy coincidence not mandated by the specification. There goes the reliability... But if you can live with this, it could be also the easier to achieve here.
A common solution in such situations is to add some ordering/weight property, and consider it while constructing the context menu, but I don't see this implemented as of version 3.3.4. A third option would be to patch your jstree instance and include and maintain this yourself if that's a viable solution for you.