summaryrefslogtreecommitdiffstats
path: root/plugins/55/indexmenu/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/55/indexmenu/scripts')
-rw-r--r--plugins/55/indexmenu/scripts/contextmenu.js429
-rw-r--r--plugins/55/indexmenu/scripts/contextmenu.local.js.example70
-rw-r--r--plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.js634
-rw-r--r--plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.min.js4
-rw-r--r--plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.min.js.map1
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/LICENSE.txt21
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.js13856
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.min.js2
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.min.js.map1
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all.js13178
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all.min.js62
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/jquery.fancytree.min.js1
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.ariagrid.js714
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.childcounter.js241
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.clones.js514
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.columnview.js205
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.dnd.js798
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.dnd5.js1157
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.edit.js403
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.filter.js549
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.fixed.js674
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.glyph.js354
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.grid.js1014
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.gridnav.js218
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.js7374
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.logger.js309
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.menu.js185
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.multi.js128
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.persist.js503
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.table.js544
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.themeroller.js125
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.ui-deps.js1449
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.wide.js257
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/readme/icons_layout__from ods.pngbin0 -> 49517 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-awesome/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.css588
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.less134
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-awesome/vline-rtl.gifbin0 -> 842 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-awesome/vline.gifbin0 -> 844 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.css620
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.less185
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/vline-rtl.gifbin0 -> 842 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/vline.gifbin0 -> 844 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/boot.css1065
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.css680
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.less356
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/vline-rtl.gifbin0 -> 842 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/vline.gifbin0 -> 844 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-custom-1/README.md14
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-lion/icons-rtl.gifbin0 -> 5948 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-lion/icons.gifbin0 -> 5937 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-lion/loading.gifbin0 -> 1849 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-lion/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.css757
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.less100
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-lion/vline-rtl.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-lion/vline.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-material/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.css581
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.less131
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-material/vline-rtl.gifbin0 -> 842 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-material/vline.gifbin0 -> 844 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-mdi/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-mdi/ui.fancytree.less131
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-mdi/vline-rtl.gifbin0 -> 842 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-mdi/vline.gifbin0 -> 844 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-themeroller/icons-rtl.gifbin0 -> 5513 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-themeroller/icons.gifbin0 -> 5510 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-themeroller/loading.gifbin0 -> 3234 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.css716
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.less64
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.min.css8
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-themeroller/vline-rtl.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-themeroller/vline.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-typicons/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-typicons/ui.fancytree.less138
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-typicons/vline-rtl.gifbin0 -> 842 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-typicons/vline.gifbin0 -> 844 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-vista/icons-rtl.gifbin0 -> 5513 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-vista/icons.gifbin0 -> 5510 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-vista/loading.gifbin0 -> 3234 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-vista/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.css763
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.less117
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-vista/vline-rtl.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-vista/vline.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win7/icons-rtl.gifbin0 -> 5513 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win7/icons.gifbin0 -> 5510 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win7/loading.gifbin0 -> 3234 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win7/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.css822
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.less157
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win7/vline-rtl.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win7/vline.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-n/icons-rtl.gifbin0 -> 5513 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-n/icons.gifbin0 -> 5510 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-n/loading.gifbin0 -> 3234 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.css767
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.less145
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-n/vline-rtl.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-n/vline.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/icons-rtl.gifbin0 -> 17451 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/icons.gifbin0 -> 17624 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/loading.gifbin0 -> 6243 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.css775
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.less40
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.min.css11
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/vline-rtl.gifbin0 -> 905 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/vline.gifbin0 -> 905 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8/icons-rtl.gifbin0 -> 5513 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8/icons.gifbin0 -> 5510 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8/loading.gifbin0 -> 3234 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.css765
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.less158
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8/vline-rtl.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-win8/vline.gifbin0 -> 852 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/icons-rtl.gifbin0 -> 4002 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/icons-rtl__old__blue laxy expanders.gifbin0 -> 4021 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/icons.gifbin0 -> 4000 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/icons__old__blue lazy expanders.gifbin0 -> 4041 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/loading.gifbin0 -> 570 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/skin-common.less972
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.css779
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.less133
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.min.css6
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/vline-rtl.gifbin0 -> 842 bytes
-rw-r--r--plugins/55/indexmenu/scripts/fancytree/skin-xp/vline.gifbin0 -> 844 bytes
-rw-r--r--plugins/55/indexmenu/scripts/indexmenu.js1008
-rw-r--r--plugins/55/indexmenu/scripts/nojsindex.js27
-rw-r--r--plugins/55/indexmenu/scripts/toolbarindexwizard.js349
143 files changed, 70782 insertions, 0 deletions
diff --git a/plugins/55/indexmenu/scripts/contextmenu.js b/plugins/55/indexmenu/scripts/contextmenu.js
new file mode 100644
index 0000000..051401e
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/contextmenu.js
@@ -0,0 +1,429 @@
+/**
+ * Right Context Menu configuration
+ *
+ * Some usefull variables:
+ * node.hns = headpage id;
+ * node.isdir = node is namespace;
+ * node.dokuid = the DW id (namespace parent in case of headpage);
+ * id = the DW id of the selected node (headpage id in case of headpage);
+ * index.config.urlbase = Url Base;
+ * index.config.sepchar = Url separator;
+ *
+ * HOWTO EDIT:
+ *
+ * To override menu entries or add a menu entry:
+ * - PLEASE EDIT ONLY the scripts/contextmenu.local.js file
+ * - DON'T EDIT this file, it is overwritten at plugin update
+ *
+ * Base structure of the context menu is displayed below.
+ * The entries with 'pg' are shown for page noded, these with 'ns' only for namespaces.
+ *
+ * Current available for everybody:
+ * indexmenu_contextmenu['all']['pg']['view'] = [...array with menu description here... ];
+ * indexmenu_contextmenu['all']['pg']['edit'] = [ ... ];
+ * indexmenu_contextmenu['all']['ns']['view'] = [ ... ];
+ *
+ * Current available for admins:
+ * indexmenu_contextmenu['pg']['view'] = [ ... ];
+ * indexmenu_contextmenu['ns']['view'] = [ ... ];
+ *
+ * Current available for authenticated users:
+ * indexmenu_contextmenu['pg']['view'] = [ ... ];
+ * indexmenu_contextmenu['ns']['view'] = [ ... ];
+ *
+ * A menu description may contain four kind of entries:
+ * - section title: array with one entry e.g.:
+ * ['Section title (html allowed)']
+ * - menu action: array with two entries e.g.:
+ * ['Title of action 1 (html allowed)', 'javascript here ... see for examples scripts/contextmenu.js']
+ * - menu action with custom tooltip: array with three entries e.g.:
+ * ['Title of action 1 (html allowed)', 'javascript here ... see for examples scripts/contextmenu.js', 'Customized title']
+ * - submenu: array with two entries where second entry is an array that describes again a menu e.g.:
+ * ['title of submenu (html allowed)', [ ...array with menu actions... ]]
+ *
+ *
+ * Examples:
+ * A menu description array:
+ * ... = [
+ * ['section title'],
+ * ['title of action 1', 'javascript here'],
+ * ['title of submenu', [['title of subaction 1', 'javascript here'], ['title of subaction 1', 'javascript here', 'Click here for action']] ]
+ * ];
+ *
+ * To Override the common menu title:
+ * indexmenu_contextmenu['all']['pg']['view'][0] = ['customtitle'];
+ *
+ * To override a menu entry, for example the menu title:
+ * indexmenu_contextmenu['all']['pg']['view'][0] = ['Custom Title'];
+ *
+ * To add option to page menu:
+ * Array.splice(index, howManyToRemove, description1)
+ * index = position to start (start counting at zero)
+ * howManyToRemove = number of elements that are removed (set to 1 to replace a element)
+ * description1 = array with menu entry description
+ * -> optional: description2 = optional you can add more elements at once by splice(index, howManyToRemove, description1, description2, etc)
+ *
+ * indexmenu_contextmenu['all']['pg']['view'].splice(1, 0, ['Input new page', '"javascript: IndexmenuContextmenu.reqpage(\'"+index.config.urlbase+"\',\'"+index.config.sepchar+"\',\'"+node.dokuid+"\');"']);
+ */
+
+/* global LANG */
+/* global DOKU_BASE */
+/* global JSINFO */
+
+
+// IMPORTANT: DON'T MODIFY THIS FILE, BUT EDIT contextmenu.local.js PLEASE!
+// THIS FILE IS OVERWRITTEN WHEN PLUGIN IS UPDATED
+
+/**
+ * Right Context Menu configuration for all users:
+ */
+indexmenu_contextmenu['all']['pg'] = {
+ 'view': [
+ ['<span class="indexmenu_titlemenu"><b>'+LANG.plugins.indexmenu.page+'</b></span>'],
+ [LANG.plugins.indexmenu.revs, 'IndexmenuContextmenu.getid(index.config.urlbase,id)+"do=revisions"'],
+ [LANG.plugins.indexmenu.tocpreview, '"javascript: IndexmenuContextmenu.createTocMenu(\'call=indexmenu&req=toc&id="+id+"\',\'picker_"+index.treeName+"\',\'s"+index.treeName+node.id+"\');"']
+ ],
+ //Menu items in edit mode, when previewing
+ 'edit': [
+ ['<span class="indexmenu_titlemenu"><b>'+LANG.plugins.indexmenu.editmode+'</b></span>'],
+ [LANG.plugins.indexmenu.insertdwlink, '"javascript: IndexmenuContextmenu.insertTags(\'"+id+"\',\'"+index.config.sepchar+"\');"+index.treeName+".divdisplay(\'r\',0);"', LANG.plugins.indexmenu.insertdwlinktooltip]
+ ]
+};
+
+indexmenu_contextmenu['all']['ns'] = {
+ 'view': [
+ ['<span class="indexmenu_titlemenu"><b>'+LANG.plugins.indexmenu.ns+'</b></span>'],
+ [LANG.plugins.indexmenu.search, '"javascript: IndexmenuContextmenu.srchpage(\'"+index.config.urlbase+"\',\'"+index.config.sepchar+"\',\'"+node.isdir+"\',\'"+node.dokuid+"\');"', LANG.plugins.indexmenu.searchtooltip]
+ ]
+};
+
+
+if (JSINFO && JSINFO.isadmin) {
+ /**
+ * Right Context Menu configuration for admin users:
+ */
+ indexmenu_contextmenu['pg'] = {
+ 'view': [
+ [LANG.plugins.indexmenu.edit, 'IndexmenuContextmenu.getid(index.config.urlbase,id)+"do=edit"'],
+ ['<em>'+LANG.plugins.indexmenu.create+'--></em>', [
+ [LANG.plugins.indexmenu.headpage, '"javascript: IndexmenuContextmenu.reqpage(\'"+index.config.urlbase+"\',\'"+index.config.sepchar+"\',\'"+node.dokuid+"\',\'"+node.name+"\');"', LANG.plugins.indexmenu.headpagetooltip],
+ [LANG.plugins.indexmenu.startpage, 'IndexmenuContextmenu.getid(index.config.urlbase,id+index.config.sepchar+"start")+"do=edit"', LANG.plugins.indexmenu.startpagetooltip],
+ [LANG.plugins.indexmenu.custompage, '"javascript: IndexmenuContextmenu.reqpage(\'"+index.config.urlbase+"\',\'"+index.config.sepchar+"\',\'"+node.dokuid+"\');"', LANG.plugins.indexmenu.custompagetooltip]
+ ]],
+ ['<em>'+LANG.plugins.indexmenu.more+'--></em>', [
+ [LANG.plugins.indexmenu.acls, 'IndexmenuContextmenu.getid(index.config.urlbase,id)+"do=admin&page=acl"'],
+ [LANG.plugins.indexmenu.purgecache, 'IndexmenuContextmenu.getid(index.config.urlbase,id)+"purge=true"'],
+ [LANG.plugins.indexmenu.exporthtml, 'IndexmenuContextmenu.getid(index.config.urlbase,id)+"do=export_xhtml"'],
+ [LANG.plugins.indexmenu.exporttext, 'IndexmenuContextmenu.getid(index.config.urlbase,id)+"do=export_raw"']
+ ]]
+ ]
+ };
+
+ indexmenu_contextmenu['ns'] = {
+ 'view': [
+ [LANG.plugins.indexmenu.newpage, '"javascript: IndexmenuContextmenu.reqpage(\'"+index.config.urlbase+"\',\'"+index.config.sepchar+"\',\'"+node.dokuid+"\');"', LANG.plugins.indexmenu.newpagetooltip],
+ ['<em>'+LANG.plugins.indexmenu.more+'--></em>', [
+ [LANG.plugins.indexmenu.headpagehere, '"javascript: IndexmenuContextmenu.reqpage(\'"+index.config.urlbase+"\',\'"+index.config.sepchar+"\',\'"+node.dokuid+"\',\'"+node.name+"\');"', LANG.plugins.indexmenu.headpageheretooltip],
+ [LANG.plugins.indexmenu.acls, 'IndexmenuContextmenu.getid(index.config.urlbase,node.dokuid)+"do=admin&page=acl"']
+ ]]
+ ]
+ };
+
+} else if (JSINFO && JSINFO.isauth) {
+ /**
+ * Right Context Menu configuration for authenticated users:
+ */
+ indexmenu_contextmenu['pg'] = {
+ 'view': [
+ [LANG.plugins.indexmenu.newpagehere, '"javascript: IndexmenuContextmenu.reqpage(\'"+index.config.urlbase+"\',\'"+index.config.sepchar+"\',\'"+node.dokuid+"\');"'],
+ ['Edit', 'IndexmenuContextmenu.getid(index.config.urlbase,id)+"do=edit"', 1, 0 ],
+ ['<em>'+LANG.plugins.indexmenu.more+'--></em>', [
+ [LANG.plugins.indexmenu.headpagehere, '"javascript: IndexmenuContextmenu.reqpage(\'"+index.config.urlbase+"\',\'"+index.config.sepchar+"\',\'"+node.dokuid+"\',\'"+node.name+"\');"'],
+ [LANG.plugins.indexmenu.purgecache, 'IndexmenuContextmenu.getid(index.config.urlbase,id)+"purge=true"'],
+ [LANG.plugins.indexmenu.exporthtml, 'IndexmenuContextmenu.getid(index.config.urlbase,id)+"do=export_xhtml"']
+ ]]
+ ]
+ };
+
+}
+
+var IndexmenuContextmenu = {
+
+ /**
+ * Common functions
+ * Insert your custom functions (available for all users) here.
+ */
+
+ /**
+ * Navigate to the search page
+ *
+ * @param {string} urlbase index.config.urlbase
+ * @param {string} sepchar index.config.sepchar
+ * @param {boolean} isdir whether a directory (probably boolean, might be string)
+ * @param {string} nid page id of node (dokuid mentioned in indexmenu.js)
+ */
+
+ srchpage: function (urlbase, sepchar, isdir, nid) {
+ const enteredText = prompt(LANG.plugins.indexmenu.insertkeywords, "");
+ if (enteredText) {
+ let fnid = nid;
+ if (isdir == "0") {
+ fnid = fnid.substring(0, nid.lastIndexOf(sepchar));
+ }
+ let b = urlbase, re = new RegExp(sepchar, 'g');
+ fnid = fnid.replace(re, ":");
+ b += (urlbase.indexOf("?id=") < 0) ? '?id=' : '';
+ window.location.href = IndexmenuContextmenu.getid(b, enteredText + " @" + fnid) + "do=search";
+ }
+ },
+
+ /**
+ * Build a url to a wiki page
+ *
+ * @param {string} urlbase
+ * @param {string} id
+ * @returns {string}
+ */
+ getid: function (urlbase, id) {
+ let url = (urlbase || '') + encodeURIComponent(id || '');
+ url += (urlbase.indexOf("?") < 0) ? '?' : '&';
+ return url;
+ },
+
+ /**
+ * Navigate to the editor window
+ *
+ * @param {string} urlbase
+ * @param {string} sepchar
+ * @param {string} id
+ * @param {string} pagename
+ */
+ reqpage: function (urlbase, sepchar, id, pagename) {
+ let newpageid;
+ if (pagename) {
+ newpageid = id + sepchar + pagename;
+ } else {
+ newpageid = prompt(LANG.plugins.indexmenu.insertpagename, "");
+ if (!newpageid) {
+ return;
+ }
+ newpageid = id + sepchar + newpageid;
+ }
+ if (newpageid) {
+ window.location.href = IndexmenuContextmenu.getid(urlbase, newpageid) + "do=edit";
+ }
+ },
+
+ /**
+ * Insert link syntax with given id in current editor window
+ *
+ * @param {string} lnk page id
+ * @param {string} sepchar
+ */
+ insertTags: function (lnk, sepchar) {
+ let r, l = lnk;
+ if (sepchar) {
+ r = new RegExp(sepchar, "g");
+ l = lnk.replace(r, ':');
+ }
+ insertTags('wiki__text', '[[', ']]', l);
+ },
+
+ /**
+ * Create or catch the picker and hide it, next call the ajax content loading to get the ToC
+ *
+ * @param {string} get query string
+ * @param {string} picker id of picker
+ * @param {string} btn id of button
+ */
+ createTocMenu: function (get, picker, btn) {
+ var $toc_picker = jQuery('#' + picker);
+ if (!$toc_picker.length) {
+ $toc_picker = IndexmenuUtils.createPicker(picker, 'indexmenu_toc');
+ $toc_picker
+ .html('<a href="#"><img src="' + DOKU_BASE + 'lib/plugins/indexmenu/images/close.gif" class="indexmenu_close" /></a><div />')
+ .children().first().click(function (event) {
+ event.stopPropagation();
+ return IndexmenuContextmenu.togglePicker($toc_picker, jQuery('#' + btn));
+ });
+ } else {
+ $toc_picker.hide();
+ }
+ IndexmenuContextmenu.ajaxmenu(get, $toc_picker, jQuery('#' + btn), $toc_picker.children().last(), null);
+ },
+
+ /**
+ * Shows the picker and adds to it or to an internal containter the ajax content
+ *
+ * @param {string} get query string
+ * @param {jQuery} $picker
+ * @param {jQuery} $btn
+ * @param {jQuery} $container if defined ajax result is added to it, otherwise to $picker
+ * @param {function} oncomplete called when defined to handle ajax result
+ */
+ ajaxmenu: function (get, $picker, $btn, $container, oncomplete) {
+ var $indx_list;
+ $indx_list = $container || $picker;
+
+ if (!IndexmenuContextmenu.togglePicker($picker, $btn)) return;
+
+ var onComplete = function (data) {
+ $indx_list.html('');
+ if (typeof oncomplete == 'function') {
+ oncomplete(data, $indx_list);
+ } else {
+ $indx_list.html(data);
+ }
+ };
+
+ //get content for picker/container
+ jQuery.ajax({
+ type: "POST",
+ url: DOKU_BASE + 'lib/exe/ajax.php',
+ data: get,
+ beforeSend: function () {
+ $indx_list.html('<div class="tocheader">'+LANG.plugins.indexmenu.loading+'</div>');
+ },
+ success: onComplete,
+ dataType: 'html'
+ });
+ },
+
+
+ /**
+ * Hide/show picker, will be shown beside btn
+ *
+ * @param {string|jQuery} $picker
+ * @param {jQuery} $btn
+ * @return {Boolean} true if open, false closed
+ */
+ togglePicker: function ($picker, $btn) {
+ var x = 8, y = 0;
+
+ if (!$picker.is(':visible')) {
+ var pos = $btn.offset();
+ //position + width of button
+ x += pos.left + $btn[0].offsetWidth;
+ y += pos.top;
+
+ $picker
+ .show()
+ .offset({
+ left: x,
+ top: y
+ });
+
+ return true;
+ } else {
+ $picker.hide();
+ return false;
+ }
+ },
+
+ /**
+ * Fills the contextmenu by creating entries from the given configuration arrays and concatenating these
+ * to the #r<id> picker
+ *
+ * @param {any[]} amenu (part of) the configuration array
+ * @param {dTree} index the indexmenu object
+ * @param {int} n node id
+ */
+ arrconcat: function (amenu, index, n) {
+ var html, id, item, a, li;
+ if (typeof amenu == 'undefined' || typeof amenu['view'] == 'undefined') {
+ return;
+ }
+ var cmenu = amenu['view'];
+ if (jQuery('#tool__bar')[0] && amenu['edit'] instanceof Array) {
+ cmenu = amenu['edit'].concat(cmenu);
+ }
+ var node = index.aNodes[n];
+ id = node.hns || node.dokuid;
+
+ var createCMenuEntry = function (entry) {
+ return '<a title="' + ((entry[2]) ? entry[2] : entry[0]) + '" href="' + eval(entry[1]) + '">' + entry[0] + '</a>';
+ };
+
+ jQuery.each(cmenu, function (i, cmenuentry) {
+ if (cmenuentry == '') {
+ return true;
+ }
+ item = document.createElement('li');
+ var $cmenu = jQuery('#r' + index.treeName);
+ if (cmenuentry[1]) {
+ if (cmenuentry[1] instanceof Array) {
+ html = document.createElement('ul');
+ jQuery.each(cmenuentry[1], function (a, subcmenuentry) {
+ li = document.createElement('li');
+ li.innerHTML = createCMenuEntry(subcmenuentry);
+ html.appendChild(li);
+ });
+
+ //}
+ item.innerHTML = '<span class="indexmenu_submenu">' + cmenuentry[0] + '</span>';
+ html.left = $cmenu[0].width;
+ item.appendChild(html);
+ } else {
+ item.innerHTML = createCMenuEntry(cmenuentry);
+ }
+ } else {
+ item.innerHTML = cmenuentry;
+ }
+ $cmenu.children().last().append(item);
+ });
+ },
+
+ /**
+ * Absolute positioning of the div at place of mouseclick
+ *
+ * @param obj div element
+ * @param e
+ */
+ mouseposition: function (obj, e) {
+ //http://www.quirksmode.org/js/events_properties.html
+ var X = 0, Y = 0;
+ if (!e) e = window.event;
+ if (e.pageX || e.pageY) {
+ X = e.pageX;
+ Y = e.pageY;
+ }
+ else if (e.clientX || e.clientY) {
+ X = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
+ Y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
+ }
+ obj.style.left = X - 5 + 'px';
+ obj.style.top = Y - 5 + 'px';
+ },
+
+ /**
+ * Check mouse button onmousedown event, only for middle and right mouse button contextmenu is shown
+ *
+ * @param {int} n node id
+ * @param {string|dTree} obj the unique name of a dTree object
+ * @param {event} e
+ */
+ checkcontextm: function (n, obj, e) {
+ e = e || event;
+ // mouse clicks: which 3 === right, button 2 === right button
+ if ((e.which === 3 || e.button === 2) || (window.opera && e.which === 1 && e.ctrlKey)) {
+ obj.contextmenu(n, e);
+ IndexmenuContextmenu.stopevt(e);
+ }
+ },
+
+ /**
+ * Prevent default oncontextmenu event
+ *
+ * @param {event} e
+ * @returns {boolean}
+ */
+ stopevt: function (e) {
+ if (!window.indexmenu_contextmenu) {
+ return true;
+ }
+ e = e || event;
+ e.preventDefault ? e.preventDefault() : e.returnValue = false;
+ return false;
+ }
+};
+
diff --git a/plugins/55/indexmenu/scripts/contextmenu.local.js.example b/plugins/55/indexmenu/scripts/contextmenu.local.js.example
new file mode 100644
index 0000000..73ab81b
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/contextmenu.local.js.example
@@ -0,0 +1,70 @@
+/**
+ * Right Context Menu local configuration -- RENAME THIS FILE TO contextmenu.local.js --
+ * How to change:
+ * - Rename this file to contextmenu.local.js
+ * - Make in this file your modifications
+ * - and go to the Configuration Manager and save the config again (this clears the cached javascript)
+ *
+ * See for information about available variables, menu structure, override and adding menu entries in the scripts/contextmenu.js
+ */
+
+/**
+ * Right Context Menu configuration for all users:
+ */
+if (!indexmenu_contextmenu['all']['pg']) indexmenu_contextmenu['all']['pg'] = {'view': [] };
+if (!indexmenu_contextmenu['all']['ns']) indexmenu_contextmenu['all']['ns'] = {'view': [] };
+
+
+// Override title of page menu
+//indexmenu_contextmenu['all']['pg']['view'][0] = ['Custom Title'];
+
+// add option to page menu
+//indexmenu_contextmenu['all']['pg']['view'].splice(1, 0, ['Input new page', '"javascript: IndexmenuContextmenu.reqpage(\'"+index.config.urlbase+"\',\'"+index.config.sepchar+"\',\'"+node.dokuid+"\');"']);
+
+
+if (JSINFO && JSINFO.isadmin) {
+ if (!indexmenu_contextmenu['pg']) indexmenu_contextmenu['pg'] = {'view': []};
+ if (!indexmenu_contextmenu['ns']) indexmenu_contextmenu['ns'] = {'view': []};
+ /**
+ * Right Context Menu configuration for admin users:
+ */
+
+ //override or add here the menu entries for admin, see for examples above
+
+
+} else if (JSINFO && JSINFO.isauth) {
+ if (!indexmenu_contextmenu['pg']) indexmenu_contextmenu['pg'] = {'view': []};
+ if (!indexmenu_contextmenu['ns']) indexmenu_contextmenu['ns'] = {'view': []};
+ /**
+ * Right Context Menu configuration for authenticated users:
+ */
+
+ //override or add here the menu entries for authenticated users, see for examples above
+
+}
+
+/**
+ * Common available functions:
+ *
+ * Some common functions are added by [indexmenu plugin folder]/scripts/contextmenu.js
+ * - IndexmenuContextmenu.srchpage(urlbase, sepchar, isdir, dokuid)
+ * - IndexmenuContextmenu.getid(urlbase, dokuid)
+ * - IndexmenuContextmenu.reqpage(urlbase, sepchar, dokuid, pagename)
+ * - IndexmenuContextmenu.insertTags(dokuid, sepchar)
+ *
+ * Insert your custom functions (available for all users) at the bottom of this file.
+ */
+
+/**
+ * Random Example function do something
+ *
+ * @param {string} id
+ * @param {Boolean} isdir
+ * @return {*} ...
+ */
+/*
+function indexmenu_custom_dosomething(a, isdir) {
+ //do something
+ return false;
+}
+*/
diff --git a/plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.js b/plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.js
new file mode 100644
index 0000000..a8fcf73
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.js
@@ -0,0 +1,634 @@
+/*******************************************************************************
+ * jquery.ui-contextmenu.js plugin.
+ *
+ * jQuery plugin that provides a context menu (based on the jQueryUI menu widget).
+ *
+ * @see https://github.com/mar10/jquery-ui-contextmenu
+ *
+ * Copyright (c) 2013-2018, Martin Wendt (http://wwWendt.de). Licensed MIT.
+ */
+
+(function( factory ) {
+ "use strict";
+ if ( typeof define === "function" && define.amd ) {
+ // AMD. Register as an anonymous module.
+ define([ "jquery", "jquery-ui/ui/widgets/menu" ], factory );
+ } else {
+ // Browser globals
+ factory( jQuery );
+ }
+}(function( $ ) {
+
+"use strict";
+
+var supportSelectstart = "onselectstart" in document.createElement("div"),
+ match = $.ui.menu.version.match(/^(\d)\.(\d+)/),
+ uiVersion = {
+ major: parseInt(match[1], 10),
+ minor: parseInt(match[2], 10)
+ },
+ isLTE110 = ( uiVersion.major < 2 && uiVersion.minor <= 10 ),
+ isLTE111 = ( uiVersion.major < 2 && uiVersion.minor <= 11 );
+
+$.widget("moogle.contextmenu", {
+ version: "@VERSION",
+ options: {
+ addClass: "ui-contextmenu", // Add this class to the outer <ul>
+ closeOnWindowBlur: true, // Close menu when window loses focus
+ appendTo: "body", // Set keyboard focus to first entry on open
+ autoFocus: false, // Set keyboard focus to first entry on open
+ autoTrigger: true, // open menu on browser's `contextmenu` event
+ delegate: null, // selector
+ hide: { effect: "fadeOut", duration: "fast" },
+ ignoreParentSelect: true, // Don't trigger 'select' for sub-menu parents
+ menu: null, // selector or jQuery pointing to <UL>, or a definition hash
+ position: null, // popup positon
+ preventContextMenuForPopup: false, // prevent opening the browser's system
+ // context menu on menu entries
+ preventSelect: false, // disable text selection of target
+ show: { effect: "slideDown", duration: "fast" },
+ taphold: false, // open menu on taphold events (requires external plugins)
+ uiMenuOptions: {}, // Additional options, used when UI Menu is created
+ // Events:
+ beforeOpen: $.noop, // menu about to open; return `false` to prevent opening
+ blur: $.noop, // menu option lost focus
+ close: $.noop, // menu was closed
+ create: $.noop, // menu was initialized
+ createMenu: $.noop, // menu was initialized (original UI Menu)
+ focus: $.noop, // menu option got focus
+ open: $.noop, // menu was opened
+ select: $.noop // menu option was selected; return `false` to prevent closing
+ },
+ /** Constructor */
+ _create: function() {
+ var cssText, eventNames, targetId,
+ opts = this.options;
+
+ this.$headStyle = null;
+ this.$menu = null;
+ this.menuIsTemp = false;
+ this.currentTarget = null;
+ this.extraData = {};
+ this.previousFocus = null;
+
+ if (opts.delegate == null) {
+ $.error("ui-contextmenu: Missing required option `delegate`.");
+ }
+ if (opts.preventSelect) {
+ // Create a global style for all potential menu targets
+ // If the contextmenu was bound to `document`, we apply the
+ // selector relative to the <body> tag instead
+ targetId = ($(this.element).is(document) ? $("body")
+ : this.element).uniqueId().attr("id");
+ cssText = "#" + targetId + " " + opts.delegate + " { " +
+ "-webkit-user-select: none; " +
+ "-khtml-user-select: none; " +
+ "-moz-user-select: none; " +
+ "-ms-user-select: none; " +
+ "user-select: none; " +
+ "}";
+ this.$headStyle = $("<style class='moogle-contextmenu-style' />")
+ .prop("type", "text/css")
+ .appendTo("head");
+
+ try {
+ this.$headStyle.html(cssText);
+ } catch ( e ) {
+ // issue #47: fix for IE 6-8
+ this.$headStyle[0].styleSheet.cssText = cssText;
+ }
+ // TODO: the selectstart is not supported by FF?
+ if (supportSelectstart) {
+ this.element.on("selectstart" + this.eventNamespace, opts.delegate,
+ function(event) {
+ event.preventDefault();
+ });
+ }
+ }
+ this._createUiMenu(opts.menu);
+
+ eventNames = "contextmenu" + this.eventNamespace;
+ if (opts.taphold) {
+ eventNames += " taphold" + this.eventNamespace;
+ }
+ this.element.on(eventNames, opts.delegate, $.proxy(this._openMenu, this));
+ },
+ /** Destructor, called on $().contextmenu("destroy"). */
+ _destroy: function() {
+ this.element.off(this.eventNamespace);
+
+ this._createUiMenu(null);
+
+ if (this.$headStyle) {
+ this.$headStyle.remove();
+ this.$headStyle = null;
+ }
+ },
+ /** (Re)Create jQuery UI Menu. */
+ _createUiMenu: function(menuDef) {
+ var ct, ed,
+ opts = this.options;
+
+ // Remove temporary <ul> if any
+ if (this.isOpen()) {
+ // #58: 'replaceMenu' in beforeOpen causing select: to lose ui.target
+ ct = this.currentTarget;
+ ed = this.extraData;
+ // close without animation, to force async mode
+ this._closeMenu(true);
+ this.currentTarget = ct;
+ this.extraData = ed;
+ }
+ if (this.menuIsTemp) {
+ this.$menu.remove(); // this will also destroy ui.menu
+ } else if (this.$menu) {
+ this.$menu
+ .menu("destroy")
+ .removeClass(opts.addClass)
+ .hide();
+ }
+ this.$menu = null;
+ this.menuIsTemp = false;
+ // If a menu definition array was passed, create a hidden <ul>
+ // and generate the structure now
+ if ( !menuDef ) {
+ return;
+ } else if ($.isArray(menuDef)) {
+ this.$menu = $.moogle.contextmenu.createMenuMarkup(menuDef, null, opts);
+ this.menuIsTemp = true;
+ }else if ( typeof menuDef === "string" ) {
+ this.$menu = $(menuDef);
+ } else {
+ this.$menu = menuDef;
+ }
+ // Create - but hide - the jQuery UI Menu widget
+ this.$menu
+ .hide()
+ .addClass(opts.addClass)
+ // Create a menu instance that delegates events to our widget
+ .menu($.extend(true, {}, opts.uiMenuOptions, {
+ items: "> :not(.ui-widget-header)",
+ blur: $.proxy(opts.blur, this),
+ create: $.proxy(opts.createMenu, this),
+ focus: $.proxy(opts.focus, this),
+ select: $.proxy(function(event, ui) {
+ // User selected a menu entry
+ var retval,
+ isParent = $.moogle.contextmenu.isMenu(ui.item),
+ actionHandler = ui.item.data("actionHandler");
+
+ ui.cmd = ui.item.attr("data-command");
+ ui.target = $(this.currentTarget);
+ ui.extraData = this.extraData;
+ // ignore clicks, if they only open a sub-menu
+ if ( !isParent || !opts.ignoreParentSelect) {
+ retval = this._trigger.call(this, "select", event, ui);
+ if ( actionHandler ) {
+ retval = actionHandler.call(this, event, ui);
+ }
+ if ( retval !== false ) {
+ this._closeMenu.call(this);
+ }
+ event.preventDefault();
+ }
+ }, this)
+ }));
+ },
+ /** Open popup (called on 'contextmenu' event). */
+ _openMenu: function(event, recursive) {
+ var res, promise, ui,
+ opts = this.options,
+ posOption = opts.position,
+ self = this,
+ manualTrigger = !!event.isTrigger;
+
+ if ( !opts.autoTrigger && !manualTrigger ) {
+ // ignore browser's `contextmenu` events
+ return;
+ }
+ // Prevent browser from opening the system context menu
+ event.preventDefault();
+
+ this.currentTarget = event.target;
+ this.extraData = event._extraData || {};
+
+ ui = { menu: this.$menu, target: $(this.currentTarget), extraData: this.extraData,
+ originalEvent: event, result: null };
+
+ if ( !recursive ) {
+ res = this._trigger("beforeOpen", event, ui);
+ promise = (ui.result && $.isFunction(ui.result.promise)) ? ui.result : null;
+ ui.result = null;
+ if ( res === false ) {
+ this.currentTarget = null;
+ return false;
+ } else if ( promise ) {
+ // Handler returned a Deferred or Promise. Delay menu open until
+ // the promise is resolved
+ promise.done(function() {
+ self._openMenu(event, true);
+ });
+ this.currentTarget = null;
+ return false;
+ }
+ ui.menu = this.$menu; // Might have changed in beforeOpen
+ }
+
+ // Register global event handlers that close the dropdown-menu
+ $(document).on("keydown" + this.eventNamespace, function(event) {
+ if ( event.which === $.ui.keyCode.ESCAPE ) {
+ self._closeMenu();
+ }
+ }).on("mousedown" + this.eventNamespace + " touchstart" + this.eventNamespace,
+ function(event) {
+ // Close menu when clicked outside menu
+ if ( !$(event.target).closest(".ui-menu-item").length ) {
+ self._closeMenu();
+ }
+ });
+ $(window).on("blur" + this.eventNamespace, function(event) {
+ if ( opts.closeOnWindowBlur ) {
+ self._closeMenu();
+ }
+ });
+
+ // required for custom positioning (issue #18 and #13).
+ if ($.isFunction(posOption)) {
+ posOption = posOption(event, ui);
+ }
+ posOption = $.extend({
+ my: "left top",
+ at: "left bottom",
+ // if called by 'open' method, event does not have pageX/Y
+ of: (event.pageX === undefined) ? event.target : event,
+ collision: "fit"
+ }, posOption);
+
+ // Update entry statuses from callbacks
+ this._updateEntries(this.$menu);
+
+ // Finally display the popup
+ this.$menu
+ .show() // required to fix positioning error
+ .css({
+ position: "absolute",
+ left: 0,
+ top: 0
+ }).position(posOption)
+ .hide(); // hide again, so we can apply nice effects
+
+ if ( opts.preventContextMenuForPopup ) {
+ this.$menu.on("contextmenu" + this.eventNamespace, function(event) {
+ event.preventDefault();
+ });
+ }
+ this._show(this.$menu, opts.show, function() {
+ var $first;
+
+ // Set focus to first active menu entry
+ if ( opts.autoFocus ) {
+ self.previousFocus = $(event.target);
+ // self.$menu.focus();
+ $first = self.$menu
+ .children("li.ui-menu-item")
+ .not(".ui-state-disabled")
+ .first();
+ self.$menu.menu("focus", null, $first).focus();
+ }
+ self._trigger.call(self, "open", event, ui);
+ });
+ },
+ /** Close popup. */
+ _closeMenu: function(immediately) {
+ var self = this,
+ hideOpts = immediately ? false : this.options.hide,
+ ui = { menu: this.$menu, target: $(this.currentTarget), extraData: this.extraData };
+
+ // Note: we don't want to unbind the 'contextmenu' event
+ $(document)
+ .off("mousedown" + this.eventNamespace)
+ .off("touchstart" + this.eventNamespace)
+ .off("keydown" + this.eventNamespace);
+ $(window)
+ .off("blur" + this.eventNamespace);
+
+ self.currentTarget = null; // issue #44 after hide animation is too late
+ self.extraData = {};
+ if ( this.$menu ) { // #88: widget might have been destroyed already
+ this.$menu
+ .off("contextmenu" + this.eventNamespace);
+ this._hide(this.$menu, hideOpts, function() {
+ if ( self.previousFocus ) {
+ self.previousFocus.focus();
+ self.previousFocus = null;
+ }
+ self._trigger("close", null, ui);
+ });
+ } else {
+ self._trigger("close", null, ui);
+ }
+ },
+ /** Handle $().contextmenu("option", key, value) calls. */
+ _setOption: function(key, value) {
+ switch (key) {
+ case "menu":
+ this.replaceMenu(value);
+ break;
+ }
+ $.Widget.prototype._setOption.apply(this, arguments);
+ },
+ /** Return ui-menu entry (<LI> tag). */
+ _getMenuEntry: function(cmd) {
+ return this.$menu.find("li[data-command=" + cmd + "]");
+ },
+ /** Close context menu. */
+ close: function() {
+ if (this.isOpen()) {
+ this._closeMenu();
+ }
+ },
+ /* Apply status callbacks when menu is opened. */
+ _updateEntries: function() {
+ var self = this,
+ ui = {
+ menu: this.$menu, target: $(this.currentTarget), extraData: this.extraData };
+
+ $.each(this.$menu.find(".ui-menu-item"), function(i, o) {
+ var $entry = $(o),
+ fn = $entry.data("disabledHandler"),
+ res = fn ? fn({ type: "disabled" }, ui) : null;
+
+ ui.item = $entry;
+ ui.cmd = $entry.attr("data-command");
+ // Evaluate `disabled()` callback
+ if ( res != null ) {
+ self.enableEntry(ui.cmd, !res);
+ self.showEntry(ui.cmd, res !== "hide");
+ }
+ // Evaluate `title()` callback
+ fn = $entry.data("titleHandler"),
+ res = fn ? fn({ type: "title" }, ui) : null;
+ if ( res != null ) {
+ self.setTitle(ui.cmd, "" + res);
+ }
+ // Evaluate `tooltip()` callback
+ fn = $entry.data("tooltipHandler"),
+ res = fn ? fn({ type: "tooltip" }, ui) : null;
+ if ( res != null ) {
+ $entry.attr("title", "" + res);
+ }
+ });
+ },
+ /** Enable or disable the menu command. */
+ enableEntry: function(cmd, flag) {
+ this._getMenuEntry(cmd).toggleClass("ui-state-disabled", (flag === false));
+ },
+ /** Return ui-menu entry (LI tag) as jQuery object. */
+ getEntry: function(cmd) {
+ return this._getMenuEntry(cmd);
+ },
+ /** Return ui-menu entry wrapper as jQuery object.
+ UI 1.10: this is the <a> tag inside the LI
+ UI 1.11: this is the LI istself
+ UI 1.12: this is the <div> tag inside the LI
+ */
+ getEntryWrapper: function(cmd) {
+ return this._getMenuEntry(cmd).find(">[role=menuitem]").addBack("[role=menuitem]");
+ },
+ /** Return Menu element (UL). */
+ getMenu: function() {
+ return this.$menu;
+ },
+ /** Return true if menu is open. */
+ isOpen: function() {
+// return this.$menu && this.$menu.is(":visible");
+ return !!this.$menu && !!this.currentTarget;
+ },
+ /** Open context menu on a specific target (must match options.delegate)
+ * Optional `extraData` is passed to event handlers as `ui.extraData`.
+ */
+ open: function(targetOrEvent, extraData) {
+ // Fake a 'contextmenu' event
+ extraData = extraData || {};
+
+ var isEvent = (targetOrEvent && targetOrEvent.type && targetOrEvent.target),
+ event = isEvent ? targetOrEvent : {},
+ target = isEvent ? targetOrEvent.target : targetOrEvent,
+ e = jQuery.Event("contextmenu", {
+ target: $(target).get(0),
+ pageX: event.pageX,
+ pageY: event.pageY,
+ originalEvent: isEvent ? targetOrEvent : undefined,
+ _extraData: extraData
+ });
+ return this.element.trigger(e);
+ },
+ /** Replace the menu altogether. */
+ replaceMenu: function(data) {
+ this._createUiMenu(data);
+ },
+ /** Redefine a whole menu entry. */
+ setEntry: function(cmd, entry) {
+ var $ul,
+ $entryLi = this._getMenuEntry(cmd);
+
+ if (typeof entry === "string") {
+ window.console && window.console.warn(
+ "setEntry(cmd, t) with a plain string title is deprecated since v1.18." +
+ "Use setTitle(cmd, '" + entry + "') instead.");
+ return this.setTitle(cmd, entry);
+ }
+ $entryLi.empty();
+ entry.cmd = entry.cmd || cmd;
+ $.moogle.contextmenu.createEntryMarkup(entry, $entryLi);
+ if ($.isArray(entry.children)) {
+ $ul = $("<ul/>").appendTo($entryLi);
+ $.moogle.contextmenu.createMenuMarkup(entry.children, $ul);
+ }
+ // #110: jQuery UI 1.12: refresh only works when this class is not set:
+ $entryLi.removeClass("ui-menu-item");
+ this.getMenu().menu("refresh");
+ },
+ /** Set icon (pass null to remove). */
+ setIcon: function(cmd, icon) {
+ return this.updateEntry(cmd, { uiIcon: icon });
+ },
+ /** Set title. */
+ setTitle: function(cmd, title) {
+ return this.updateEntry(cmd, { title: title });
+ },
+ // /** Set tooltip (pass null to remove). */
+ // setTooltip: function(cmd, tooltip) {
+ // this._getMenuEntry(cmd).attr("title", tooltip);
+ // },
+ /** Show or hide the menu command. */
+ showEntry: function(cmd, flag) {
+ this._getMenuEntry(cmd).toggle(flag !== false);
+ },
+ /** Redefine selective attributes of a menu entry. */
+ updateEntry: function(cmd, entry) {
+ var $icon, $wrapper,
+ $entryLi = this._getMenuEntry(cmd);
+
+ if ( entry.title !== undefined ) {
+ $.moogle.contextmenu.updateTitle($entryLi, "" + entry.title);
+ }
+ if ( entry.tooltip !== undefined ) {
+ if ( entry.tooltip === null ) {
+ $entryLi.removeAttr("title");
+ } else {
+ $entryLi.attr("title", entry.tooltip);
+ }
+ }
+ if ( entry.uiIcon !== undefined ) {
+ $wrapper = this.getEntryWrapper(cmd),
+ $icon = $wrapper.find("span.ui-icon").not(".ui-menu-icon");
+ $icon.remove();
+ if ( entry.uiIcon ) {
+ $wrapper.append($("<span class='ui-icon' />").addClass(entry.uiIcon));
+ }
+ }
+ if ( entry.hide !== undefined ) {
+ $entryLi.toggle(!entry.hide);
+ } else if ( entry.show !== undefined ) {
+ // Note: `show` is an undocumented variant. `hide: false` is preferred
+ $entryLi.toggle(!!entry.show);
+ }
+ // if ( entry.isHeader !== undefined ) {
+ // $entryLi.toggleClass("ui-widget-header", !!entry.isHeader);
+ // }
+ if ( entry.data !== undefined ) {
+ $entryLi.data(entry.data);
+ }
+
+ // Set/clear class names, but handle ui-state-disabled separately
+ if ( entry.disabled === undefined ) {
+ entry.disabled = $entryLi.hasClass("ui-state-disabled");
+ }
+ if ( entry.setClass ) {
+ if ( $entryLi.hasClass("ui-menu-item") ) {
+ entry.setClass += " ui-menu-item";
+ }
+ $entryLi.removeClass();
+ $entryLi.addClass(entry.setClass);
+ } else if ( entry.addClass ) {
+ $entryLi.addClass(entry.addClass);
+ }
+ $entryLi.toggleClass("ui-state-disabled", !!entry.disabled);
+ // // #110: jQuery UI 1.12: refresh only works when this class is not set:
+ // $entryLi.removeClass("ui-menu-item");
+ // this.getMenu().menu("refresh");
+ }
+});
+
+/*
+ * Global functions
+ */
+$.extend($.moogle.contextmenu, {
+ /** Convert a menu description into a into a <li> content. */
+ createEntryMarkup: function(entry, $parentLi) {
+ var $wrapper = null;
+
+ $parentLi.attr("data-command", entry.cmd);
+
+ if ( !/[^\-\u2014\u2013\s]/.test( entry.title ) ) {
+ // hyphen, em dash, en dash: separator as defined by UI Menu 1.10
+ $parentLi.text(entry.title);
+ } else {
+ if ( isLTE110 ) {
+ // jQuery UI Menu 1.10 or before required an `<a>` tag
+ $wrapper = $("<a/>", {
+ html: "" + entry.title,
+ href: "#"
+ }).appendTo($parentLi);
+
+ } else if ( isLTE111 ) {
+ // jQuery UI Menu 1.11 preferes to avoid `<a>` tags or <div> wrapper
+ $parentLi.html("" + entry.title);
+ $wrapper = $parentLi;
+
+ } else {
+ // jQuery UI Menu 1.12 introduced `<div>` wrappers
+ $wrapper = $("<div/>", {
+ html: "" + entry.title
+ }).appendTo($parentLi);
+ }
+ if ( entry.uiIcon ) {
+ $wrapper.append($("<span class='ui-icon' />").addClass(entry.uiIcon));
+ }
+ // Store option callbacks in entry's data
+ $.each( [ "action", "disabled", "title", "tooltip" ], function(i, attr) {
+ if ( $.isFunction(entry[attr]) ) {
+ $parentLi.data(attr + "Handler", entry[attr]);
+ }
+ });
+ if ( entry.disabled === true ) {
+ $parentLi.addClass("ui-state-disabled");
+ }
+ if ( entry.isHeader ) {
+ $parentLi.addClass("ui-widget-header");
+ }
+ if ( entry.addClass ) {
+ $parentLi.addClass(entry.addClass);
+ }
+ if ( $.isPlainObject(entry.data) ) {
+ $parentLi.data(entry.data);
+ }
+ if ( typeof entry.tooltip === "string" ) {
+ $parentLi.attr("title", entry.tooltip);
+ }
+ }
+ },
+ /** Convert a nested array of command objects into a <ul> structure. */
+ createMenuMarkup: function(options, $parentUl, opts) {
+ var i, menu, $ul, $li,
+ appendTo = (opts && opts.appendTo) ? opts.appendTo : "body";
+
+ if ( $parentUl == null ) {
+ $parentUl = $("<ul class='ui-helper-hidden' />").appendTo(appendTo);
+ }
+ for (i = 0; i < options.length; i++) {
+ menu = options[i];
+ $li = $("<li/>").appendTo($parentUl);
+
+ $.moogle.contextmenu.createEntryMarkup(menu, $li);
+
+ if ( $.isArray(menu.children) ) {
+ $ul = $("<ul/>").appendTo($li);
+ $.moogle.contextmenu.createMenuMarkup(menu.children, $ul);
+ }
+ }
+ return $parentUl;
+ },
+ /** Returns true if the menu item has child menu items */
+ isMenu: function(item) {
+ if ( isLTE110 ) {
+ return item.has(">a[aria-haspopup='true']").length > 0;
+ } else if ( isLTE111 ) { // jQuery UI 1.11 used no tag wrappers
+ return item.is("[aria-haspopup='true']");
+ } else {
+ return item.has(">div[aria-haspopup='true']").length > 0;
+ }
+ },
+ /** Replace the title of elem', but retain icons andchild entries. */
+ replaceFirstTextNodeChild: function(elem, html) {
+ var $icons = elem.find(">span.ui-icon,>ul.ui-menu").detach();
+
+ elem
+ .empty()
+ .html(html)
+ .append($icons);
+ },
+ /** Updates the menu item's title */
+ updateTitle: function(item, title) {
+ if ( isLTE110 ) { // jQuery UI 1.10 and before used <a> tags
+ $.moogle.contextmenu.replaceFirstTextNodeChild($("a", item), title);
+ } else if ( isLTE111 ) { // jQuery UI 1.11 used no tag wrappers
+ $.moogle.contextmenu.replaceFirstTextNodeChild(item, title);
+ } else { // jQuery UI 1.12+ introduced <div> tag wrappers
+ $.moogle.contextmenu.replaceFirstTextNodeChild($("div", item), title);
+ }
+ }
+});
+
+}));
diff --git a/plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.min.js b/plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.min.js
new file mode 100644
index 0000000..4436aaa
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.min.js
@@ -0,0 +1,4 @@
+/*! jQuery UI context menu plugin - v1.18.2-0 - 2019-01-28 | https://github.com/mar10/jquery-ui-contextmenu | Copyright (c) 2013 -2019 Martin Wendt; Licensed MIT */
+
+!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery","jquery-ui/ui/widgets/menu"],a):a(jQuery)}(function(a){"use strict";var b="onselectstart"in document.createElement("div"),c=a.ui.menu.version.match(/^(\d)\.(\d+)/),d={major:parseInt(c[1],10),minor:parseInt(c[2],10)},e=d.major<2&&d.minor<=10,f=d.major<2&&d.minor<=11;a.widget("moogle.contextmenu",{version:"@VERSION",options:{addClass:"ui-contextmenu",closeOnWindowBlur:!0,appendTo:"body",autoFocus:!1,autoTrigger:!0,delegate:null,hide:{effect:"fadeOut",duration:"fast"},ignoreParentSelect:!0,menu:null,position:null,preventContextMenuForPopup:!1,preventSelect:!1,show:{effect:"slideDown",duration:"fast"},taphold:!1,uiMenuOptions:{},beforeOpen:a.noop,blur:a.noop,close:a.noop,create:a.noop,createMenu:a.noop,focus:a.noop,open:a.noop,select:a.noop},_create:function(){var c,d,e,f=this.options;if(this.$headStyle=null,this.$menu=null,this.menuIsTemp=!1,this.currentTarget=null,this.extraData={},this.previousFocus=null,null==f.delegate&&a.error("ui-contextmenu: Missing required option `delegate`."),f.preventSelect){e=(a(this.element).is(document)?a("body"):this.element).uniqueId().attr("id"),c="#"+e+" "+f.delegate+" { -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }",this.$headStyle=a("<style class='moogle-contextmenu-style' />").prop("type","text/css").appendTo("head");try{this.$headStyle.html(c)}catch(g){this.$headStyle[0].styleSheet.cssText=c}b&&this.element.on("selectstart"+this.eventNamespace,f.delegate,function(a){a.preventDefault()})}this._createUiMenu(f.menu),d="contextmenu"+this.eventNamespace,f.taphold&&(d+=" taphold"+this.eventNamespace),this.element.on(d,f.delegate,a.proxy(this._openMenu,this))},_destroy:function(){this.element.off(this.eventNamespace),this._createUiMenu(null),this.$headStyle&&(this.$headStyle.remove(),this.$headStyle=null)},_createUiMenu:function(b){var c,d,e=this.options;this.isOpen()&&(c=this.currentTarget,d=this.extraData,this._closeMenu(!0),this.currentTarget=c,this.extraData=d),this.menuIsTemp?this.$menu.remove():this.$menu&&this.$menu.menu("destroy").removeClass(e.addClass).hide(),this.$menu=null,this.menuIsTemp=!1,b&&(a.isArray(b)?(this.$menu=a.moogle.contextmenu.createMenuMarkup(b,null,e),this.menuIsTemp=!0):"string"==typeof b?this.$menu=a(b):this.$menu=b,this.$menu.hide().addClass(e.addClass).menu(a.extend(!0,{},e.uiMenuOptions,{items:"> :not(.ui-widget-header)",blur:a.proxy(e.blur,this),create:a.proxy(e.createMenu,this),focus:a.proxy(e.focus,this),select:a.proxy(function(b,c){var d,f=a.moogle.contextmenu.isMenu(c.item),g=c.item.data("actionHandler");c.cmd=c.item.attr("data-command"),c.target=a(this.currentTarget),c.extraData=this.extraData,f&&e.ignoreParentSelect||(d=this._trigger.call(this,"select",b,c),g&&(d=g.call(this,b,c)),d!==!1&&this._closeMenu.call(this),b.preventDefault())},this)})))},_openMenu:function(b,c){var d,e,f,g=this.options,h=g.position,i=this,j=!!b.isTrigger;if(g.autoTrigger||j){if(b.preventDefault(),this.currentTarget=b.target,this.extraData=b._extraData||{},f={menu:this.$menu,target:a(this.currentTarget),extraData:this.extraData,originalEvent:b,result:null},!c){if(d=this._trigger("beforeOpen",b,f),e=f.result&&a.isFunction(f.result.promise)?f.result:null,f.result=null,d===!1)return this.currentTarget=null,!1;if(e)return e.done(function(){i._openMenu(b,!0)}),this.currentTarget=null,!1;f.menu=this.$menu}a(document).on("keydown"+this.eventNamespace,function(b){b.which===a.ui.keyCode.ESCAPE&&i._closeMenu()}).on("mousedown"+this.eventNamespace+" touchstart"+this.eventNamespace,function(b){a(b.target).closest(".ui-menu-item").length||i._closeMenu()}),a(window).on("blur"+this.eventNamespace,function(a){g.closeOnWindowBlur&&i._closeMenu()}),a.isFunction(h)&&(h=h(b,f)),h=a.extend({my:"left top",at:"left bottom",of:void 0===b.pageX?b.target:b,collision:"fit"},h),this._updateEntries(this.$menu),this.$menu.show().css({position:"absolute",left:0,top:0}).position(h).hide(),g.preventContextMenuForPopup&&this.$menu.on("contextmenu"+this.eventNamespace,function(a){a.preventDefault()}),this._show(this.$menu,g.show,function(){var c;g.autoFocus&&(i.previousFocus=a(b.target),c=i.$menu.children("li.ui-menu-item").not(".ui-state-disabled").first(),i.$menu.menu("focus",null,c).focus()),i._trigger.call(i,"open",b,f)})}},_closeMenu:function(b){var c=this,d=!b&&this.options.hide,e={menu:this.$menu,target:a(this.currentTarget),extraData:this.extraData};a(document).off("mousedown"+this.eventNamespace).off("touchstart"+this.eventNamespace).off("keydown"+this.eventNamespace),a(window).off("blur"+this.eventNamespace),c.currentTarget=null,c.extraData={},this.$menu?(this.$menu.off("contextmenu"+this.eventNamespace),this._hide(this.$menu,d,function(){c.previousFocus&&(c.previousFocus.focus(),c.previousFocus=null),c._trigger("close",null,e)})):c._trigger("close",null,e)},_setOption:function(b,c){switch(b){case"menu":this.replaceMenu(c)}a.Widget.prototype._setOption.apply(this,arguments)},_getMenuEntry:function(a){return this.$menu.find("li[data-command="+a+"]")},close:function(){this.isOpen()&&this._closeMenu()},_updateEntries:function(){var b=this,c={menu:this.$menu,target:a(this.currentTarget),extraData:this.extraData};a.each(this.$menu.find(".ui-menu-item"),function(d,e){var f=a(e),g=f.data("disabledHandler"),h=g?g({type:"disabled"},c):null;c.item=f,c.cmd=f.attr("data-command"),null!=h&&(b.enableEntry(c.cmd,!h),b.showEntry(c.cmd,"hide"!==h)),g=f.data("titleHandler"),h=g?g({type:"title"},c):null,null!=h&&b.setTitle(c.cmd,""+h),g=f.data("tooltipHandler"),h=g?g({type:"tooltip"},c):null,null!=h&&f.attr("title",""+h)})},enableEntry:function(a,b){this._getMenuEntry(a).toggleClass("ui-state-disabled",b===!1)},getEntry:function(a){return this._getMenuEntry(a)},getEntryWrapper:function(a){return this._getMenuEntry(a).find(">[role=menuitem]").addBack("[role=menuitem]")},getMenu:function(){return this.$menu},isOpen:function(){return!!this.$menu&&!!this.currentTarget},open:function(b,c){c=c||{};var d=b&&b.type&&b.target,e=d?b:{},f=d?b.target:b,g=jQuery.Event("contextmenu",{target:a(f).get(0),pageX:e.pageX,pageY:e.pageY,originalEvent:d?b:void 0,_extraData:c});return this.element.trigger(g)},replaceMenu:function(a){this._createUiMenu(a)},setEntry:function(b,c){var d,e=this._getMenuEntry(b);return"string"==typeof c?(window.console&&window.console.warn("setEntry(cmd, t) with a plain string title is deprecated since v1.18.Use setTitle(cmd, '"+c+"') instead."),this.setTitle(b,c)):(e.empty(),c.cmd=c.cmd||b,a.moogle.contextmenu.createEntryMarkup(c,e),a.isArray(c.children)&&(d=a("<ul/>").appendTo(e),a.moogle.contextmenu.createMenuMarkup(c.children,d)),e.removeClass("ui-menu-item"),void this.getMenu().menu("refresh"))},setIcon:function(a,b){return this.updateEntry(a,{uiIcon:b})},setTitle:function(a,b){return this.updateEntry(a,{title:b})},showEntry:function(a,b){this._getMenuEntry(a).toggle(b!==!1)},updateEntry:function(b,c){var d,e,f=this._getMenuEntry(b);void 0!==c.title&&a.moogle.contextmenu.updateTitle(f,""+c.title),void 0!==c.tooltip&&(null===c.tooltip?f.removeAttr("title"):f.attr("title",c.tooltip)),void 0!==c.uiIcon&&(e=this.getEntryWrapper(b),d=e.find("span.ui-icon").not(".ui-menu-icon"),d.remove(),c.uiIcon&&e.append(a("<span class='ui-icon' />").addClass(c.uiIcon))),void 0!==c.hide?f.toggle(!c.hide):void 0!==c.show&&f.toggle(!!c.show),void 0!==c.data&&f.data(c.data),void 0===c.disabled&&(c.disabled=f.hasClass("ui-state-disabled")),c.setClass?(f.hasClass("ui-menu-item")&&(c.setClass+=" ui-menu-item"),f.removeClass(),f.addClass(c.setClass)):c.addClass&&f.addClass(c.addClass),f.toggleClass("ui-state-disabled",!!c.disabled)}}),a.extend(a.moogle.contextmenu,{createEntryMarkup:function(b,c){var d=null;c.attr("data-command",b.cmd),/[^\-\u2014\u2013\s]/.test(b.title)?(e?d=a("<a/>",{html:""+b.title,href:"#"}).appendTo(c):f?(c.html(""+b.title),d=c):d=a("<div/>",{html:""+b.title}).appendTo(c),b.uiIcon&&d.append(a("<span class='ui-icon' />").addClass(b.uiIcon)),a.each(["action","disabled","title","tooltip"],function(d,e){a.isFunction(b[e])&&c.data(e+"Handler",b[e])}),b.disabled===!0&&c.addClass("ui-state-disabled"),b.isHeader&&c.addClass("ui-widget-header"),b.addClass&&c.addClass(b.addClass),a.isPlainObject(b.data)&&c.data(b.data),"string"==typeof b.tooltip&&c.attr("title",b.tooltip)):c.text(b.title)},createMenuMarkup:function(b,c,d){var e,f,g,h,i=d&&d.appendTo?d.appendTo:"body";for(null==c&&(c=a("<ul class='ui-helper-hidden' />").appendTo(i)),e=0;e<b.length;e++)f=b[e],h=a("<li/>").appendTo(c),a.moogle.contextmenu.createEntryMarkup(f,h),a.isArray(f.children)&&(g=a("<ul/>").appendTo(h),a.moogle.contextmenu.createMenuMarkup(f.children,g));return c},isMenu:function(a){return e?a.has(">a[aria-haspopup='true']").length>0:f?a.is("[aria-haspopup='true']"):a.has(">div[aria-haspopup='true']").length>0},replaceFirstTextNodeChild:function(a,b){var c=a.find(">span.ui-icon,>ul.ui-menu").detach();a.empty().html(b).append(c)},updateTitle:function(b,c){e?a.moogle.contextmenu.replaceFirstTextNodeChild(a("a",b),c):f?a.moogle.contextmenu.replaceFirstTextNodeChild(b,c):a.moogle.contextmenu.replaceFirstTextNodeChild(a("div",b),c)}})});
+//# sourceMappingURL=jquery.ui-contextmenu.min.js.map \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.min.js.map b/plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.min.js.map
new file mode 100644
index 0000000..28dfb80
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/contextmenu/jquery.ui-contextmenu.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["jquery.ui-contextmenu.js"],"names":["factory","define","amd","jQuery","$","supportSelectstart","document","createElement","match","ui","menu","version","uiVersion","major","parseInt","minor","isLTE110","isLTE111","widget","options","addClass","closeOnWindowBlur","appendTo","autoFocus","autoTrigger","delegate","hide","effect","duration","ignoreParentSelect","position","preventContextMenuForPopup","preventSelect","show","taphold","uiMenuOptions","beforeOpen","noop","blur","close","create","createMenu","focus","open","select","_create","cssText","eventNames","targetId","opts","this","$headStyle","$menu","menuIsTemp","currentTarget","extraData","previousFocus","error","element","is","uniqueId","attr","prop","html","e","styleSheet","on","eventNamespace","event","preventDefault","_createUiMenu","proxy","_openMenu","_destroy","off","remove","menuDef","ct","ed","isOpen","_closeMenu","removeClass","isArray","moogle","contextmenu","createMenuMarkup","extend","items","retval","isParent","isMenu","item","actionHandler","data","cmd","target","_trigger","call","recursive","res","promise","posOption","self","manualTrigger","isTrigger","_extraData","originalEvent","result","isFunction","done","which","keyCode","ESCAPE","closest","length","window","my","at","of","undefined","pageX","collision","_updateEntries","css","left","top","_show","$first","children","not","first","immediately","hideOpts","_hide","_setOption","key","value","replaceMenu","Widget","prototype","apply","arguments","_getMenuEntry","find","each","i","o","$entry","fn","type","enableEntry","showEntry","setTitle","flag","toggleClass","getEntry","getEntryWrapper","addBack","getMenu","targetOrEvent","isEvent","Event","get","pageY","trigger","setEntry","entry","$ul","$entryLi","console","warn","empty","createEntryMarkup","setIcon","icon","updateEntry","uiIcon","title","toggle","$icon","$wrapper","updateTitle","tooltip","removeAttr","append","disabled","hasClass","setClass","$parentLi","test","href","isHeader","isPlainObject","text","$parentUl","$li","has","replaceFirstTextNodeChild","elem","$icons","detach"],"mappings":"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","file":"jquery.ui-contextmenu.min.js"} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/LICENSE.txt b/plugins/55/indexmenu/scripts/fancytree/LICENSE.txt
new file mode 100644
index 0000000..1a61571
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/LICENSE.txt
@@ -0,0 +1,21 @@
+Copyright 2008-2023 Martin Wendt,
+https://wwWendt.de/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.js b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.js
new file mode 100644
index 0000000..ab9b9d2
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.js
@@ -0,0 +1,13856 @@
+/*! jQuery Fancytree Plugin - 2.38.3 - 2023-02-01T20:52:50Z
+ * https://github.com/mar10/fancytree
+ * Copyright (c) 2023 Martin Wendt; Licensed MIT
+ */
+/*! jQuery UI - v1.13.0 - 2021-11-09
+* http://jqueryui.com
+* Includes: widget.js, position.js, jquery-patch.js, keycode.js, scroll-parent.js, unique-id.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+/*
+ NOTE: Original jQuery UI wrapper was replaced with a simple IIFE.
+ See README-Fancytree.md
+*/
+(function( $ ) {
+
+ $.ui = $.ui || {};
+
+ var version = $.ui.version = "1.13.2";
+
+
+ /*!
+ * jQuery UI Widget 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+ //>>label: Widget
+ //>>group: Core
+ //>>description: Provides a factory for creating stateful widgets with a common API.
+ //>>docs: http://api.jqueryui.com/jQuery.widget/
+ //>>demos: http://jqueryui.com/widget/
+
+
+ var widgetUuid = 0;
+ var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
+ var widgetSlice = Array.prototype.slice;
+
+ $.cleanData = ( function( orig ) {
+ return function( elems ) {
+ var events, elem, i;
+ for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
+
+ // Only trigger remove when necessary to save time
+ events = $._data( elem, "events" );
+ if ( events && events.remove ) {
+ $( elem ).triggerHandler( "remove" );
+ }
+ }
+ orig( elems );
+ };
+ } )( $.cleanData );
+
+ $.widget = function( name, base, prototype ) {
+ var existingConstructor, constructor, basePrototype;
+
+ // ProxiedPrototype allows the provided prototype to remain unmodified
+ // so that it can be used as a mixin for multiple widgets (#8876)
+ var proxiedPrototype = {};
+
+ var namespace = name.split( "." )[ 0 ];
+ name = name.split( "." )[ 1 ];
+ var fullName = namespace + "-" + name;
+
+ if ( !prototype ) {
+ prototype = base;
+ base = $.Widget;
+ }
+
+ if ( Array.isArray( prototype ) ) {
+ prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
+ }
+
+ // Create selector for plugin
+ $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
+ return !!$.data( elem, fullName );
+ };
+
+ $[ namespace ] = $[ namespace ] || {};
+ existingConstructor = $[ namespace ][ name ];
+ constructor = $[ namespace ][ name ] = function( options, element ) {
+
+ // Allow instantiation without "new" keyword
+ if ( !this || !this._createWidget ) {
+ return new constructor( options, element );
+ }
+
+ // Allow instantiation without initializing for simple inheritance
+ // must use "new" keyword (the code above always passes args)
+ if ( arguments.length ) {
+ this._createWidget( options, element );
+ }
+ };
+
+ // Extend with the existing constructor to carry over any static properties
+ $.extend( constructor, existingConstructor, {
+ version: prototype.version,
+
+ // Copy the object used to create the prototype in case we need to
+ // redefine the widget later
+ _proto: $.extend( {}, prototype ),
+
+ // Track widgets that inherit from this widget in case this widget is
+ // redefined after a widget inherits from it
+ _childConstructors: []
+ } );
+
+ basePrototype = new base();
+
+ // We need to make the options hash a property directly on the new instance
+ // otherwise we'll modify the options hash on the prototype that we're
+ // inheriting from
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
+ $.each( prototype, function( prop, value ) {
+ if ( typeof value !== "function" ) {
+ proxiedPrototype[ prop ] = value;
+ return;
+ }
+ proxiedPrototype[ prop ] = ( function() {
+ function _super() {
+ return base.prototype[ prop ].apply( this, arguments );
+ }
+
+ function _superApply( args ) {
+ return base.prototype[ prop ].apply( this, args );
+ }
+
+ return function() {
+ var __super = this._super;
+ var __superApply = this._superApply;
+ var returnValue;
+
+ this._super = _super;
+ this._superApply = _superApply;
+
+ returnValue = value.apply( this, arguments );
+
+ this._super = __super;
+ this._superApply = __superApply;
+
+ return returnValue;
+ };
+ } )();
+ } );
+ constructor.prototype = $.widget.extend( basePrototype, {
+
+ // TODO: remove support for widgetEventPrefix
+ // always use the name + a colon as the prefix, e.g., draggable:start
+ // don't prefix for widgets that aren't DOM-based
+ widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
+ }, proxiedPrototype, {
+ constructor: constructor,
+ namespace: namespace,
+ widgetName: name,
+ widgetFullName: fullName
+ } );
+
+ // If this widget is being redefined then we need to find all widgets that
+ // are inheriting from it and redefine all of them so that they inherit from
+ // the new version of this widget. We're essentially trying to replace one
+ // level in the prototype chain.
+ if ( existingConstructor ) {
+ $.each( existingConstructor._childConstructors, function( i, child ) {
+ var childPrototype = child.prototype;
+
+ // Redefine the child widget using the same prototype that was
+ // originally used, but inherit from the new version of the base
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
+ child._proto );
+ } );
+
+ // Remove the list of existing child constructors from the old constructor
+ // so the old child constructors can be garbage collected
+ delete existingConstructor._childConstructors;
+ } else {
+ base._childConstructors.push( constructor );
+ }
+
+ $.widget.bridge( name, constructor );
+
+ return constructor;
+ };
+
+ $.widget.extend = function( target ) {
+ var input = widgetSlice.call( arguments, 1 );
+ var inputIndex = 0;
+ var inputLength = input.length;
+ var key;
+ var value;
+
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
+ for ( key in input[ inputIndex ] ) {
+ value = input[ inputIndex ][ key ];
+ if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
+
+ // Clone objects
+ if ( $.isPlainObject( value ) ) {
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
+ $.widget.extend( {}, target[ key ], value ) :
+
+ // Don't extend strings, arrays, etc. with objects
+ $.widget.extend( {}, value );
+
+ // Copy everything else by reference
+ } else {
+ target[ key ] = value;
+ }
+ }
+ }
+ }
+ return target;
+ };
+
+ $.widget.bridge = function( name, object ) {
+ var fullName = object.prototype.widgetFullName || name;
+ $.fn[ name ] = function( options ) {
+ var isMethodCall = typeof options === "string";
+ var args = widgetSlice.call( arguments, 1 );
+ var returnValue = this;
+
+ if ( isMethodCall ) {
+
+ // If this is an empty collection, we need to have the instance method
+ // return undefined instead of the jQuery instance
+ if ( !this.length && options === "instance" ) {
+ returnValue = undefined;
+ } else {
+ this.each( function() {
+ var methodValue;
+ var instance = $.data( this, fullName );
+
+ if ( options === "instance" ) {
+ returnValue = instance;
+ return false;
+ }
+
+ if ( !instance ) {
+ return $.error( "cannot call methods on " + name +
+ " prior to initialization; " +
+ "attempted to call method '" + options + "'" );
+ }
+
+ if ( typeof instance[ options ] !== "function" ||
+ options.charAt( 0 ) === "_" ) {
+ return $.error( "no such method '" + options + "' for " + name +
+ " widget instance" );
+ }
+
+ methodValue = instance[ options ].apply( instance, args );
+
+ if ( methodValue !== instance && methodValue !== undefined ) {
+ returnValue = methodValue && methodValue.jquery ?
+ returnValue.pushStack( methodValue.get() ) :
+ methodValue;
+ return false;
+ }
+ } );
+ }
+ } else {
+
+ // Allow multiple hashes to be passed on init
+ if ( args.length ) {
+ options = $.widget.extend.apply( null, [ options ].concat( args ) );
+ }
+
+ this.each( function() {
+ var instance = $.data( this, fullName );
+ if ( instance ) {
+ instance.option( options || {} );
+ if ( instance._init ) {
+ instance._init();
+ }
+ } else {
+ $.data( this, fullName, new object( options, this ) );
+ }
+ } );
+ }
+
+ return returnValue;
+ };
+ };
+
+ $.Widget = function( /* options, element */ ) {};
+ $.Widget._childConstructors = [];
+
+ $.Widget.prototype = {
+ widgetName: "widget",
+ widgetEventPrefix: "",
+ defaultElement: "<div>",
+
+ options: {
+ classes: {},
+ disabled: false,
+
+ // Callbacks
+ create: null
+ },
+
+ _createWidget: function( options, element ) {
+ element = $( element || this.defaultElement || this )[ 0 ];
+ this.element = $( element );
+ this.uuid = widgetUuid++;
+ this.eventNamespace = "." + this.widgetName + this.uuid;
+
+ this.bindings = $();
+ this.hoverable = $();
+ this.focusable = $();
+ this.classesElementLookup = {};
+
+ if ( element !== this ) {
+ $.data( element, this.widgetFullName, this );
+ this._on( true, this.element, {
+ remove: function( event ) {
+ if ( event.target === element ) {
+ this.destroy();
+ }
+ }
+ } );
+ this.document = $( element.style ?
+
+ // Element within the document
+ element.ownerDocument :
+
+ // Element is window or document
+ element.document || element );
+ this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
+ }
+
+ this.options = $.widget.extend( {},
+ this.options,
+ this._getCreateOptions(),
+ options );
+
+ this._create();
+
+ if ( this.options.disabled ) {
+ this._setOptionDisabled( this.options.disabled );
+ }
+
+ this._trigger( "create", null, this._getCreateEventData() );
+ this._init();
+ },
+
+ _getCreateOptions: function() {
+ return {};
+ },
+
+ _getCreateEventData: $.noop,
+
+ _create: $.noop,
+
+ _init: $.noop,
+
+ destroy: function() {
+ var that = this;
+
+ this._destroy();
+ $.each( this.classesElementLookup, function( key, value ) {
+ that._removeClass( value, key );
+ } );
+
+ // We can probably remove the unbind calls in 2.0
+ // all event bindings should go through this._on()
+ this.element
+ .off( this.eventNamespace )
+ .removeData( this.widgetFullName );
+ this.widget()
+ .off( this.eventNamespace )
+ .removeAttr( "aria-disabled" );
+
+ // Clean up events and states
+ this.bindings.off( this.eventNamespace );
+ },
+
+ _destroy: $.noop,
+
+ widget: function() {
+ return this.element;
+ },
+
+ option: function( key, value ) {
+ var options = key;
+ var parts;
+ var curOption;
+ var i;
+
+ if ( arguments.length === 0 ) {
+
+ // Don't return a reference to the internal hash
+ return $.widget.extend( {}, this.options );
+ }
+
+ if ( typeof key === "string" ) {
+
+ // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
+ options = {};
+ parts = key.split( "." );
+ key = parts.shift();
+ if ( parts.length ) {
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
+ for ( i = 0; i < parts.length - 1; i++ ) {
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
+ curOption = curOption[ parts[ i ] ];
+ }
+ key = parts.pop();
+ if ( arguments.length === 1 ) {
+ return curOption[ key ] === undefined ? null : curOption[ key ];
+ }
+ curOption[ key ] = value;
+ } else {
+ if ( arguments.length === 1 ) {
+ return this.options[ key ] === undefined ? null : this.options[ key ];
+ }
+ options[ key ] = value;
+ }
+ }
+
+ this._setOptions( options );
+
+ return this;
+ },
+
+ _setOptions: function( options ) {
+ var key;
+
+ for ( key in options ) {
+ this._setOption( key, options[ key ] );
+ }
+
+ return this;
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "classes" ) {
+ this._setOptionClasses( value );
+ }
+
+ this.options[ key ] = value;
+
+ if ( key === "disabled" ) {
+ this._setOptionDisabled( value );
+ }
+
+ return this;
+ },
+
+ _setOptionClasses: function( value ) {
+ var classKey, elements, currentElements;
+
+ for ( classKey in value ) {
+ currentElements = this.classesElementLookup[ classKey ];
+ if ( value[ classKey ] === this.options.classes[ classKey ] ||
+ !currentElements ||
+ !currentElements.length ) {
+ continue;
+ }
+
+ // We are doing this to create a new jQuery object because the _removeClass() call
+ // on the next line is going to destroy the reference to the current elements being
+ // tracked. We need to save a copy of this collection so that we can add the new classes
+ // below.
+ elements = $( currentElements.get() );
+ this._removeClass( currentElements, classKey );
+
+ // We don't use _addClass() here, because that uses this.options.classes
+ // for generating the string of classes. We want to use the value passed in from
+ // _setOption(), this is the new value of the classes option which was passed to
+ // _setOption(). We pass this value directly to _classes().
+ elements.addClass( this._classes( {
+ element: elements,
+ keys: classKey,
+ classes: value,
+ add: true
+ } ) );
+ }
+ },
+
+ _setOptionDisabled: function( value ) {
+ this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
+
+ // If the widget is becoming disabled, then nothing is interactive
+ if ( value ) {
+ this._removeClass( this.hoverable, null, "ui-state-hover" );
+ this._removeClass( this.focusable, null, "ui-state-focus" );
+ }
+ },
+
+ enable: function() {
+ return this._setOptions( { disabled: false } );
+ },
+
+ disable: function() {
+ return this._setOptions( { disabled: true } );
+ },
+
+ _classes: function( options ) {
+ var full = [];
+ var that = this;
+
+ options = $.extend( {
+ element: this.element,
+ classes: this.options.classes || {}
+ }, options );
+
+ function bindRemoveEvent() {
+ var nodesToBind = [];
+
+ options.element.each( function( _, element ) {
+ var isTracked = $.map( that.classesElementLookup, function( elements ) {
+ return elements;
+ } )
+ .some( function( elements ) {
+ return elements.is( element );
+ } );
+
+ if ( !isTracked ) {
+ nodesToBind.push( element );
+ }
+ } );
+
+ that._on( $( nodesToBind ), {
+ remove: "_untrackClassesElement"
+ } );
+ }
+
+ function processClassString( classes, checkOption ) {
+ var current, i;
+ for ( i = 0; i < classes.length; i++ ) {
+ current = that.classesElementLookup[ classes[ i ] ] || $();
+ if ( options.add ) {
+ bindRemoveEvent();
+ current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
+ } else {
+ current = $( current.not( options.element ).get() );
+ }
+ that.classesElementLookup[ classes[ i ] ] = current;
+ full.push( classes[ i ] );
+ if ( checkOption && options.classes[ classes[ i ] ] ) {
+ full.push( options.classes[ classes[ i ] ] );
+ }
+ }
+ }
+
+ if ( options.keys ) {
+ processClassString( options.keys.match( /\S+/g ) || [], true );
+ }
+ if ( options.extra ) {
+ processClassString( options.extra.match( /\S+/g ) || [] );
+ }
+
+ return full.join( " " );
+ },
+
+ _untrackClassesElement: function( event ) {
+ var that = this;
+ $.each( that.classesElementLookup, function( key, value ) {
+ if ( $.inArray( event.target, value ) !== -1 ) {
+ that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
+ }
+ } );
+
+ this._off( $( event.target ) );
+ },
+
+ _removeClass: function( element, keys, extra ) {
+ return this._toggleClass( element, keys, extra, false );
+ },
+
+ _addClass: function( element, keys, extra ) {
+ return this._toggleClass( element, keys, extra, true );
+ },
+
+ _toggleClass: function( element, keys, extra, add ) {
+ add = ( typeof add === "boolean" ) ? add : extra;
+ var shift = ( typeof element === "string" || element === null ),
+ options = {
+ extra: shift ? keys : extra,
+ keys: shift ? element : keys,
+ element: shift ? this.element : element,
+ add: add
+ };
+ options.element.toggleClass( this._classes( options ), add );
+ return this;
+ },
+
+ _on: function( suppressDisabledCheck, element, handlers ) {
+ var delegateElement;
+ var instance = this;
+
+ // No suppressDisabledCheck flag, shuffle arguments
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
+ handlers = element;
+ element = suppressDisabledCheck;
+ suppressDisabledCheck = false;
+ }
+
+ // No element argument, shuffle and use this.element
+ if ( !handlers ) {
+ handlers = element;
+ element = this.element;
+ delegateElement = this.widget();
+ } else {
+ element = delegateElement = $( element );
+ this.bindings = this.bindings.add( element );
+ }
+
+ $.each( handlers, function( event, handler ) {
+ function handlerProxy() {
+
+ // Allow widgets to customize the disabled handling
+ // - disabled as an array instead of boolean
+ // - disabled class as method for disabling individual parts
+ if ( !suppressDisabledCheck &&
+ ( instance.options.disabled === true ||
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
+ return;
+ }
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+
+ // Copy the guid so direct unbinding works
+ if ( typeof handler !== "string" ) {
+ handlerProxy.guid = handler.guid =
+ handler.guid || handlerProxy.guid || $.guid++;
+ }
+
+ var match = event.match( /^([\w:-]*)\s*(.*)$/ );
+ var eventName = match[ 1 ] + instance.eventNamespace;
+ var selector = match[ 2 ];
+
+ if ( selector ) {
+ delegateElement.on( eventName, selector, handlerProxy );
+ } else {
+ element.on( eventName, handlerProxy );
+ }
+ } );
+ },
+
+ _off: function( element, eventName ) {
+ eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
+ this.eventNamespace;
+ element.off( eventName );
+
+ // Clear the stack to avoid memory leaks (#10056)
+ this.bindings = $( this.bindings.not( element ).get() );
+ this.focusable = $( this.focusable.not( element ).get() );
+ this.hoverable = $( this.hoverable.not( element ).get() );
+ },
+
+ _delay: function( handler, delay ) {
+ function handlerProxy() {
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+ var instance = this;
+ return setTimeout( handlerProxy, delay || 0 );
+ },
+
+ _hoverable: function( element ) {
+ this.hoverable = this.hoverable.add( element );
+ this._on( element, {
+ mouseenter: function( event ) {
+ this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
+ },
+ mouseleave: function( event ) {
+ this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
+ }
+ } );
+ },
+
+ _focusable: function( element ) {
+ this.focusable = this.focusable.add( element );
+ this._on( element, {
+ focusin: function( event ) {
+ this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
+ },
+ focusout: function( event ) {
+ this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
+ }
+ } );
+ },
+
+ _trigger: function( type, event, data ) {
+ var prop, orig;
+ var callback = this.options[ type ];
+
+ data = data || {};
+ event = $.Event( event );
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+
+ // The original event may come from any element
+ // so we need to reset the target on the new event
+ event.target = this.element[ 0 ];
+
+ // Copy original event properties over to the new event
+ orig = event.originalEvent;
+ if ( orig ) {
+ for ( prop in orig ) {
+ if ( !( prop in event ) ) {
+ event[ prop ] = orig[ prop ];
+ }
+ }
+ }
+
+ this.element.trigger( event, data );
+ return !( typeof callback === "function" &&
+ callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
+ event.isDefaultPrevented() );
+ }
+ };
+
+ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
+ if ( typeof options === "string" ) {
+ options = { effect: options };
+ }
+
+ var hasOptions;
+ var effectName = !options ?
+ method :
+ options === true || typeof options === "number" ?
+ defaultEffect :
+ options.effect || defaultEffect;
+
+ options = options || {};
+ if ( typeof options === "number" ) {
+ options = { duration: options };
+ } else if ( options === true ) {
+ options = {};
+ }
+
+ hasOptions = !$.isEmptyObject( options );
+ options.complete = callback;
+
+ if ( options.delay ) {
+ element.delay( options.delay );
+ }
+
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
+ element[ method ]( options );
+ } else if ( effectName !== method && element[ effectName ] ) {
+ element[ effectName ]( options.duration, options.easing, callback );
+ } else {
+ element.queue( function( next ) {
+ $( this )[ method ]();
+ if ( callback ) {
+ callback.call( element[ 0 ] );
+ }
+ next();
+ } );
+ }
+ };
+ } );
+
+ var widget = $.widget;
+
+
+ /*!
+ * jQuery UI Position 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/position/
+ */
+
+ //>>label: Position
+ //>>group: Core
+ //>>description: Positions elements relative to other elements.
+ //>>docs: http://api.jqueryui.com/position/
+ //>>demos: http://jqueryui.com/position/
+
+
+ ( function() {
+ var cachedScrollbarWidth,
+ max = Math.max,
+ abs = Math.abs,
+ rhorizontal = /left|center|right/,
+ rvertical = /top|center|bottom/,
+ roffset = /[\+\-]\d+(\.[\d]+)?%?/,
+ rposition = /^\w+/,
+ rpercent = /%$/,
+ _position = $.fn.position;
+
+ function getOffsets( offsets, width, height ) {
+ return [
+ parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
+ parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
+ ];
+ }
+
+ function parseCss( element, property ) {
+ return parseInt( $.css( element, property ), 10 ) || 0;
+ }
+
+ function isWindow( obj ) {
+ return obj != null && obj === obj.window;
+ }
+
+ function getDimensions( elem ) {
+ var raw = elem[ 0 ];
+ if ( raw.nodeType === 9 ) {
+ return {
+ width: elem.width(),
+ height: elem.height(),
+ offset: { top: 0, left: 0 }
+ };
+ }
+ if ( isWindow( raw ) ) {
+ return {
+ width: elem.width(),
+ height: elem.height(),
+ offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
+ };
+ }
+ if ( raw.preventDefault ) {
+ return {
+ width: 0,
+ height: 0,
+ offset: { top: raw.pageY, left: raw.pageX }
+ };
+ }
+ return {
+ width: elem.outerWidth(),
+ height: elem.outerHeight(),
+ offset: elem.offset()
+ };
+ }
+
+ $.position = {
+ scrollbarWidth: function() {
+ if ( cachedScrollbarWidth !== undefined ) {
+ return cachedScrollbarWidth;
+ }
+ var w1, w2,
+ div = $( "<div style=" +
+ "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
+ "<div style='height:300px;width:auto;'></div></div>" ),
+ innerDiv = div.children()[ 0 ];
+
+ $( "body" ).append( div );
+ w1 = innerDiv.offsetWidth;
+ div.css( "overflow", "scroll" );
+
+ w2 = innerDiv.offsetWidth;
+
+ if ( w1 === w2 ) {
+ w2 = div[ 0 ].clientWidth;
+ }
+
+ div.remove();
+
+ return ( cachedScrollbarWidth = w1 - w2 );
+ },
+ getScrollInfo: function( within ) {
+ var overflowX = within.isWindow || within.isDocument ? "" :
+ within.element.css( "overflow-x" ),
+ overflowY = within.isWindow || within.isDocument ? "" :
+ within.element.css( "overflow-y" ),
+ hasOverflowX = overflowX === "scroll" ||
+ ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
+ hasOverflowY = overflowY === "scroll" ||
+ ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
+ return {
+ width: hasOverflowY ? $.position.scrollbarWidth() : 0,
+ height: hasOverflowX ? $.position.scrollbarWidth() : 0
+ };
+ },
+ getWithinInfo: function( element ) {
+ var withinElement = $( element || window ),
+ isElemWindow = isWindow( withinElement[ 0 ] ),
+ isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
+ hasOffset = !isElemWindow && !isDocument;
+ return {
+ element: withinElement,
+ isWindow: isElemWindow,
+ isDocument: isDocument,
+ offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
+ scrollLeft: withinElement.scrollLeft(),
+ scrollTop: withinElement.scrollTop(),
+ width: withinElement.outerWidth(),
+ height: withinElement.outerHeight()
+ };
+ }
+ };
+
+ $.fn.position = function( options ) {
+ if ( !options || !options.of ) {
+ return _position.apply( this, arguments );
+ }
+
+ // Make a copy, we don't want to modify arguments
+ options = $.extend( {}, options );
+
+ var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
+
+ // Make sure string options are treated as CSS selectors
+ target = typeof options.of === "string" ?
+ $( document ).find( options.of ) :
+ $( options.of ),
+
+ within = $.position.getWithinInfo( options.within ),
+ scrollInfo = $.position.getScrollInfo( within ),
+ collision = ( options.collision || "flip" ).split( " " ),
+ offsets = {};
+
+ dimensions = getDimensions( target );
+ if ( target[ 0 ].preventDefault ) {
+
+ // Force left top to allow flipping
+ options.at = "left top";
+ }
+ targetWidth = dimensions.width;
+ targetHeight = dimensions.height;
+ targetOffset = dimensions.offset;
+
+ // Clone to reuse original targetOffset later
+ basePosition = $.extend( {}, targetOffset );
+
+ // Force my and at to have valid horizontal and vertical positions
+ // if a value is missing or invalid, it will be converted to center
+ $.each( [ "my", "at" ], function() {
+ var pos = ( options[ this ] || "" ).split( " " ),
+ horizontalOffset,
+ verticalOffset;
+
+ if ( pos.length === 1 ) {
+ pos = rhorizontal.test( pos[ 0 ] ) ?
+ pos.concat( [ "center" ] ) :
+ rvertical.test( pos[ 0 ] ) ?
+ [ "center" ].concat( pos ) :
+ [ "center", "center" ];
+ }
+ pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
+ pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
+
+ // Calculate offsets
+ horizontalOffset = roffset.exec( pos[ 0 ] );
+ verticalOffset = roffset.exec( pos[ 1 ] );
+ offsets[ this ] = [
+ horizontalOffset ? horizontalOffset[ 0 ] : 0,
+ verticalOffset ? verticalOffset[ 0 ] : 0
+ ];
+
+ // Reduce to just the positions without the offsets
+ options[ this ] = [
+ rposition.exec( pos[ 0 ] )[ 0 ],
+ rposition.exec( pos[ 1 ] )[ 0 ]
+ ];
+ } );
+
+ // Normalize collision option
+ if ( collision.length === 1 ) {
+ collision[ 1 ] = collision[ 0 ];
+ }
+
+ if ( options.at[ 0 ] === "right" ) {
+ basePosition.left += targetWidth;
+ } else if ( options.at[ 0 ] === "center" ) {
+ basePosition.left += targetWidth / 2;
+ }
+
+ if ( options.at[ 1 ] === "bottom" ) {
+ basePosition.top += targetHeight;
+ } else if ( options.at[ 1 ] === "center" ) {
+ basePosition.top += targetHeight / 2;
+ }
+
+ atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
+ basePosition.left += atOffset[ 0 ];
+ basePosition.top += atOffset[ 1 ];
+
+ return this.each( function() {
+ var collisionPosition, using,
+ elem = $( this ),
+ elemWidth = elem.outerWidth(),
+ elemHeight = elem.outerHeight(),
+ marginLeft = parseCss( this, "marginLeft" ),
+ marginTop = parseCss( this, "marginTop" ),
+ collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
+ scrollInfo.width,
+ collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
+ scrollInfo.height,
+ position = $.extend( {}, basePosition ),
+ myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
+
+ if ( options.my[ 0 ] === "right" ) {
+ position.left -= elemWidth;
+ } else if ( options.my[ 0 ] === "center" ) {
+ position.left -= elemWidth / 2;
+ }
+
+ if ( options.my[ 1 ] === "bottom" ) {
+ position.top -= elemHeight;
+ } else if ( options.my[ 1 ] === "center" ) {
+ position.top -= elemHeight / 2;
+ }
+
+ position.left += myOffset[ 0 ];
+ position.top += myOffset[ 1 ];
+
+ collisionPosition = {
+ marginLeft: marginLeft,
+ marginTop: marginTop
+ };
+
+ $.each( [ "left", "top" ], function( i, dir ) {
+ if ( $.ui.position[ collision[ i ] ] ) {
+ $.ui.position[ collision[ i ] ][ dir ]( position, {
+ targetWidth: targetWidth,
+ targetHeight: targetHeight,
+ elemWidth: elemWidth,
+ elemHeight: elemHeight,
+ collisionPosition: collisionPosition,
+ collisionWidth: collisionWidth,
+ collisionHeight: collisionHeight,
+ offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
+ my: options.my,
+ at: options.at,
+ within: within,
+ elem: elem
+ } );
+ }
+ } );
+
+ if ( options.using ) {
+
+ // Adds feedback as second argument to using callback, if present
+ using = function( props ) {
+ var left = targetOffset.left - position.left,
+ right = left + targetWidth - elemWidth,
+ top = targetOffset.top - position.top,
+ bottom = top + targetHeight - elemHeight,
+ feedback = {
+ target: {
+ element: target,
+ left: targetOffset.left,
+ top: targetOffset.top,
+ width: targetWidth,
+ height: targetHeight
+ },
+ element: {
+ element: elem,
+ left: position.left,
+ top: position.top,
+ width: elemWidth,
+ height: elemHeight
+ },
+ horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
+ vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
+ };
+ if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
+ feedback.horizontal = "center";
+ }
+ if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
+ feedback.vertical = "middle";
+ }
+ if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
+ feedback.important = "horizontal";
+ } else {
+ feedback.important = "vertical";
+ }
+ options.using.call( this, props, feedback );
+ };
+ }
+
+ elem.offset( $.extend( position, { using: using } ) );
+ } );
+ };
+
+ $.ui.position = {
+ fit: {
+ left: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
+ outerWidth = within.width,
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = withinOffset - collisionPosLeft,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
+ newOverRight;
+
+ // Element is wider than within
+ if ( data.collisionWidth > outerWidth ) {
+
+ // Element is initially over the left side of within
+ if ( overLeft > 0 && overRight <= 0 ) {
+ newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
+ withinOffset;
+ position.left += overLeft - newOverRight;
+
+ // Element is initially over right side of within
+ } else if ( overRight > 0 && overLeft <= 0 ) {
+ position.left = withinOffset;
+
+ // Element is initially over both left and right sides of within
+ } else {
+ if ( overLeft > overRight ) {
+ position.left = withinOffset + outerWidth - data.collisionWidth;
+ } else {
+ position.left = withinOffset;
+ }
+ }
+
+ // Too far left -> align with left edge
+ } else if ( overLeft > 0 ) {
+ position.left += overLeft;
+
+ // Too far right -> align with right edge
+ } else if ( overRight > 0 ) {
+ position.left -= overRight;
+
+ // Adjust based on position and margin
+ } else {
+ position.left = max( position.left - collisionPosLeft, position.left );
+ }
+ },
+ top: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
+ outerHeight = data.within.height,
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = withinOffset - collisionPosTop,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
+ newOverBottom;
+
+ // Element is taller than within
+ if ( data.collisionHeight > outerHeight ) {
+
+ // Element is initially over the top of within
+ if ( overTop > 0 && overBottom <= 0 ) {
+ newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
+ withinOffset;
+ position.top += overTop - newOverBottom;
+
+ // Element is initially over bottom of within
+ } else if ( overBottom > 0 && overTop <= 0 ) {
+ position.top = withinOffset;
+
+ // Element is initially over both top and bottom of within
+ } else {
+ if ( overTop > overBottom ) {
+ position.top = withinOffset + outerHeight - data.collisionHeight;
+ } else {
+ position.top = withinOffset;
+ }
+ }
+
+ // Too far up -> align with top
+ } else if ( overTop > 0 ) {
+ position.top += overTop;
+
+ // Too far down -> align with bottom edge
+ } else if ( overBottom > 0 ) {
+ position.top -= overBottom;
+
+ // Adjust based on position and margin
+ } else {
+ position.top = max( position.top - collisionPosTop, position.top );
+ }
+ }
+ },
+ flip: {
+ left: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.offset.left + within.scrollLeft,
+ outerWidth = within.width,
+ offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = collisionPosLeft - offsetLeft,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
+ myOffset = data.my[ 0 ] === "left" ?
+ -data.elemWidth :
+ data.my[ 0 ] === "right" ?
+ data.elemWidth :
+ 0,
+ atOffset = data.at[ 0 ] === "left" ?
+ data.targetWidth :
+ data.at[ 0 ] === "right" ?
+ -data.targetWidth :
+ 0,
+ offset = -2 * data.offset[ 0 ],
+ newOverRight,
+ newOverLeft;
+
+ if ( overLeft < 0 ) {
+ newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
+ outerWidth - withinOffset;
+ if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
+ position.left += myOffset + atOffset + offset;
+ }
+ } else if ( overRight > 0 ) {
+ newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
+ atOffset + offset - offsetLeft;
+ if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
+ position.left += myOffset + atOffset + offset;
+ }
+ }
+ },
+ top: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.offset.top + within.scrollTop,
+ outerHeight = within.height,
+ offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = collisionPosTop - offsetTop,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
+ top = data.my[ 1 ] === "top",
+ myOffset = top ?
+ -data.elemHeight :
+ data.my[ 1 ] === "bottom" ?
+ data.elemHeight :
+ 0,
+ atOffset = data.at[ 1 ] === "top" ?
+ data.targetHeight :
+ data.at[ 1 ] === "bottom" ?
+ -data.targetHeight :
+ 0,
+ offset = -2 * data.offset[ 1 ],
+ newOverTop,
+ newOverBottom;
+ if ( overTop < 0 ) {
+ newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
+ outerHeight - withinOffset;
+ if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
+ position.top += myOffset + atOffset + offset;
+ }
+ } else if ( overBottom > 0 ) {
+ newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
+ offset - offsetTop;
+ if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
+ position.top += myOffset + atOffset + offset;
+ }
+ }
+ }
+ },
+ flipfit: {
+ left: function() {
+ $.ui.position.flip.left.apply( this, arguments );
+ $.ui.position.fit.left.apply( this, arguments );
+ },
+ top: function() {
+ $.ui.position.flip.top.apply( this, arguments );
+ $.ui.position.fit.top.apply( this, arguments );
+ }
+ }
+ };
+
+ } )();
+
+ var position = $.ui.position;
+
+
+ /*!
+ * jQuery UI Support for jQuery core 1.8.x and newer 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ */
+
+ //>>label: jQuery 1.8+ Support
+ //>>group: Core
+ //>>description: Support version 1.8.x and newer of jQuery core
+
+
+ // Support: jQuery 1.9.x or older
+ // $.expr[ ":" ] is deprecated.
+ if ( !$.expr.pseudos ) {
+ $.expr.pseudos = $.expr[ ":" ];
+ }
+
+ // Support: jQuery 1.11.x or older
+ // $.unique has been renamed to $.uniqueSort
+ if ( !$.uniqueSort ) {
+ $.uniqueSort = $.unique;
+ }
+
+ // Support: jQuery 2.2.x or older.
+ // This method has been defined in jQuery 3.0.0.
+ // Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
+ if ( !$.escapeSelector ) {
+
+ // CSS string/identifier serialization
+ // https://drafts.csswg.org/cssom/#common-serializing-idioms
+ var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
+
+ var fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ };
+
+ $.escapeSelector = function( sel ) {
+ return ( sel + "" ).replace( rcssescape, fcssescape );
+ };
+ }
+
+ // Support: jQuery 3.4.x or older
+ // These methods have been defined in jQuery 3.5.0.
+ if ( !$.fn.even || !$.fn.odd ) {
+ $.fn.extend( {
+ even: function() {
+ return this.filter( function( i ) {
+ return i % 2 === 0;
+ } );
+ },
+ odd: function() {
+ return this.filter( function( i ) {
+ return i % 2 === 1;
+ } );
+ }
+ } );
+ }
+
+ ;
+ /*!
+ * jQuery UI Keycode 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+ //>>label: Keycode
+ //>>group: Core
+ //>>description: Provide keycodes as keynames
+ //>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
+
+
+ var keycode = $.ui.keyCode = {
+ BACKSPACE: 8,
+ COMMA: 188,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ LEFT: 37,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38
+ };
+
+
+ /*!
+ * jQuery UI Scroll Parent 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+ //>>label: scrollParent
+ //>>group: Core
+ //>>description: Get the closest ancestor element that is scrollable.
+ //>>docs: http://api.jqueryui.com/scrollParent/
+
+
+ var scrollParent = $.fn.scrollParent = function( includeHidden ) {
+ var position = this.css( "position" ),
+ excludeStaticParent = position === "absolute",
+ overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
+ scrollParent = this.parents().filter( function() {
+ var parent = $( this );
+ if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
+ return false;
+ }
+ return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
+ parent.css( "overflow-x" ) );
+ } ).eq( 0 );
+
+ return position === "fixed" || !scrollParent.length ?
+ $( this[ 0 ].ownerDocument || document ) :
+ scrollParent;
+ };
+
+
+ /*!
+ * jQuery UI Unique ID 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+ //>>label: uniqueId
+ //>>group: Core
+ //>>description: Functions to generate and remove uniqueId's
+ //>>docs: http://api.jqueryui.com/uniqueId/
+
+
+ var uniqueId = $.fn.extend( {
+ uniqueId: ( function() {
+ var uuid = 0;
+
+ return function() {
+ return this.each( function() {
+ if ( !this.id ) {
+ this.id = "ui-id-" + ( ++uuid );
+ }
+ } );
+ };
+ } )(),
+
+ removeUniqueId: function() {
+ return this.each( function() {
+ if ( /^ui-id-\d+$/.test( this.id ) ) {
+ $( this ).removeAttr( "id" );
+ }
+ } );
+ }
+ } );
+
+
+
+
+// NOTE: Original jQuery UI wrapper was replaced. See README-Fancytree.md
+// }));
+})(jQuery);
+
+(function( factory ) {
+ if ( typeof define === "function" && define.amd ) {
+ // AMD. Register as an anonymous module.
+ define( [ "jquery" ], factory );
+ } else if ( typeof module === "object" && module.exports ) {
+ // Node/CommonJS
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory( jQuery );
+ }
+}(function( $ ) {
+
+
+/*! Fancytree Core *//*!
+ * jquery.fancytree.js
+ * Tree view control with support for lazy loading and much more.
+ * https://github.com/mar10/fancytree/
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+/** Core Fancytree module.
+ */
+
+// UMD wrapper for the Fancytree core module
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree.ui-deps"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree.ui-deps");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ // prevent duplicate loading
+ if ($.ui && $.ui.fancytree) {
+ $.ui.fancytree.warn("Fancytree: ignored duplicate include");
+ return;
+ }
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+
+ var i,
+ attr,
+ FT = null, // initialized below
+ TEST_IMG = new RegExp(/\.|\//), // strings are considered image urls if they contain '.' or '/'
+ REX_HTML = /[&<>"'/]/g, // Escape those characters
+ REX_TOOLTIP = /[<>"'/]/g, // Don't escape `&` in tooltips
+ RECURSIVE_REQUEST_ERROR = "$recursive_request",
+ INVALID_REQUEST_TARGET_ERROR = "$request_target_invalid",
+ ENTITY_MAP = {
+ "&": "&amp;",
+ "<": "&lt;",
+ ">": "&gt;",
+ '"': "&quot;",
+ "'": "&#39;",
+ "/": "&#x2F;",
+ },
+ IGNORE_KEYCODES = { 16: true, 17: true, 18: true },
+ SPECIAL_KEYCODES = {
+ 8: "backspace",
+ 9: "tab",
+ 10: "return",
+ 13: "return",
+ // 16: null, 17: null, 18: null, // ignore shift, ctrl, alt
+ 19: "pause",
+ 20: "capslock",
+ 27: "esc",
+ 32: "space",
+ 33: "pageup",
+ 34: "pagedown",
+ 35: "end",
+ 36: "home",
+ 37: "left",
+ 38: "up",
+ 39: "right",
+ 40: "down",
+ 45: "insert",
+ 46: "del",
+ 59: ";",
+ 61: "=",
+ // 91: null, 93: null, // ignore left and right meta
+ 96: "0",
+ 97: "1",
+ 98: "2",
+ 99: "3",
+ 100: "4",
+ 101: "5",
+ 102: "6",
+ 103: "7",
+ 104: "8",
+ 105: "9",
+ 106: "*",
+ 107: "+",
+ 109: "-",
+ 110: ".",
+ 111: "/",
+ 112: "f1",
+ 113: "f2",
+ 114: "f3",
+ 115: "f4",
+ 116: "f5",
+ 117: "f6",
+ 118: "f7",
+ 119: "f8",
+ 120: "f9",
+ 121: "f10",
+ 122: "f11",
+ 123: "f12",
+ 144: "numlock",
+ 145: "scroll",
+ 173: "-",
+ 186: ";",
+ 187: "=",
+ 188: ",",
+ 189: "-",
+ 190: ".",
+ 191: "/",
+ 192: "`",
+ 219: "[",
+ 220: "\\",
+ 221: "]",
+ 222: "'",
+ },
+ MODIFIERS = {
+ 16: "shift",
+ 17: "ctrl",
+ 18: "alt",
+ 91: "meta",
+ 93: "meta",
+ },
+ MOUSE_BUTTONS = { 0: "", 1: "left", 2: "middle", 3: "right" },
+ // Boolean attributes that can be set with equivalent class names in the LI tags
+ // Note: v2.23: checkbox and hideCheckbox are *not* in this list
+ CLASS_ATTRS =
+ "active expanded focus folder lazy radiogroup selected unselectable unselectableIgnore".split(
+ " "
+ ),
+ CLASS_ATTR_MAP = {},
+ // Top-level Fancytree attributes, that can be set by dict
+ TREE_ATTRS = "columns types".split(" "),
+ // TREE_ATTR_MAP = {},
+ // Top-level FancytreeNode attributes, that can be set by dict
+ NODE_ATTRS =
+ "checkbox expanded extraClasses folder icon iconTooltip key lazy partsel radiogroup refKey selected statusNodeType title tooltip type unselectable unselectableIgnore unselectableStatus".split(
+ " "
+ ),
+ NODE_ATTR_MAP = {},
+ // Mapping of lowercase -> real name (because HTML5 data-... attribute only supports lowercase)
+ NODE_ATTR_LOWERCASE_MAP = {},
+ // Attribute names that should NOT be added to node.data
+ NONE_NODE_DATA_MAP = {
+ active: true,
+ children: true,
+ data: true,
+ focus: true,
+ };
+
+ for (i = 0; i < CLASS_ATTRS.length; i++) {
+ CLASS_ATTR_MAP[CLASS_ATTRS[i]] = true;
+ }
+ for (i = 0; i < NODE_ATTRS.length; i++) {
+ attr = NODE_ATTRS[i];
+ NODE_ATTR_MAP[attr] = true;
+ if (attr !== attr.toLowerCase()) {
+ NODE_ATTR_LOWERCASE_MAP[attr.toLowerCase()] = attr;
+ }
+ }
+ // for(i=0; i<TREE_ATTRS.length; i++) {
+ // TREE_ATTR_MAP[TREE_ATTRS[i]] = true;
+ // }
+
+ function _assert(cond, msg) {
+ // TODO: see qunit.js extractStacktrace()
+ if (!cond) {
+ msg = msg ? ": " + msg : "";
+ msg = "Fancytree assertion failed" + msg;
+
+ // consoleApply("assert", [!!cond, msg]);
+
+ // #1041: Raised exceptions may not be visible in the browser
+ // console if inside promise chains, so we also print directly:
+ $.ui.fancytree.error(msg);
+
+ // Throw exception:
+ $.error(msg);
+ }
+ }
+
+ function _hasProp(object, property) {
+ return Object.prototype.hasOwnProperty.call(object, property);
+ }
+
+ /* Replacement for the deprecated `jQuery.isFunction()`. */
+ function _isFunction(obj) {
+ return typeof obj === "function";
+ }
+
+ /* Replacement for the deprecated `jQuery.trim()`. */
+ function _trim(text) {
+ return text == null ? "" : text.trim();
+ }
+
+ /* Replacement for the deprecated `jQuery.isArray()`. */
+ var _isArray = Array.isArray;
+
+ _assert($.ui, "Fancytree requires jQuery UI (http://jqueryui.com)");
+
+ function consoleApply(method, args) {
+ var i,
+ s,
+ fn = window.console ? window.console[method] : null;
+
+ if (fn) {
+ try {
+ fn.apply(window.console, args);
+ } catch (e) {
+ // IE 8?
+ s = "";
+ for (i = 0; i < args.length; i++) {
+ s += args[i];
+ }
+ fn(s);
+ }
+ }
+ }
+
+ /* support: IE8 Polyfil for Date.now() */
+ if (!Date.now) {
+ Date.now = function now() {
+ return new Date().getTime();
+ };
+ }
+
+ /*Return true if x is a FancytreeNode.*/
+ function _isNode(x) {
+ return !!(x.tree && x.statusNodeType !== undefined);
+ }
+
+ /** Return true if dotted version string is equal or higher than requested version.
+ *
+ * See http://jsfiddle.net/mar10/FjSAN/
+ */
+ function isVersionAtLeast(dottedVersion, major, minor, patch) {
+ var i,
+ v,
+ t,
+ verParts = $.map(_trim(dottedVersion).split("."), function (e) {
+ return parseInt(e, 10);
+ }),
+ testParts = $.map(
+ Array.prototype.slice.call(arguments, 1),
+ function (e) {
+ return parseInt(e, 10);
+ }
+ );
+
+ for (i = 0; i < testParts.length; i++) {
+ v = verParts[i] || 0;
+ t = testParts[i] || 0;
+ if (v !== t) {
+ return v > t;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Deep-merge a list of objects (but replace array-type options).
+ *
+ * jQuery's $.extend(true, ...) method does a deep merge, that also merges Arrays.
+ * This variant is used to merge extension defaults with user options, and should
+ * merge objects, but override arrays (for example the `triggerStart: [...]` option
+ * of ext-edit). Also `null` values are copied over and not skipped.
+ *
+ * See issue #876
+ *
+ * Example:
+ * _simpleDeepMerge({}, o1, o2);
+ */
+ function _simpleDeepMerge() {
+ var options,
+ name,
+ src,
+ copy,
+ clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length;
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if (typeof target !== "object" && !_isFunction(target)) {
+ target = {};
+ }
+ if (i === length) {
+ throw Error("need at least two args");
+ }
+ for (; i < length; i++) {
+ // Only deal with non-null/undefined values
+ if ((options = arguments[i]) != null) {
+ // Extend the base object
+ for (name in options) {
+ if (_hasProp(options, name)) {
+ src = target[name];
+ copy = options[name];
+ // Prevent never-ending loop
+ if (target === copy) {
+ continue;
+ }
+ // Recurse if we're merging plain objects
+ // (NOTE: unlike $.extend, we don't merge arrays, but replace them)
+ if (copy && $.isPlainObject(copy)) {
+ clone = src && $.isPlainObject(src) ? src : {};
+ // Never move original objects, clone them
+ target[name] = _simpleDeepMerge(clone, copy);
+ // Don't bring in undefined values
+ } else if (copy !== undefined) {
+ target[name] = copy;
+ }
+ }
+ }
+ }
+ }
+ // Return the modified object
+ return target;
+ }
+
+ /** Return a wrapper that calls sub.methodName() and exposes
+ * this : tree
+ * this._local : tree.ext.EXTNAME
+ * this._super : base.methodName.call()
+ * this._superApply : base.methodName.apply()
+ */
+ function _makeVirtualFunction(methodName, tree, base, extension, extName) {
+ // $.ui.fancytree.debug("_makeVirtualFunction", methodName, tree, base, extension, extName);
+ // if(rexTestSuper && !rexTestSuper.test(func)){
+ // // extension.methodName() doesn't call _super(), so no wrapper required
+ // return func;
+ // }
+ // Use an immediate function as closure
+ var proxy = (function () {
+ var prevFunc = tree[methodName], // org. tree method or prev. proxy
+ baseFunc = extension[methodName], //
+ _local = tree.ext[extName],
+ _super = function () {
+ return prevFunc.apply(tree, arguments);
+ },
+ _superApply = function (args) {
+ return prevFunc.apply(tree, args);
+ };
+
+ // Return the wrapper function
+ return function () {
+ var prevLocal = tree._local,
+ prevSuper = tree._super,
+ prevSuperApply = tree._superApply;
+
+ try {
+ tree._local = _local;
+ tree._super = _super;
+ tree._superApply = _superApply;
+ return baseFunc.apply(tree, arguments);
+ } finally {
+ tree._local = prevLocal;
+ tree._super = prevSuper;
+ tree._superApply = prevSuperApply;
+ }
+ };
+ })(); // end of Immediate Function
+ return proxy;
+ }
+
+ /**
+ * Subclass `base` by creating proxy functions
+ */
+ function _subclassObject(tree, base, extension, extName) {
+ // $.ui.fancytree.debug("_subclassObject", tree, base, extension, extName);
+ for (var attrName in extension) {
+ if (typeof extension[attrName] === "function") {
+ if (typeof tree[attrName] === "function") {
+ // override existing method
+ tree[attrName] = _makeVirtualFunction(
+ attrName,
+ tree,
+ base,
+ extension,
+ extName
+ );
+ } else if (attrName.charAt(0) === "_") {
+ // Create private methods in tree.ext.EXTENSION namespace
+ tree.ext[extName][attrName] = _makeVirtualFunction(
+ attrName,
+ tree,
+ base,
+ extension,
+ extName
+ );
+ } else {
+ $.error(
+ "Could not override tree." +
+ attrName +
+ ". Use prefix '_' to create tree." +
+ extName +
+ "._" +
+ attrName
+ );
+ }
+ } else {
+ // Create member variables in tree.ext.EXTENSION namespace
+ if (attrName !== "options") {
+ tree.ext[extName][attrName] = extension[attrName];
+ }
+ }
+ }
+ }
+
+ function _getResolvedPromise(context, argArray) {
+ if (context === undefined) {
+ return $.Deferred(function () {
+ this.resolve();
+ }).promise();
+ }
+ return $.Deferred(function () {
+ this.resolveWith(context, argArray);
+ }).promise();
+ }
+
+ function _getRejectedPromise(context, argArray) {
+ if (context === undefined) {
+ return $.Deferred(function () {
+ this.reject();
+ }).promise();
+ }
+ return $.Deferred(function () {
+ this.rejectWith(context, argArray);
+ }).promise();
+ }
+
+ function _makeResolveFunc(deferred, context) {
+ return function () {
+ deferred.resolveWith(context);
+ };
+ }
+
+ function _getElementDataAsDict($el) {
+ // Evaluate 'data-NAME' attributes with special treatment for 'data-json'.
+ var d = $.extend({}, $el.data()),
+ json = d.json;
+
+ delete d.fancytree; // added to container by widget factory (old jQuery UI)
+ delete d.uiFancytree; // added to container by widget factory
+
+ if (json) {
+ delete d.json;
+ // <li data-json='...'> is already returned as object (http://api.jquery.com/data/#data-html5)
+ d = $.extend(d, json);
+ }
+ return d;
+ }
+
+ function _escapeTooltip(s) {
+ return ("" + s).replace(REX_TOOLTIP, function (s) {
+ return ENTITY_MAP[s];
+ });
+ }
+
+ // TODO: use currying
+ function _makeNodeTitleMatcher(s) {
+ s = s.toLowerCase();
+ return function (node) {
+ return node.title.toLowerCase().indexOf(s) >= 0;
+ };
+ }
+
+ function _makeNodeTitleStartMatcher(s) {
+ var reMatch = new RegExp("^" + s, "i");
+ return function (node) {
+ return reMatch.test(node.title);
+ };
+ }
+
+ /******************************************************************************
+ * FancytreeNode
+ */
+
+ /**
+ * Creates a new FancytreeNode
+ *
+ * @class FancytreeNode
+ * @classdesc A FancytreeNode represents the hierarchical data model and operations.
+ *
+ * @param {FancytreeNode} parent
+ * @param {NodeData} obj
+ *
+ * @property {Fancytree} tree The tree instance
+ * @property {FancytreeNode} parent The parent node
+ * @property {string} key Node id (must be unique inside the tree)
+ * @property {string} title Display name (may contain HTML)
+ * @property {object} data Contains all extra data that was passed on node creation
+ * @property {FancytreeNode[] | null | undefined} children Array of child nodes.<br>
+ * For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array
+ * to define a node that has no children.
+ * @property {boolean} expanded Use isExpanded(), setExpanded() to access this property.
+ * @property {string} extraClasses Additional CSS classes, added to the node's `<span>`.<br>
+ * Note: use `node.add/remove/toggleClass()` to modify.
+ * @property {boolean} folder Folder nodes have different default icons and click behavior.<br>
+ * Note: Also non-folders may have children.
+ * @property {string} statusNodeType null for standard nodes. Otherwise type of special system node: 'error', 'loading', 'nodata', or 'paging'.
+ * @property {boolean} lazy True if this node is loaded on demand, i.e. on first expansion.
+ * @property {boolean} selected Use isSelected(), setSelected() to access this property.
+ * @property {string} tooltip Alternative description used as hover popup
+ * @property {string} iconTooltip Description used as hover popup for icon. @since 2.27
+ * @property {string} type Node type, used with tree.types map. @since 2.27
+ */
+ function FancytreeNode(parent, obj) {
+ var i, l, name, cl;
+
+ this.parent = parent;
+ this.tree = parent.tree;
+ this.ul = null;
+ this.li = null; // <li id='key' ftnode=this> tag
+ this.statusNodeType = null; // if this is a temp. node to display the status of its parent
+ this._isLoading = false; // if this node itself is loading
+ this._error = null; // {message: '...'} if a load error occurred
+ this.data = {};
+
+ // TODO: merge this code with node.toDict()
+ // copy attributes from obj object
+ for (i = 0, l = NODE_ATTRS.length; i < l; i++) {
+ name = NODE_ATTRS[i];
+ this[name] = obj[name];
+ }
+ // unselectableIgnore and unselectableStatus imply unselectable
+ if (
+ this.unselectableIgnore != null ||
+ this.unselectableStatus != null
+ ) {
+ this.unselectable = true;
+ }
+ if (obj.hideCheckbox) {
+ $.error(
+ "'hideCheckbox' node option was removed in v2.23.0: use 'checkbox: false'"
+ );
+ }
+ // node.data += obj.data
+ if (obj.data) {
+ $.extend(this.data, obj.data);
+ }
+ // Copy all other attributes to this.data.NAME
+ for (name in obj) {
+ if (
+ !NODE_ATTR_MAP[name] &&
+ (this.tree.options.copyFunctionsToData ||
+ !_isFunction(obj[name])) &&
+ !NONE_NODE_DATA_MAP[name]
+ ) {
+ // node.data.NAME = obj.NAME
+ this.data[name] = obj[name];
+ }
+ }
+
+ // Fix missing key
+ if (this.key == null) {
+ // test for null OR undefined
+ if (this.tree.options.defaultKey) {
+ this.key = "" + this.tree.options.defaultKey(this);
+ _assert(this.key, "defaultKey() must return a unique key");
+ } else {
+ this.key = "_" + FT._nextNodeKey++;
+ }
+ } else {
+ this.key = "" + this.key; // Convert to string (#217)
+ }
+
+ // Fix tree.activeNode
+ // TODO: not elegant: we use obj.active as marker to set tree.activeNode
+ // when loading from a dictionary.
+ if (obj.active) {
+ _assert(
+ this.tree.activeNode === null,
+ "only one active node allowed"
+ );
+ this.tree.activeNode = this;
+ }
+ if (obj.selected) {
+ // #186
+ this.tree.lastSelectedNode = this;
+ }
+ // TODO: handle obj.focus = true
+
+ // Create child nodes
+ cl = obj.children;
+ if (cl) {
+ if (cl.length) {
+ this._setChildren(cl);
+ } else {
+ // if an empty array was passed for a lazy node, keep it, in order to mark it 'loaded'
+ this.children = this.lazy ? [] : null;
+ }
+ } else {
+ this.children = null;
+ }
+ // Add to key/ref map (except for root node)
+ // if( parent ) {
+ this.tree._callHook("treeRegisterNode", this.tree, true, this);
+ // }
+ }
+
+ FancytreeNode.prototype = /** @lends FancytreeNode# */ {
+ /* Return the direct child FancytreeNode with a given key, index. */
+ _findDirectChild: function (ptr) {
+ var i,
+ l,
+ cl = this.children;
+
+ if (cl) {
+ if (typeof ptr === "string") {
+ for (i = 0, l = cl.length; i < l; i++) {
+ if (cl[i].key === ptr) {
+ return cl[i];
+ }
+ }
+ } else if (typeof ptr === "number") {
+ return this.children[ptr];
+ } else if (ptr.parent === this) {
+ return ptr;
+ }
+ }
+ return null;
+ },
+ // TODO: activate()
+ // TODO: activateSilently()
+ /* Internal helper called in recursive addChildren sequence.*/
+ _setChildren: function (children) {
+ _assert(
+ children && (!this.children || this.children.length === 0),
+ "only init supported"
+ );
+ this.children = [];
+ for (var i = 0, l = children.length; i < l; i++) {
+ this.children.push(new FancytreeNode(this, children[i]));
+ }
+ this.tree._callHook(
+ "treeStructureChanged",
+ this.tree,
+ "setChildren"
+ );
+ },
+ /**
+ * Append (or insert) a list of child nodes.
+ *
+ * @param {NodeData[]} children array of child node definitions (also single child accepted)
+ * @param {FancytreeNode | string | Integer} [insertBefore] child node (or key or index of such).
+ * If omitted, the new children are appended.
+ * @returns {FancytreeNode} first child added
+ *
+ * @see FancytreeNode#applyPatch
+ */
+ addChildren: function (children, insertBefore) {
+ var i,
+ l,
+ pos,
+ origFirstChild = this.getFirstChild(),
+ origLastChild = this.getLastChild(),
+ firstNode = null,
+ nodeList = [];
+
+ if ($.isPlainObject(children)) {
+ children = [children];
+ }
+ if (!this.children) {
+ this.children = [];
+ }
+ for (i = 0, l = children.length; i < l; i++) {
+ nodeList.push(new FancytreeNode(this, children[i]));
+ }
+ firstNode = nodeList[0];
+ if (insertBefore == null) {
+ this.children = this.children.concat(nodeList);
+ } else {
+ // Returns null if insertBefore is not a direct child:
+ insertBefore = this._findDirectChild(insertBefore);
+ pos = $.inArray(insertBefore, this.children);
+ _assert(pos >= 0, "insertBefore must be an existing child");
+ // insert nodeList after children[pos]
+ this.children.splice.apply(
+ this.children,
+ [pos, 0].concat(nodeList)
+ );
+ }
+ if (origFirstChild && !insertBefore) {
+ // #708: Fast path -- don't render every child of root, just the new ones!
+ // #723, #729: but only if it's appended to an existing child list
+ for (i = 0, l = nodeList.length; i < l; i++) {
+ nodeList[i].render(); // New nodes were never rendered before
+ }
+ // Adjust classes where status may have changed
+ // Has a first child
+ if (origFirstChild !== this.getFirstChild()) {
+ // Different first child -- recompute classes
+ origFirstChild.renderStatus();
+ }
+ if (origLastChild !== this.getLastChild()) {
+ // Different last child -- recompute classes
+ origLastChild.renderStatus();
+ }
+ } else if (!this.parent || this.parent.ul || this.tr) {
+ // render if the parent was rendered (or this is a root node)
+ this.render();
+ }
+ if (this.tree.options.selectMode === 3) {
+ this.fixSelection3FromEndNodes();
+ }
+ this.triggerModifyChild(
+ "add",
+ nodeList.length === 1 ? nodeList[0] : null
+ );
+ return firstNode;
+ },
+ /**
+ * Add class to node's span tag and to .extraClasses.
+ *
+ * @param {string} className class name
+ *
+ * @since 2.17
+ */
+ addClass: function (className) {
+ return this.toggleClass(className, true);
+ },
+ /**
+ * Append or prepend a node, or append a child node.
+ *
+ * This a convenience function that calls addChildren()
+ *
+ * @param {NodeData} node node definition
+ * @param {string} [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')
+ * @returns {FancytreeNode} new node
+ */
+ addNode: function (node, mode) {
+ if (mode === undefined || mode === "over") {
+ mode = "child";
+ }
+ switch (mode) {
+ case "after":
+ return this.getParent().addChildren(
+ node,
+ this.getNextSibling()
+ );
+ case "before":
+ return this.getParent().addChildren(node, this);
+ case "firstChild":
+ // Insert before the first child if any
+ var insertBefore = this.children ? this.children[0] : null;
+ return this.addChildren(node, insertBefore);
+ case "child":
+ case "over":
+ return this.addChildren(node);
+ }
+ _assert(false, "Invalid mode: " + mode);
+ },
+ /**Add child status nodes that indicate 'More...', etc.
+ *
+ * This also maintains the node's `partload` property.
+ * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.
+ * @param {string} [mode='child'] 'child'|firstChild'
+ * @since 2.15
+ */
+ addPagingNode: function (node, mode) {
+ var i, n;
+
+ mode = mode || "child";
+ if (node === false) {
+ for (i = this.children.length - 1; i >= 0; i--) {
+ n = this.children[i];
+ if (n.statusNodeType === "paging") {
+ this.removeChild(n);
+ }
+ }
+ this.partload = false;
+ return;
+ }
+ node = $.extend(
+ {
+ title: this.tree.options.strings.moreData,
+ statusNodeType: "paging",
+ icon: false,
+ },
+ node
+ );
+ this.partload = true;
+ return this.addNode(node, mode);
+ },
+ /**
+ * Append new node after this.
+ *
+ * This a convenience function that calls addNode(node, 'after')
+ *
+ * @param {NodeData} node node definition
+ * @returns {FancytreeNode} new node
+ */
+ appendSibling: function (node) {
+ return this.addNode(node, "after");
+ },
+ /**
+ * (experimental) Apply a modification (or navigation) operation.
+ *
+ * @param {string} cmd
+ * @param {object} [opts]
+ * @see Fancytree#applyCommand
+ * @since 2.32
+ */
+ applyCommand: function (cmd, opts) {
+ return this.tree.applyCommand(cmd, this, opts);
+ },
+ /**
+ * Modify existing child nodes.
+ *
+ * @param {NodePatch} patch
+ * @returns {$.Promise}
+ * @see FancytreeNode#addChildren
+ */
+ applyPatch: function (patch) {
+ // patch [key, null] means 'remove'
+ if (patch === null) {
+ this.remove();
+ return _getResolvedPromise(this);
+ }
+ // TODO: make sure that root node is not collapsed or modified
+ // copy (most) attributes to node.ATTR or node.data.ATTR
+ var name,
+ promise,
+ v,
+ IGNORE_MAP = { children: true, expanded: true, parent: true }; // TODO: should be global
+
+ for (name in patch) {
+ if (_hasProp(patch, name)) {
+ v = patch[name];
+ if (!IGNORE_MAP[name] && !_isFunction(v)) {
+ if (NODE_ATTR_MAP[name]) {
+ this[name] = v;
+ } else {
+ this.data[name] = v;
+ }
+ }
+ }
+ }
+ // Remove and/or create children
+ if (_hasProp(patch, "children")) {
+ this.removeChildren();
+ if (patch.children) {
+ // only if not null and not empty list
+ // TODO: addChildren instead?
+ this._setChildren(patch.children);
+ }
+ // TODO: how can we APPEND or INSERT child nodes?
+ }
+ if (this.isVisible()) {
+ this.renderTitle();
+ this.renderStatus();
+ }
+ // Expand collapse (final step, since this may be async)
+ if (_hasProp(patch, "expanded")) {
+ promise = this.setExpanded(patch.expanded);
+ } else {
+ promise = _getResolvedPromise(this);
+ }
+ return promise;
+ },
+ /** Collapse all sibling nodes.
+ * @returns {$.Promise}
+ */
+ collapseSiblings: function () {
+ return this.tree._callHook("nodeCollapseSiblings", this);
+ },
+ /** Copy this node as sibling or child of `node`.
+ *
+ * @param {FancytreeNode} node source node
+ * @param {string} [mode=child] 'before' | 'after' | 'child'
+ * @param {Function} [map] callback function(NodeData, FancytreeNode) that could modify the new node
+ * @returns {FancytreeNode} new
+ */
+ copyTo: function (node, mode, map) {
+ return node.addNode(this.toDict(true, map), mode);
+ },
+ /** Count direct and indirect children.
+ *
+ * @param {boolean} [deep=true] pass 'false' to only count direct children
+ * @returns {int} number of child nodes
+ */
+ countChildren: function (deep) {
+ var cl = this.children,
+ i,
+ l,
+ n;
+ if (!cl) {
+ return 0;
+ }
+ n = cl.length;
+ if (deep !== false) {
+ for (i = 0, l = n; i < l; i++) {
+ n += cl[i].countChildren();
+ }
+ }
+ return n;
+ },
+ // TODO: deactivate()
+ /** Write to browser console if debugLevel >= 4 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ debug: function (msg) {
+ if (this.tree.options.debugLevel >= 4) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("log", arguments);
+ }
+ },
+ /** Deprecated.
+ * @deprecated since 2014-02-16. Use resetLazy() instead.
+ */
+ discard: function () {
+ this.warn(
+ "FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."
+ );
+ return this.resetLazy();
+ },
+ /** Remove DOM elements for all descendents. May be called on .collapse event
+ * to keep the DOM small.
+ * @param {boolean} [includeSelf=false]
+ */
+ discardMarkup: function (includeSelf) {
+ var fn = includeSelf ? "nodeRemoveMarkup" : "nodeRemoveChildMarkup";
+ this.tree._callHook(fn, this);
+ },
+ /** Write error to browser console if debugLevel >= 1 (prepending tree info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ error: function (msg) {
+ if (this.tree.options.debugLevel >= 1) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("error", arguments);
+ }
+ },
+ /**Find all nodes that match condition (excluding self).
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode[]} array of nodes (may be empty)
+ */
+ findAll: function (match) {
+ match = _isFunction(match) ? match : _makeNodeTitleMatcher(match);
+ var res = [];
+ this.visit(function (n) {
+ if (match(n)) {
+ res.push(n);
+ }
+ });
+ return res;
+ },
+ /**Find first node that matches condition (excluding self).
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode} matching node or null
+ * @see FancytreeNode#findAll
+ */
+ findFirst: function (match) {
+ match = _isFunction(match) ? match : _makeNodeTitleMatcher(match);
+ var res = null;
+ this.visit(function (n) {
+ if (match(n)) {
+ res = n;
+ return false;
+ }
+ });
+ return res;
+ },
+ /** Find a node relative to self.
+ *
+ * @param {number|string} where The keyCode that would normally trigger this move,
+ * or a keyword ('down', 'first', 'last', 'left', 'parent', 'right', 'up').
+ * @returns {FancytreeNode}
+ * @since v2.31
+ */
+ findRelatedNode: function (where, includeHidden) {
+ return this.tree.findRelatedNode(this, where, includeHidden);
+ },
+ /* Apply selection state (internal use only) */
+ _changeSelectStatusAttrs: function (state) {
+ var changed = false,
+ opts = this.tree.options,
+ unselectable = FT.evalOption(
+ "unselectable",
+ this,
+ this,
+ opts,
+ false
+ ),
+ unselectableStatus = FT.evalOption(
+ "unselectableStatus",
+ this,
+ this,
+ opts,
+ undefined
+ );
+
+ if (unselectable && unselectableStatus != null) {
+ state = unselectableStatus;
+ }
+ switch (state) {
+ case false:
+ changed = this.selected || this.partsel;
+ this.selected = false;
+ this.partsel = false;
+ break;
+ case true:
+ changed = !this.selected || !this.partsel;
+ this.selected = true;
+ this.partsel = true;
+ break;
+ case undefined:
+ changed = this.selected || !this.partsel;
+ this.selected = false;
+ this.partsel = true;
+ break;
+ default:
+ _assert(false, "invalid state: " + state);
+ }
+ // this.debug("fixSelection3AfterLoad() _changeSelectStatusAttrs()", state, changed);
+ if (changed) {
+ this.renderStatus();
+ }
+ return changed;
+ },
+ /**
+ * Fix selection status, after this node was (de)selected in multi-hier mode.
+ * This includes (de)selecting all children.
+ */
+ fixSelection3AfterClick: function (callOpts) {
+ var flag = this.isSelected();
+
+ // this.debug("fixSelection3AfterClick()");
+
+ this.visit(function (node) {
+ node._changeSelectStatusAttrs(flag);
+ if (node.radiogroup) {
+ // #931: don't (de)select this branch
+ return "skip";
+ }
+ });
+ this.fixSelection3FromEndNodes(callOpts);
+ },
+ /**
+ * Fix selection status for multi-hier mode.
+ * Only end-nodes are considered to update the descendants branch and parents.
+ * Should be called after this node has loaded new children or after
+ * children have been modified using the API.
+ */
+ fixSelection3FromEndNodes: function (callOpts) {
+ var opts = this.tree.options;
+
+ // this.debug("fixSelection3FromEndNodes()");
+ _assert(opts.selectMode === 3, "expected selectMode 3");
+
+ // Visit all end nodes and adjust their parent's `selected` and `partsel`
+ // attributes. Return selection state true, false, or undefined.
+ function _walk(node) {
+ var i,
+ l,
+ child,
+ s,
+ state,
+ allSelected,
+ someSelected,
+ unselIgnore,
+ unselState,
+ children = node.children;
+
+ if (children && children.length) {
+ // check all children recursively
+ allSelected = true;
+ someSelected = false;
+
+ for (i = 0, l = children.length; i < l; i++) {
+ child = children[i];
+ // the selection state of a node is not relevant; we need the end-nodes
+ s = _walk(child);
+ // if( !child.unselectableIgnore ) {
+ unselIgnore = FT.evalOption(
+ "unselectableIgnore",
+ child,
+ child,
+ opts,
+ false
+ );
+ if (!unselIgnore) {
+ if (s !== false) {
+ someSelected = true;
+ }
+ if (s !== true) {
+ allSelected = false;
+ }
+ }
+ }
+ // eslint-disable-next-line no-nested-ternary
+ state = allSelected
+ ? true
+ : someSelected
+ ? undefined
+ : false;
+ } else {
+ // This is an end-node: simply report the status
+ unselState = FT.evalOption(
+ "unselectableStatus",
+ node,
+ node,
+ opts,
+ undefined
+ );
+ state = unselState == null ? !!node.selected : !!unselState;
+ }
+ // #939: Keep a `partsel` flag that was explicitly set on a lazy node
+ if (
+ node.partsel &&
+ !node.selected &&
+ node.lazy &&
+ node.children == null
+ ) {
+ state = undefined;
+ }
+ node._changeSelectStatusAttrs(state);
+ return state;
+ }
+ _walk(this);
+
+ // Update parent's state
+ this.visitParents(function (node) {
+ var i,
+ l,
+ child,
+ state,
+ unselIgnore,
+ unselState,
+ children = node.children,
+ allSelected = true,
+ someSelected = false;
+
+ for (i = 0, l = children.length; i < l; i++) {
+ child = children[i];
+ unselIgnore = FT.evalOption(
+ "unselectableIgnore",
+ child,
+ child,
+ opts,
+ false
+ );
+ if (!unselIgnore) {
+ unselState = FT.evalOption(
+ "unselectableStatus",
+ child,
+ child,
+ opts,
+ undefined
+ );
+ state =
+ unselState == null
+ ? !!child.selected
+ : !!unselState;
+ // When fixing the parents, we trust the sibling status (i.e.
+ // we don't recurse)
+ if (state || child.partsel) {
+ someSelected = true;
+ }
+ if (!state) {
+ allSelected = false;
+ }
+ }
+ }
+ // eslint-disable-next-line no-nested-ternary
+ state = allSelected ? true : someSelected ? undefined : false;
+ node._changeSelectStatusAttrs(state);
+ });
+ },
+ // TODO: focus()
+ /**
+ * Update node data. If dict contains 'children', then also replace
+ * the hole sub tree.
+ * @param {NodeData} dict
+ *
+ * @see FancytreeNode#addChildren
+ * @see FancytreeNode#applyPatch
+ */
+ fromDict: function (dict) {
+ // copy all other attributes to this.data.xxx
+ for (var name in dict) {
+ if (NODE_ATTR_MAP[name]) {
+ // node.NAME = dict.NAME
+ this[name] = dict[name];
+ } else if (name === "data") {
+ // node.data += dict.data
+ $.extend(this.data, dict.data);
+ } else if (
+ !_isFunction(dict[name]) &&
+ !NONE_NODE_DATA_MAP[name]
+ ) {
+ // node.data.NAME = dict.NAME
+ this.data[name] = dict[name];
+ }
+ }
+ if (dict.children) {
+ // recursively set children and render
+ this.removeChildren();
+ this.addChildren(dict.children);
+ }
+ this.renderTitle();
+ /*
+ var children = dict.children;
+ if(children === undefined){
+ this.data = $.extend(this.data, dict);
+ this.render();
+ return;
+ }
+ dict = $.extend({}, dict);
+ dict.children = undefined;
+ this.data = $.extend(this.data, dict);
+ this.removeChildren();
+ this.addChild(children);
+ */
+ },
+ /** Return the list of child nodes (undefined for unexpanded lazy nodes).
+ * @returns {FancytreeNode[] | undefined}
+ */
+ getChildren: function () {
+ if (this.hasChildren() === undefined) {
+ // TODO: only required for lazy nodes?
+ return undefined; // Lazy node: unloaded, currently loading, or load error
+ }
+ return this.children;
+ },
+ /** Return the first child node or null.
+ * @returns {FancytreeNode | null}
+ */
+ getFirstChild: function () {
+ return this.children ? this.children[0] : null;
+ },
+ /** Return the 0-based child index.
+ * @returns {int}
+ */
+ getIndex: function () {
+ // return this.parent.children.indexOf(this);
+ return $.inArray(this, this.parent.children); // indexOf doesn't work in IE7
+ },
+ /** Return the hierarchical child index (1-based, e.g. '3.2.4').
+ * @param {string} [separator="."]
+ * @param {int} [digits=1]
+ * @returns {string}
+ */
+ getIndexHier: function (separator, digits) {
+ separator = separator || ".";
+ var s,
+ res = [];
+ $.each(this.getParentList(false, true), function (i, o) {
+ s = "" + (o.getIndex() + 1);
+ if (digits) {
+ // prepend leading zeroes
+ s = ("0000000" + s).substr(-digits);
+ }
+ res.push(s);
+ });
+ return res.join(separator);
+ },
+ /** Return the parent keys separated by options.keyPathSeparator, e.g. "/id_1/id_17/id_32".
+ *
+ * (Unlike `node.getPath()`, this method prepends a "/" and inverts the first argument.)
+ *
+ * @see FancytreeNode#getPath
+ * @param {boolean} [excludeSelf=false]
+ * @returns {string}
+ */
+ getKeyPath: function (excludeSelf) {
+ var sep = this.tree.options.keyPathSeparator;
+
+ return sep + this.getPath(!excludeSelf, "key", sep);
+ },
+ /** Return the last child of this node or null.
+ * @returns {FancytreeNode | null}
+ */
+ getLastChild: function () {
+ return this.children
+ ? this.children[this.children.length - 1]
+ : null;
+ },
+ /** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... .
+ * @returns {int}
+ */
+ getLevel: function () {
+ var level = 0,
+ dtn = this.parent;
+ while (dtn) {
+ level++;
+ dtn = dtn.parent;
+ }
+ return level;
+ },
+ /** Return the successor node (under the same parent) or null.
+ * @returns {FancytreeNode | null}
+ */
+ getNextSibling: function () {
+ // TODO: use indexOf, if available: (not in IE6)
+ if (this.parent) {
+ var i,
+ l,
+ ac = this.parent.children;
+
+ for (i = 0, l = ac.length - 1; i < l; i++) {
+ // up to length-2, so next(last) = null
+ if (ac[i] === this) {
+ return ac[i + 1];
+ }
+ }
+ }
+ return null;
+ },
+ /** Return the parent node (null for the system root node).
+ * @returns {FancytreeNode | null}
+ */
+ getParent: function () {
+ // TODO: return null for top-level nodes?
+ return this.parent;
+ },
+ /** Return an array of all parent nodes (top-down).
+ * @param {boolean} [includeRoot=false] Include the invisible system root node.
+ * @param {boolean} [includeSelf=false] Include the node itself.
+ * @returns {FancytreeNode[]}
+ */
+ getParentList: function (includeRoot, includeSelf) {
+ var l = [],
+ dtn = includeSelf ? this : this.parent;
+ while (dtn) {
+ if (includeRoot || dtn.parent) {
+ l.unshift(dtn);
+ }
+ dtn = dtn.parent;
+ }
+ return l;
+ },
+ /** Return a string representing the hierachical node path, e.g. "a/b/c".
+ * @param {boolean} [includeSelf=true]
+ * @param {string | function} [part="title"] node property name or callback
+ * @param {string} [separator="/"]
+ * @returns {string}
+ * @since v2.31
+ */
+ getPath: function (includeSelf, part, separator) {
+ includeSelf = includeSelf !== false;
+ part = part || "title";
+ separator = separator || "/";
+
+ var val,
+ path = [],
+ isFunc = _isFunction(part);
+
+ this.visitParents(function (n) {
+ if (n.parent) {
+ val = isFunc ? part(n) : n[part];
+ path.unshift(val);
+ }
+ }, includeSelf);
+ return path.join(separator);
+ },
+ /** Return the predecessor node (under the same parent) or null.
+ * @returns {FancytreeNode | null}
+ */
+ getPrevSibling: function () {
+ if (this.parent) {
+ var i,
+ l,
+ ac = this.parent.children;
+
+ for (i = 1, l = ac.length; i < l; i++) {
+ // start with 1, so prev(first) = null
+ if (ac[i] === this) {
+ return ac[i - 1];
+ }
+ }
+ }
+ return null;
+ },
+ /**
+ * Return an array of selected descendant nodes.
+ * @param {boolean} [stopOnParents=false] only return the topmost selected
+ * node (useful with selectMode 3)
+ * @returns {FancytreeNode[]}
+ */
+ getSelectedNodes: function (stopOnParents) {
+ var nodeList = [];
+ this.visit(function (node) {
+ if (node.selected) {
+ nodeList.push(node);
+ if (stopOnParents === true) {
+ return "skip"; // stop processing this branch
+ }
+ }
+ });
+ return nodeList;
+ },
+ /** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded).
+ * @returns {boolean | undefined}
+ */
+ hasChildren: function () {
+ if (this.lazy) {
+ if (this.children == null) {
+ // null or undefined: Not yet loaded
+ return undefined;
+ } else if (this.children.length === 0) {
+ // Loaded, but response was empty
+ return false;
+ } else if (
+ this.children.length === 1 &&
+ this.children[0].isStatusNode()
+ ) {
+ // Currently loading or load error
+ return undefined;
+ }
+ return true;
+ }
+ return !!(this.children && this.children.length);
+ },
+ /**
+ * Return true if node has `className` defined in .extraClasses.
+ *
+ * @param {string} className class name (separate multiple classes by space)
+ * @returns {boolean}
+ *
+ * @since 2.32
+ */
+ hasClass: function (className) {
+ return (
+ (" " + (this.extraClasses || "") + " ").indexOf(
+ " " + className + " "
+ ) >= 0
+ );
+ },
+ /** Return true if node has keyboard focus.
+ * @returns {boolean}
+ */
+ hasFocus: function () {
+ return this.tree.hasFocus() && this.tree.focusNode === this;
+ },
+ /** Write to browser console if debugLevel >= 3 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ info: function (msg) {
+ if (this.tree.options.debugLevel >= 3) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("info", arguments);
+ }
+ },
+ /** Return true if node is active (see also FancytreeNode#isSelected).
+ * @returns {boolean}
+ */
+ isActive: function () {
+ return this.tree.activeNode === this;
+ },
+ /** Return true if node is vertically below `otherNode`, i.e. rendered in a subsequent row.
+ * @param {FancytreeNode} otherNode
+ * @returns {boolean}
+ * @since 2.28
+ */
+ isBelowOf: function (otherNode) {
+ return this.getIndexHier(".", 5) > otherNode.getIndexHier(".", 5);
+ },
+ /** Return true if node is a direct child of otherNode.
+ * @param {FancytreeNode} otherNode
+ * @returns {boolean}
+ */
+ isChildOf: function (otherNode) {
+ return this.parent && this.parent === otherNode;
+ },
+ /** Return true, if node is a direct or indirect sub node of otherNode.
+ * @param {FancytreeNode} otherNode
+ * @returns {boolean}
+ */
+ isDescendantOf: function (otherNode) {
+ if (!otherNode || otherNode.tree !== this.tree) {
+ return false;
+ }
+ var p = this.parent;
+ while (p) {
+ if (p === otherNode) {
+ return true;
+ }
+ if (p === p.parent) {
+ $.error("Recursive parent link: " + p);
+ }
+ p = p.parent;
+ }
+ return false;
+ },
+ /** Return true if node is expanded.
+ * @returns {boolean}
+ */
+ isExpanded: function () {
+ return !!this.expanded;
+ },
+ /** Return true if node is the first node of its parent's children.
+ * @returns {boolean}
+ */
+ isFirstSibling: function () {
+ var p = this.parent;
+ return !p || p.children[0] === this;
+ },
+ /** Return true if node is a folder, i.e. has the node.folder attribute set.
+ * @returns {boolean}
+ */
+ isFolder: function () {
+ return !!this.folder;
+ },
+ /** Return true if node is the last node of its parent's children.
+ * @returns {boolean}
+ */
+ isLastSibling: function () {
+ var p = this.parent;
+ return !p || p.children[p.children.length - 1] === this;
+ },
+ /** Return true if node is lazy (even if data was already loaded)
+ * @returns {boolean}
+ */
+ isLazy: function () {
+ return !!this.lazy;
+ },
+ /** Return true if node is lazy and loaded. For non-lazy nodes always return true.
+ * @returns {boolean}
+ */
+ isLoaded: function () {
+ return !this.lazy || this.hasChildren() !== undefined; // Also checks if the only child is a status node
+ },
+ /** Return true if children are currently beeing loaded, i.e. a Ajax request is pending.
+ * @returns {boolean}
+ */
+ isLoading: function () {
+ return !!this._isLoading;
+ },
+ /*
+ * @deprecated since v2.4.0: Use isRootNode() instead
+ */
+ isRoot: function () {
+ return this.isRootNode();
+ },
+ /** Return true if node is partially selected (tri-state).
+ * @returns {boolean}
+ * @since 2.23
+ */
+ isPartsel: function () {
+ return !this.selected && !!this.partsel;
+ },
+ /** (experimental) Return true if this is partially loaded.
+ * @returns {boolean}
+ * @since 2.15
+ */
+ isPartload: function () {
+ return !!this.partload;
+ },
+ /** Return true if this is the (invisible) system root node.
+ * @returns {boolean}
+ * @since 2.4
+ */
+ isRootNode: function () {
+ return this.tree.rootNode === this;
+ },
+ /** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive).
+ * @returns {boolean}
+ */
+ isSelected: function () {
+ return !!this.selected;
+ },
+ /** Return true if this node is a temporarily generated system node like
+ * 'loading', 'paging', or 'error' (node.statusNodeType contains the type).
+ * @returns {boolean}
+ */
+ isStatusNode: function () {
+ return !!this.statusNodeType;
+ },
+ /** Return true if this node is a status node of type 'paging'.
+ * @returns {boolean}
+ * @since 2.15
+ */
+ isPagingNode: function () {
+ return this.statusNodeType === "paging";
+ },
+ /** Return true if this a top level node, i.e. a direct child of the (invisible) system root node.
+ * @returns {boolean}
+ * @since 2.4
+ */
+ isTopLevel: function () {
+ return this.tree.rootNode === this.parent;
+ },
+ /** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false.
+ * @returns {boolean}
+ */
+ isUndefined: function () {
+ return this.hasChildren() === undefined; // also checks if the only child is a status node
+ },
+ /** Return true if all parent nodes are expanded. Note: this does not check
+ * whether the node is scrolled into the visible part of the screen.
+ * @returns {boolean}
+ */
+ isVisible: function () {
+ var i,
+ l,
+ n,
+ hasFilter = this.tree.enableFilter,
+ parents = this.getParentList(false, false);
+
+ // TODO: check $(n.span).is(":visible")
+ // i.e. return false for nodes (but not parents) that are hidden
+ // by a filter
+ if (hasFilter && !this.match && !this.subMatchCount) {
+ // this.debug( "isVisible: HIDDEN (" + hasFilter + ", " + this.match + ", " + this.match + ")" );
+ return false;
+ }
+
+ for (i = 0, l = parents.length; i < l; i++) {
+ n = parents[i];
+
+ if (!n.expanded) {
+ // this.debug("isVisible: HIDDEN (parent collapsed)");
+ return false;
+ }
+ // if (hasFilter && !n.match && !n.subMatchCount) {
+ // this.debug("isVisible: HIDDEN (" + hasFilter + ", " + this.match + ", " + this.match + ")");
+ // return false;
+ // }
+ }
+ // this.debug("isVisible: VISIBLE");
+ return true;
+ },
+ /** Deprecated.
+ * @deprecated since 2014-02-16: use load() instead.
+ */
+ lazyLoad: function (discard) {
+ $.error(
+ "FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead."
+ );
+ },
+ /**
+ * Load all children of a lazy node if neccessary. The <i>expanded</i> state is maintained.
+ * @param {boolean} [forceReload=false] Pass true to discard any existing nodes before. Otherwise this method does nothing if the node was already loaded.
+ * @returns {$.Promise}
+ */
+ load: function (forceReload) {
+ var res,
+ source,
+ self = this,
+ wasExpanded = this.isExpanded();
+
+ _assert(this.isLazy(), "load() requires a lazy node");
+ // _assert( forceReload || this.isUndefined(), "Pass forceReload=true to re-load a lazy node" );
+ if (!forceReload && !this.isUndefined()) {
+ return _getResolvedPromise(this);
+ }
+ if (this.isLoaded()) {
+ this.resetLazy(); // also collapses
+ }
+ // This method is also called by setExpanded() and loadKeyPath(), so we
+ // have to avoid recursion.
+ source = this.tree._triggerNodeEvent("lazyLoad", this);
+ if (source === false) {
+ // #69
+ return _getResolvedPromise(this);
+ }
+ _assert(
+ typeof source !== "boolean",
+ "lazyLoad event must return source in data.result"
+ );
+ res = this.tree._callHook("nodeLoadChildren", this, source);
+ if (wasExpanded) {
+ this.expanded = true;
+ res.always(function () {
+ self.render();
+ });
+ } else {
+ res.always(function () {
+ self.renderStatus(); // fix expander icon to 'loaded'
+ });
+ }
+ return res;
+ },
+ /** Expand all parents and optionally scroll into visible area as neccessary.
+ * Promise is resolved, when lazy loading and animations are done.
+ * @param {object} [opts] passed to `setExpanded()`.
+ * Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
+ * @returns {$.Promise}
+ */
+ makeVisible: function (opts) {
+ var i,
+ self = this,
+ deferreds = [],
+ dfd = new $.Deferred(),
+ parents = this.getParentList(false, false),
+ len = parents.length,
+ effects = !(opts && opts.noAnimation === true),
+ scroll = !(opts && opts.scrollIntoView === false);
+
+ // Expand bottom-up, so only the top node is animated
+ for (i = len - 1; i >= 0; i--) {
+ // self.debug("pushexpand" + parents[i]);
+ deferreds.push(parents[i].setExpanded(true, opts));
+ }
+ $.when.apply($, deferreds).done(function () {
+ // All expands have finished
+ // self.debug("expand DONE", scroll);
+ if (scroll) {
+ self.scrollIntoView(effects).done(function () {
+ // self.debug("scroll DONE");
+ dfd.resolve();
+ });
+ } else {
+ dfd.resolve();
+ }
+ });
+ return dfd.promise();
+ },
+ /** Move this node to targetNode.
+ * @param {FancytreeNode} targetNode
+ * @param {string} mode <pre>
+ * 'child': append this node as last child of targetNode.
+ * This is the default. To be compatble with the D'n'd
+ * hitMode, we also accept 'over'.
+ * 'firstChild': add this node as first child of targetNode.
+ * 'before': add this node as sibling before targetNode.
+ * 'after': add this node as sibling after targetNode.</pre>
+ * @param {function} [map] optional callback(FancytreeNode) to allow modifcations
+ */
+ moveTo: function (targetNode, mode, map) {
+ if (mode === undefined || mode === "over") {
+ mode = "child";
+ } else if (mode === "firstChild") {
+ if (targetNode.children && targetNode.children.length) {
+ mode = "before";
+ targetNode = targetNode.children[0];
+ } else {
+ mode = "child";
+ }
+ }
+ var pos,
+ tree = this.tree,
+ prevParent = this.parent,
+ targetParent =
+ mode === "child" ? targetNode : targetNode.parent;
+
+ if (this === targetNode) {
+ return;
+ } else if (!this.parent) {
+ $.error("Cannot move system root");
+ } else if (targetParent.isDescendantOf(this)) {
+ $.error("Cannot move a node to its own descendant");
+ }
+ if (targetParent !== prevParent) {
+ prevParent.triggerModifyChild("remove", this);
+ }
+ // Unlink this node from current parent
+ if (this.parent.children.length === 1) {
+ if (this.parent === targetParent) {
+ return; // #258
+ }
+ this.parent.children = this.parent.lazy ? [] : null;
+ this.parent.expanded = false;
+ } else {
+ pos = $.inArray(this, this.parent.children);
+ _assert(pos >= 0, "invalid source parent");
+ this.parent.children.splice(pos, 1);
+ }
+ // Remove from source DOM parent
+ // if(this.parent.ul){
+ // this.parent.ul.removeChild(this.li);
+ // }
+
+ // Insert this node to target parent's child list
+ this.parent = targetParent;
+ if (targetParent.hasChildren()) {
+ switch (mode) {
+ case "child":
+ // Append to existing target children
+ targetParent.children.push(this);
+ break;
+ case "before":
+ // Insert this node before target node
+ pos = $.inArray(targetNode, targetParent.children);
+ _assert(pos >= 0, "invalid target parent");
+ targetParent.children.splice(pos, 0, this);
+ break;
+ case "after":
+ // Insert this node after target node
+ pos = $.inArray(targetNode, targetParent.children);
+ _assert(pos >= 0, "invalid target parent");
+ targetParent.children.splice(pos + 1, 0, this);
+ break;
+ default:
+ $.error("Invalid mode " + mode);
+ }
+ } else {
+ targetParent.children = [this];
+ }
+ // Parent has no <ul> tag yet:
+ // if( !targetParent.ul ) {
+ // // This is the parent's first child: create UL tag
+ // // (Hidden, because it will be
+ // targetParent.ul = document.createElement("ul");
+ // targetParent.ul.style.display = "none";
+ // targetParent.li.appendChild(targetParent.ul);
+ // }
+ // // Issue 319: Add to target DOM parent (only if node was already rendered(expanded))
+ // if(this.li){
+ // targetParent.ul.appendChild(this.li);
+ // }
+
+ // Let caller modify the nodes
+ if (map) {
+ targetNode.visit(map, true);
+ }
+ if (targetParent === prevParent) {
+ targetParent.triggerModifyChild("move", this);
+ } else {
+ // prevParent.triggerModifyChild("remove", this);
+ targetParent.triggerModifyChild("add", this);
+ }
+ // Handle cross-tree moves
+ if (tree !== targetNode.tree) {
+ // Fix node.tree for all source nodes
+ // _assert(false, "Cross-tree move is not yet implemented.");
+ this.warn("Cross-tree moveTo is experimental!");
+ this.visit(function (n) {
+ // TODO: fix selection state and activation, ...
+ n.tree = targetNode.tree;
+ }, true);
+ }
+
+ // A collaposed node won't re-render children, so we have to remove it manually
+ // if( !targetParent.expanded ){
+ // prevParent.ul.removeChild(this.li);
+ // }
+ tree._callHook("treeStructureChanged", tree, "moveTo");
+
+ // Update HTML markup
+ if (!prevParent.isDescendantOf(targetParent)) {
+ prevParent.render();
+ }
+ if (
+ !targetParent.isDescendantOf(prevParent) &&
+ targetParent !== prevParent
+ ) {
+ targetParent.render();
+ }
+ // TODO: fix selection state
+ // TODO: fix active state
+
+ /*
+ var tree = this.tree;
+ var opts = tree.options;
+ var pers = tree.persistence;
+
+ // Always expand, if it's below minExpandLevel
+ // tree.logDebug ("%s._addChildNode(%o), l=%o", this, ftnode, ftnode.getLevel());
+ if ( opts.minExpandLevel >= ftnode.getLevel() ) {
+ // tree.logDebug ("Force expand for %o", ftnode);
+ this.bExpanded = true;
+ }
+
+ // In multi-hier mode, update the parents selection state
+ // DT issue #82: only if not initializing, because the children may not exist yet
+ // if( !ftnode.data.isStatusNode() && opts.selectMode==3 && !isInitializing )
+ // ftnode._fixSelectionState();
+
+ // In multi-hier mode, update the parents selection state
+ if( ftnode.bSelected && opts.selectMode==3 ) {
+ var p = this;
+ while( p ) {
+ if( !p.hasSubSel )
+ p._setSubSel(true);
+ p = p.parent;
+ }
+ }
+ // render this node and the new child
+ if ( tree.bEnableUpdate )
+ this.render();
+ return ftnode;
+ */
+ },
+ /** Set focus relative to this node and optionally activate.
+ *
+ * 'left' collapses the node if it is expanded, or move to the parent
+ * otherwise.
+ * 'right' expands the node if it is collapsed, or move to the first
+ * child otherwise.
+ *
+ * @param {string|number} where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.
+ * (Alternatively the keyCode that would normally trigger this move,
+ * e.g. `$.ui.keyCode.LEFT` = 'left'.
+ * @param {boolean} [activate=true]
+ * @returns {$.Promise}
+ */
+ navigate: function (where, activate) {
+ var node,
+ KC = $.ui.keyCode;
+
+ // Handle optional expand/collapse action for LEFT/RIGHT
+ switch (where) {
+ case "left":
+ case KC.LEFT:
+ if (this.expanded) {
+ return this.setExpanded(false);
+ }
+ break;
+ case "right":
+ case KC.RIGHT:
+ if (!this.expanded && (this.children || this.lazy)) {
+ return this.setExpanded();
+ }
+ break;
+ }
+ // Otherwise activate or focus the related node
+ node = this.findRelatedNode(where);
+ if (node) {
+ // setFocus/setActive will scroll later (if autoScroll is specified)
+ try {
+ node.makeVisible({ scrollIntoView: false });
+ } catch (e) {} // #272
+ if (activate === false) {
+ node.setFocus();
+ return _getResolvedPromise();
+ }
+ return node.setActive();
+ }
+ this.warn("Could not find related node '" + where + "'.");
+ return _getResolvedPromise();
+ },
+ /**
+ * Remove this node (not allowed for system root).
+ */
+ remove: function () {
+ return this.parent.removeChild(this);
+ },
+ /**
+ * Remove childNode from list of direct children.
+ * @param {FancytreeNode} childNode
+ */
+ removeChild: function (childNode) {
+ return this.tree._callHook("nodeRemoveChild", this, childNode);
+ },
+ /**
+ * Remove all child nodes and descendents. This converts the node into a leaf.<br>
+ * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy()
+ * in order to trigger lazyLoad on next expand.
+ */
+ removeChildren: function () {
+ return this.tree._callHook("nodeRemoveChildren", this);
+ },
+ /**
+ * Remove class from node's span tag and .extraClasses.
+ *
+ * @param {string} className class name
+ *
+ * @since 2.17
+ */
+ removeClass: function (className) {
+ return this.toggleClass(className, false);
+ },
+ /**
+ * This method renders and updates all HTML markup that is required
+ * to display this node in its current state.<br>
+ * Note:
+ * <ul>
+ * <li>It should only be neccessary to call this method after the node object
+ * was modified by direct access to its properties, because the common
+ * API methods (node.setTitle(), moveTo(), addChildren(), remove(), ...)
+ * already handle this.
+ * <li> {@link FancytreeNode#renderTitle} and {@link FancytreeNode#renderStatus}
+ * are implied. If changes are more local, calling only renderTitle() or
+ * renderStatus() may be sufficient and faster.
+ * </ul>
+ *
+ * @param {boolean} [force=false] re-render, even if html markup was already created
+ * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+ */
+ render: function (force, deep) {
+ return this.tree._callHook("nodeRender", this, force, deep);
+ },
+ /** Create HTML markup for the node's outer `<span>` (expander, checkbox, icon, and title).
+ * Implies {@link FancytreeNode#renderStatus}.
+ * @see Fancytree_Hooks#nodeRenderTitle
+ */
+ renderTitle: function () {
+ return this.tree._callHook("nodeRenderTitle", this);
+ },
+ /** Update element's CSS classes according to node state.
+ * @see Fancytree_Hooks#nodeRenderStatus
+ */
+ renderStatus: function () {
+ return this.tree._callHook("nodeRenderStatus", this);
+ },
+ /**
+ * (experimental) Replace this node with `source`.
+ * (Currently only available for paging nodes.)
+ * @param {NodeData[]} source List of child node definitions
+ * @since 2.15
+ */
+ replaceWith: function (source) {
+ var res,
+ parent = this.parent,
+ pos = $.inArray(this, parent.children),
+ self = this;
+
+ _assert(
+ this.isPagingNode(),
+ "replaceWith() currently requires a paging status node"
+ );
+
+ res = this.tree._callHook("nodeLoadChildren", this, source);
+ res.done(function (data) {
+ // New nodes are currently children of `this`.
+ var children = self.children;
+ // Prepend newly loaded child nodes to `this`
+ // Move new children after self
+ for (i = 0; i < children.length; i++) {
+ children[i].parent = parent;
+ }
+ parent.children.splice.apply(
+ parent.children,
+ [pos + 1, 0].concat(children)
+ );
+
+ // Remove self
+ self.children = null;
+ self.remove();
+ // Redraw new nodes
+ parent.render();
+ // TODO: set node.partload = false if this was tha last paging node?
+ // parent.addPagingNode(false);
+ }).fail(function () {
+ self.setExpanded();
+ });
+ return res;
+ // $.error("Not implemented: replaceWith()");
+ },
+ /**
+ * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad
+ * event is triggered on next expand.
+ */
+ resetLazy: function () {
+ this.removeChildren();
+ this.expanded = false;
+ this.lazy = true;
+ this.children = undefined;
+ this.renderStatus();
+ },
+ /** Schedule activity for delayed execution (cancel any pending request).
+ * scheduleAction('cancel') will only cancel a pending request (if any).
+ * @param {string} mode
+ * @param {number} ms
+ */
+ scheduleAction: function (mode, ms) {
+ if (this.tree.timer) {
+ clearTimeout(this.tree.timer);
+ this.tree.debug("clearTimeout(%o)", this.tree.timer);
+ }
+ this.tree.timer = null;
+ var self = this; // required for closures
+ switch (mode) {
+ case "cancel":
+ // Simply made sure that timer was cleared
+ break;
+ case "expand":
+ this.tree.timer = setTimeout(function () {
+ self.tree.debug("setTimeout: trigger expand");
+ self.setExpanded(true);
+ }, ms);
+ break;
+ case "activate":
+ this.tree.timer = setTimeout(function () {
+ self.tree.debug("setTimeout: trigger activate");
+ self.setActive(true);
+ }, ms);
+ break;
+ default:
+ $.error("Invalid mode " + mode);
+ }
+ // this.tree.debug("setTimeout(%s, %s): %s", mode, ms, this.tree.timer);
+ },
+ /**
+ *
+ * @param {boolean | PlainObject} [effects=false] animation options.
+ * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in
+ * any case, even if `this` is outside the scroll pane.
+ * @returns {$.Promise}
+ */
+ scrollIntoView: function (effects, options) {
+ if (options !== undefined && _isNode(options)) {
+ throw Error(
+ "scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead."
+ );
+ }
+ // The scroll parent is typically the plain tree's <UL> container.
+ // For ext-table, we choose the nearest parent that has `position: relative`
+ // and `overflow` set.
+ // (This default can be overridden by the local or global `scrollParent` option.)
+ var opts = $.extend(
+ {
+ effects:
+ effects === true
+ ? { duration: 200, queue: false }
+ : effects,
+ scrollOfs: this.tree.options.scrollOfs,
+ scrollParent: this.tree.options.scrollParent,
+ topNode: null,
+ },
+ options
+ ),
+ $scrollParent = opts.scrollParent,
+ $container = this.tree.$container,
+ overflowY = $container.css("overflow-y");
+
+ if (!$scrollParent) {
+ if (this.tree.tbody) {
+ $scrollParent = $container.scrollParent();
+ } else if (overflowY === "scroll" || overflowY === "auto") {
+ $scrollParent = $container;
+ } else {
+ // #922 plain tree in a non-fixed-sized UL scrolls inside its parent
+ $scrollParent = $container.scrollParent();
+ }
+ } else if (!$scrollParent.jquery) {
+ // Make sure we have a jQuery object
+ $scrollParent = $($scrollParent);
+ }
+ if (
+ $scrollParent[0] === document ||
+ $scrollParent[0] === document.body
+ ) {
+ // `document` may be returned by $().scrollParent(), if nothing is found,
+ // but would not work: (see #894)
+ this.debug(
+ "scrollIntoView(): normalizing scrollParent to 'window':",
+ $scrollParent[0]
+ );
+ $scrollParent = $(window);
+ }
+ // eslint-disable-next-line one-var
+ var topNodeY,
+ nodeY,
+ horzScrollbarHeight,
+ containerOffsetTop,
+ dfd = new $.Deferred(),
+ self = this,
+ nodeHeight = $(this.span).height(),
+ topOfs = opts.scrollOfs.top || 0,
+ bottomOfs = opts.scrollOfs.bottom || 0,
+ containerHeight = $scrollParent.height(),
+ scrollTop = $scrollParent.scrollTop(),
+ $animateTarget = $scrollParent,
+ isParentWindow = $scrollParent[0] === window,
+ topNode = opts.topNode || null,
+ newScrollTop = null;
+
+ // this.debug("scrollIntoView(), scrollTop=" + scrollTop, opts.scrollOfs);
+ // _assert($(this.span).is(":visible"), "scrollIntoView node is invisible"); // otherwise we cannot calc offsets
+ if (this.isRootNode() || !this.isVisible()) {
+ // We cannot calc offsets for hidden elements
+ this.info("scrollIntoView(): node is invisible.");
+ return _getResolvedPromise();
+ }
+ if (isParentWindow) {
+ nodeY = $(this.span).offset().top;
+ topNodeY =
+ topNode && topNode.span ? $(topNode.span).offset().top : 0;
+ $animateTarget = $("html,body");
+ } else {
+ _assert(
+ $scrollParent[0] !== document &&
+ $scrollParent[0] !== document.body,
+ "scrollParent should be a simple element or `window`, not document or body."
+ );
+
+ containerOffsetTop = $scrollParent.offset().top;
+ nodeY =
+ $(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent
+ topNodeY = topNode
+ ? $(topNode.span).offset().top -
+ containerOffsetTop +
+ scrollTop
+ : 0;
+ horzScrollbarHeight = Math.max(
+ 0,
+ $scrollParent.innerHeight() - $scrollParent[0].clientHeight
+ );
+ containerHeight -= horzScrollbarHeight;
+ }
+
+ // this.debug(" scrollIntoView(), nodeY=" + nodeY + ", containerHeight=" + containerHeight);
+ if (nodeY < scrollTop + topOfs) {
+ // Node is above visible container area
+ newScrollTop = nodeY - topOfs;
+ // this.debug(" scrollIntoView(), UPPER newScrollTop=" + newScrollTop);
+ } else if (
+ nodeY + nodeHeight >
+ scrollTop + containerHeight - bottomOfs
+ ) {
+ newScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs;
+ // this.debug(" scrollIntoView(), LOWER newScrollTop=" + newScrollTop);
+ // If a topNode was passed, make sure that it is never scrolled
+ // outside the upper border
+ if (topNode) {
+ _assert(
+ topNode.isRootNode() || topNode.isVisible(),
+ "topNode must be visible"
+ );
+ if (topNodeY < newScrollTop) {
+ newScrollTop = topNodeY - topOfs;
+ // this.debug(" scrollIntoView(), TOP newScrollTop=" + newScrollTop);
+ }
+ }
+ }
+
+ if (newScrollTop === null) {
+ dfd.resolveWith(this);
+ } else {
+ // this.debug(" scrollIntoView(), SET newScrollTop=" + newScrollTop);
+ if (opts.effects) {
+ opts.effects.complete = function () {
+ dfd.resolveWith(self);
+ };
+ $animateTarget.stop(true).animate(
+ {
+ scrollTop: newScrollTop,
+ },
+ opts.effects
+ );
+ } else {
+ $animateTarget[0].scrollTop = newScrollTop;
+ dfd.resolveWith(this);
+ }
+ }
+ return dfd.promise();
+ },
+
+ /**Activate this node.
+ *
+ * The `cell` option requires the ext-table and ext-ariagrid extensions.
+ *
+ * @param {boolean} [flag=true] pass false to deactivate
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false, cell: null}
+ * @returns {$.Promise}
+ */
+ setActive: function (flag, opts) {
+ return this.tree._callHook("nodeSetActive", this, flag, opts);
+ },
+ /**Expand or collapse this node. Promise is resolved, when lazy loading and animations are done.
+ * @param {boolean} [flag=true] pass false to collapse
+ * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}
+ * @returns {$.Promise}
+ */
+ setExpanded: function (flag, opts) {
+ return this.tree._callHook("nodeSetExpanded", this, flag, opts);
+ },
+ /**Set keyboard focus to this node.
+ * @param {boolean} [flag=true] pass false to blur
+ * @see Fancytree#setFocus
+ */
+ setFocus: function (flag) {
+ return this.tree._callHook("nodeSetFocus", this, flag);
+ },
+ /**Select this node, i.e. check the checkbox.
+ * @param {boolean} [flag=true] pass false to deselect
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, p
+ * propagateDown: null, propagateUp: null, callback: null }
+ */
+ setSelected: function (flag, opts) {
+ return this.tree._callHook("nodeSetSelected", this, flag, opts);
+ },
+ /**Mark a lazy node as 'error', 'loading', 'nodata', or 'ok'.
+ * @param {string} status 'error'|'loading'|'nodata'|'ok'
+ * @param {string} [message]
+ * @param {string} [details]
+ */
+ setStatus: function (status, message, details) {
+ return this.tree._callHook(
+ "nodeSetStatus",
+ this,
+ status,
+ message,
+ details
+ );
+ },
+ /**Rename this node.
+ * @param {string} title
+ */
+ setTitle: function (title) {
+ this.title = title;
+ this.renderTitle();
+ this.triggerModify("rename");
+ },
+ /**Sort child list by title.
+ * @param {function} [cmp] custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title).
+ * @param {boolean} [deep=false] pass true to sort all descendant nodes
+ */
+ sortChildren: function (cmp, deep) {
+ var i,
+ l,
+ cl = this.children;
+
+ if (!cl) {
+ return;
+ }
+ cmp =
+ cmp ||
+ function (a, b) {
+ var x = a.title.toLowerCase(),
+ y = b.title.toLowerCase();
+
+ // eslint-disable-next-line no-nested-ternary
+ return x === y ? 0 : x > y ? 1 : -1;
+ };
+ cl.sort(cmp);
+ if (deep) {
+ for (i = 0, l = cl.length; i < l; i++) {
+ if (cl[i].children) {
+ cl[i].sortChildren(cmp, "$norender$");
+ }
+ }
+ }
+ if (deep !== "$norender$") {
+ this.render();
+ }
+ this.triggerModifyChild("sort");
+ },
+ /** Convert node (or whole branch) into a plain object.
+ *
+ * The result is compatible with node.addChildren().
+ *
+ * @param {boolean} [recursive=false] include child nodes
+ * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications.
+ * Return `false` to ignore this node or `"skip"` to include this node without its children.
+ * @returns {NodeData}
+ */
+ toDict: function (recursive, callback) {
+ var i,
+ l,
+ node,
+ res,
+ dict = {},
+ self = this;
+
+ $.each(NODE_ATTRS, function (i, a) {
+ if (self[a] || self[a] === false) {
+ dict[a] = self[a];
+ }
+ });
+ if (!$.isEmptyObject(this.data)) {
+ dict.data = $.extend({}, this.data);
+ if ($.isEmptyObject(dict.data)) {
+ delete dict.data;
+ }
+ }
+ if (callback) {
+ res = callback(dict, self);
+ if (res === false) {
+ return false; // Don't include this node nor its children
+ }
+ if (res === "skip") {
+ recursive = false; // Include this node, but not the children
+ }
+ }
+ if (recursive) {
+ if (_isArray(this.children)) {
+ dict.children = [];
+ for (i = 0, l = this.children.length; i < l; i++) {
+ node = this.children[i];
+ if (!node.isStatusNode()) {
+ res = node.toDict(true, callback);
+ if (res !== false) {
+ dict.children.push(res);
+ }
+ }
+ }
+ }
+ }
+ return dict;
+ },
+ /**
+ * Set, clear, or toggle class of node's span tag and .extraClasses.
+ *
+ * @param {string} className class name (separate multiple classes by space)
+ * @param {boolean} [flag] true/false to add/remove class. If omitted, class is toggled.
+ * @returns {boolean} true if a class was added
+ *
+ * @since 2.17
+ */
+ toggleClass: function (value, flag) {
+ var className,
+ hasClass,
+ rnotwhite = /\S+/g,
+ classNames = value.match(rnotwhite) || [],
+ i = 0,
+ wasAdded = false,
+ statusElem = this[this.tree.statusClassPropName],
+ curClasses = " " + (this.extraClasses || "") + " ";
+
+ // this.info("toggleClass('" + value + "', " + flag + ")", curClasses);
+ // Modify DOM element directly if it already exists
+ if (statusElem) {
+ $(statusElem).toggleClass(value, flag);
+ }
+ // Modify node.extraClasses to make this change persistent
+ // Toggle if flag was not passed
+ while ((className = classNames[i++])) {
+ hasClass = curClasses.indexOf(" " + className + " ") >= 0;
+ flag = flag === undefined ? !hasClass : !!flag;
+ if (flag) {
+ if (!hasClass) {
+ curClasses += className + " ";
+ wasAdded = true;
+ }
+ } else {
+ while (curClasses.indexOf(" " + className + " ") > -1) {
+ curClasses = curClasses.replace(
+ " " + className + " ",
+ " "
+ );
+ }
+ }
+ }
+ this.extraClasses = _trim(curClasses);
+ // this.info("-> toggleClass('" + value + "', " + flag + "): '" + this.extraClasses + "'");
+ return wasAdded;
+ },
+ /** Flip expanded status. */
+ toggleExpanded: function () {
+ return this.tree._callHook("nodeToggleExpanded", this);
+ },
+ /** Flip selection status. */
+ toggleSelected: function () {
+ return this.tree._callHook("nodeToggleSelected", this);
+ },
+ toString: function () {
+ return "FancytreeNode@" + this.key + "[title='" + this.title + "']";
+ // return "<FancytreeNode(#" + this.key + ", '" + this.title + "')>";
+ },
+ /**
+ * Trigger `modifyChild` event on a parent to signal that a child was modified.
+ * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
+ * @param {FancytreeNode} [childNode]
+ * @param {object} [extra]
+ */
+ triggerModifyChild: function (operation, childNode, extra) {
+ var data,
+ modifyChild = this.tree.options.modifyChild;
+
+ if (modifyChild) {
+ if (childNode && childNode.parent !== this) {
+ $.error(
+ "childNode " + childNode + " is not a child of " + this
+ );
+ }
+ data = {
+ node: this,
+ tree: this.tree,
+ operation: operation,
+ childNode: childNode || null,
+ };
+ if (extra) {
+ $.extend(data, extra);
+ }
+ modifyChild({ type: "modifyChild" }, data);
+ }
+ },
+ /**
+ * Trigger `modifyChild` event on node.parent(!).
+ * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
+ * @param {object} [extra]
+ */
+ triggerModify: function (operation, extra) {
+ this.parent.triggerModifyChild(operation, this, extra);
+ },
+ /** Call fn(node) for all child nodes in hierarchical order (depth-first).<br>
+ * Stop iteration, if fn() returns false. Skip current branch, if fn() returns "skip".<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and
+ * its children only.
+ * @param {boolean} [includeSelf=false]
+ * @returns {boolean}
+ */
+ visit: function (fn, includeSelf) {
+ var i,
+ l,
+ res = true,
+ children = this.children;
+
+ if (includeSelf === true) {
+ res = fn(this);
+ if (res === false || res === "skip") {
+ return res;
+ }
+ }
+ if (children) {
+ for (i = 0, l = children.length; i < l; i++) {
+ res = children[i].visit(fn, true);
+ if (res === false) {
+ break;
+ }
+ }
+ }
+ return res;
+ },
+ /** Call fn(node) for all child nodes and recursively load lazy children.<br>
+ * <b>Note:</b> If you need this method, you probably should consider to review
+ * your architecture! Recursivley loading nodes is a perfect way for lazy
+ * programmers to flood the server with requests ;-)
+ *
+ * @param {function} [fn] optional callback function.
+ * Return false to stop iteration, return "skip" to skip this node and
+ * its children only.
+ * @param {boolean} [includeSelf=false]
+ * @returns {$.Promise}
+ * @since 2.4
+ */
+ visitAndLoad: function (fn, includeSelf, _recursion) {
+ var dfd,
+ res,
+ loaders,
+ node = this;
+
+ // node.debug("visitAndLoad");
+ if (fn && includeSelf === true) {
+ res = fn(node);
+ if (res === false || res === "skip") {
+ return _recursion ? res : _getResolvedPromise();
+ }
+ }
+ if (!node.children && !node.lazy) {
+ return _getResolvedPromise();
+ }
+ dfd = new $.Deferred();
+ loaders = [];
+ // node.debug("load()...");
+ node.load().done(function () {
+ // node.debug("load()... done.");
+ for (var i = 0, l = node.children.length; i < l; i++) {
+ res = node.children[i].visitAndLoad(fn, true, true);
+ if (res === false) {
+ dfd.reject();
+ break;
+ } else if (res !== "skip") {
+ loaders.push(res); // Add promise to the list
+ }
+ }
+ $.when.apply(this, loaders).then(function () {
+ dfd.resolve();
+ });
+ });
+ return dfd.promise();
+ },
+ /** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>
+ * Stop iteration, if fn() returns false.<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and children only.
+ * @param {boolean} [includeSelf=false]
+ * @returns {boolean}
+ */
+ visitParents: function (fn, includeSelf) {
+ // Visit parent nodes (bottom up)
+ if (includeSelf && fn(this) === false) {
+ return false;
+ }
+ var p = this.parent;
+ while (p) {
+ if (fn(p) === false) {
+ return false;
+ }
+ p = p.parent;
+ }
+ return true;
+ },
+ /** Call fn(node) for all sibling nodes.<br>
+ * Stop iteration, if fn() returns false.<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration.
+ * @param {boolean} [includeSelf=false]
+ * @returns {boolean}
+ */
+ visitSiblings: function (fn, includeSelf) {
+ var i,
+ l,
+ n,
+ ac = this.parent.children;
+
+ for (i = 0, l = ac.length; i < l; i++) {
+ n = ac[i];
+ if (includeSelf || n !== this) {
+ if (fn(n) === false) {
+ return false;
+ }
+ }
+ }
+ return true;
+ },
+ /** Write warning to browser console if debugLevel >= 2 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ warn: function (msg) {
+ if (this.tree.options.debugLevel >= 2) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("warn", arguments);
+ }
+ },
+ };
+
+ /******************************************************************************
+ * Fancytree
+ */
+ /**
+ * Construct a new tree object.
+ *
+ * @class Fancytree
+ * @classdesc The controller behind a fancytree.
+ * This class also contains 'hook methods': see {@link Fancytree_Hooks}.
+ *
+ * @param {Widget} widget
+ *
+ * @property {string} _id Automatically generated unique tree instance ID, e.g. "1".
+ * @property {string} _ns Automatically generated unique tree namespace, e.g. ".fancytree-1".
+ * @property {FancytreeNode} activeNode Currently active node or null.
+ * @property {string} ariaPropName Property name of FancytreeNode that contains the element which will receive the aria attributes.
+ * Typically "li", but "tr" for table extension.
+ * @property {jQueryObject} $container Outer `<ul>` element (or `<table>` element for ext-table).
+ * @property {jQueryObject} $div A jQuery object containing the element used to instantiate the tree widget (`widget.element`)
+ * @property {object|array} columns Recommended place to store shared column meta data. @since 2.27
+ * @property {object} data Metadata, i.e. properties that may be passed to `source` in addition to a children array.
+ * @property {object} ext Hash of all active plugin instances.
+ * @property {FancytreeNode} focusNode Currently focused node or null.
+ * @property {FancytreeNode} lastSelectedNode Used to implement selectMode 1 (single select)
+ * @property {string} nodeContainerAttrName Property name of FancytreeNode that contains the outer element of single nodes.
+ * Typically "li", but "tr" for table extension.
+ * @property {FancytreeOptions} options Current options, i.e. default options + options passed to constructor.
+ * @property {FancytreeNode} rootNode Invisible system root node.
+ * @property {string} statusClassPropName Property name of FancytreeNode that contains the element which will receive the status classes.
+ * Typically "span", but "tr" for table extension.
+ * @property {object} types Map for shared type specific meta data, used with node.type attribute. @since 2.27
+ * @property {object} viewport See ext-vieport. @since v2.31
+ * @property {object} widget Base widget instance.
+ */
+ function Fancytree(widget) {
+ this.widget = widget;
+ this.$div = widget.element;
+ this.options = widget.options;
+ if (this.options) {
+ if (this.options.lazyload !== undefined) {
+ $.error(
+ "The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."
+ );
+ }
+ if (this.options.loaderror !== undefined) {
+ $.error(
+ "The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."
+ );
+ }
+ if (this.options.fx !== undefined) {
+ $.error(
+ "The 'fx' option was replaced by 'toggleEffect' since 2014-11-30."
+ );
+ }
+ if (this.options.removeNode !== undefined) {
+ $.error(
+ "The 'removeNode' event was replaced by 'modifyChild' since 2.20 (2016-09-10)."
+ );
+ }
+ }
+ this.ext = {}; // Active extension instances
+ this.types = {};
+ this.columns = {};
+ // allow to init tree.data.foo from <div data-foo=''>
+ this.data = _getElementDataAsDict(this.$div);
+ // TODO: use widget.uuid instead?
+ this._id = "" + (this.options.treeId || $.ui.fancytree._nextId++);
+ // TODO: use widget.eventNamespace instead?
+ this._ns = ".fancytree-" + this._id; // append for namespaced events
+ this.activeNode = null;
+ this.focusNode = null;
+ this._hasFocus = null;
+ this._tempCache = {};
+ this._lastMousedownNode = null;
+ this._enableUpdate = true;
+ this.lastSelectedNode = null;
+ this.systemFocusElement = null;
+ this.lastQuicksearchTerm = "";
+ this.lastQuicksearchTime = 0;
+ this.viewport = null; // ext-grid
+
+ this.statusClassPropName = "span";
+ this.ariaPropName = "li";
+ this.nodeContainerAttrName = "li";
+
+ // Remove previous markup if any
+ this.$div.find(">ul.fancytree-container").remove();
+
+ // Create a node without parent.
+ var fakeParent = { tree: this },
+ $ul;
+ this.rootNode = new FancytreeNode(fakeParent, {
+ title: "root",
+ key: "root_" + this._id,
+ children: null,
+ expanded: true,
+ });
+ this.rootNode.parent = null;
+
+ // Create root markup
+ $ul = $("<ul>", {
+ id: "ft-id-" + this._id,
+ class: "ui-fancytree fancytree-container fancytree-plain",
+ }).appendTo(this.$div);
+ this.$container = $ul;
+ this.rootNode.ul = $ul[0];
+
+ if (this.options.debugLevel == null) {
+ this.options.debugLevel = FT.debugLevel;
+ }
+ // // Add container to the TAB chain
+ // // See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant
+ // // #577: Allow to set tabindex to "0", "-1" and ""
+ // this.$container.attr("tabindex", this.options.tabindex);
+
+ // if( this.options.rtl ) {
+ // this.$container.attr("DIR", "RTL").addClass("fancytree-rtl");
+ // // }else{
+ // // this.$container.attr("DIR", null).removeClass("fancytree-rtl");
+ // }
+ // if(this.options.aria){
+ // this.$container.attr("role", "tree");
+ // if( this.options.selectMode !== 1 ) {
+ // this.$container.attr("aria-multiselectable", true);
+ // }
+ // }
+ }
+
+ Fancytree.prototype = /** @lends Fancytree# */ {
+ /* Return a context object that can be re-used for _callHook().
+ * @param {Fancytree | FancytreeNode | EventData} obj
+ * @param {Event} originalEvent
+ * @param {Object} extra
+ * @returns {EventData}
+ */
+ _makeHookContext: function (obj, originalEvent, extra) {
+ var ctx, tree;
+ if (obj.node !== undefined) {
+ // obj is already a context object
+ if (originalEvent && obj.originalEvent !== originalEvent) {
+ $.error("invalid args");
+ }
+ ctx = obj;
+ } else if (obj.tree) {
+ // obj is a FancytreeNode
+ tree = obj.tree;
+ ctx = {
+ node: obj,
+ tree: tree,
+ widget: tree.widget,
+ options: tree.widget.options,
+ originalEvent: originalEvent,
+ typeInfo: tree.types[obj.type] || {},
+ };
+ } else if (obj.widget) {
+ // obj is a Fancytree
+ ctx = {
+ node: null,
+ tree: obj,
+ widget: obj.widget,
+ options: obj.widget.options,
+ originalEvent: originalEvent,
+ };
+ } else {
+ $.error("invalid args");
+ }
+ if (extra) {
+ $.extend(ctx, extra);
+ }
+ return ctx;
+ },
+ /* Trigger a hook function: funcName(ctx, [...]).
+ *
+ * @param {string} funcName
+ * @param {Fancytree|FancytreeNode|EventData} contextObject
+ * @param {any} [_extraArgs] optional additional arguments
+ * @returns {any}
+ */
+ _callHook: function (funcName, contextObject, _extraArgs) {
+ var ctx = this._makeHookContext(contextObject),
+ fn = this[funcName],
+ args = Array.prototype.slice.call(arguments, 2);
+ if (!_isFunction(fn)) {
+ $.error("_callHook('" + funcName + "') is not a function");
+ }
+ args.unshift(ctx);
+ // this.debug("_hook", funcName, ctx.node && ctx.node.toString() || ctx.tree.toString(), args);
+ return fn.apply(this, args);
+ },
+ _setExpiringValue: function (key, value, ms) {
+ this._tempCache[key] = {
+ value: value,
+ expire: Date.now() + (+ms || 50),
+ };
+ },
+ _getExpiringValue: function (key) {
+ var entry = this._tempCache[key];
+ if (entry && entry.expire > Date.now()) {
+ return entry.value;
+ }
+ delete this._tempCache[key];
+ return null;
+ },
+ /* Check if this tree has extension `name` enabled.
+ *
+ * @param {string} name name of the required extension
+ */
+ _usesExtension: function (name) {
+ return $.inArray(name, this.options.extensions) >= 0;
+ },
+ /* Check if current extensions dependencies are met and throw an error if not.
+ *
+ * This method may be called inside the `treeInit` hook for custom extensions.
+ *
+ * @param {string} name name of the required extension
+ * @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present
+ * @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter)
+ * @param {string} [message] optional error message (defaults to a descriptve error message)
+ */
+ _requireExtension: function (name, required, before, message) {
+ if (before != null) {
+ before = !!before;
+ }
+ var thisName = this._local.name,
+ extList = this.options.extensions,
+ isBefore =
+ $.inArray(name, extList) < $.inArray(thisName, extList),
+ isMissing = required && this.ext[name] == null,
+ badOrder = !isMissing && before != null && before !== isBefore;
+
+ _assert(
+ thisName && thisName !== name,
+ "invalid or same name '" + thisName + "' (require yourself?)"
+ );
+
+ if (isMissing || badOrder) {
+ if (!message) {
+ if (isMissing || required) {
+ message =
+ "'" +
+ thisName +
+ "' extension requires '" +
+ name +
+ "'";
+ if (badOrder) {
+ message +=
+ " to be registered " +
+ (before ? "before" : "after") +
+ " itself";
+ }
+ } else {
+ message =
+ "If used together, `" +
+ name +
+ "` must be registered " +
+ (before ? "before" : "after") +
+ " `" +
+ thisName +
+ "`";
+ }
+ }
+ $.error(message);
+ return false;
+ }
+ return true;
+ },
+ /** Activate node with a given key and fire focus and activate events.
+ *
+ * A previously activated node will be deactivated.
+ * If activeVisible option is set, all parents will be expanded as necessary.
+ * Pass key = false, to deactivate the current node only.
+ * @param {string} key
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}
+ * @returns {FancytreeNode} activated node (null, if not found)
+ */
+ activateKey: function (key, opts) {
+ var node = this.getNodeByKey(key);
+ if (node) {
+ node.setActive(true, opts);
+ } else if (this.activeNode) {
+ this.activeNode.setActive(false, opts);
+ }
+ return node;
+ },
+ /** (experimental) Add child status nodes that indicate 'More...', ....
+ * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.
+ * @param {string} [mode='append'] 'child'|firstChild'
+ * @since 2.15
+ */
+ addPagingNode: function (node, mode) {
+ return this.rootNode.addPagingNode(node, mode);
+ },
+ /**
+ * (experimental) Apply a modification (or navigation) operation.
+ *
+ * Valid commands:
+ * - 'moveUp', 'moveDown'
+ * - 'indent', 'outdent'
+ * - 'remove'
+ * - 'edit', 'addChild', 'addSibling': (reqires ext-edit extension)
+ * - 'cut', 'copy', 'paste': (use an internal singleton 'clipboard')
+ * - 'down', 'first', 'last', 'left', 'parent', 'right', 'up': navigate
+ *
+ * @param {string} cmd
+ * @param {FancytreeNode} [node=active_node]
+ * @param {object} [opts] Currently unused
+ *
+ * @since 2.32
+ */
+ applyCommand: function (cmd, node, opts_) {
+ var // clipboard,
+ refNode;
+ // opts = $.extend(
+ // { setActive: true, clipboard: CLIPBOARD },
+ // opts_
+ // );
+
+ node = node || this.getActiveNode();
+ // clipboard = opts.clipboard;
+
+ switch (cmd) {
+ // Sorting and indentation:
+ case "moveUp":
+ refNode = node.getPrevSibling();
+ if (refNode) {
+ node.moveTo(refNode, "before");
+ node.setActive();
+ }
+ break;
+ case "moveDown":
+ refNode = node.getNextSibling();
+ if (refNode) {
+ node.moveTo(refNode, "after");
+ node.setActive();
+ }
+ break;
+ case "indent":
+ refNode = node.getPrevSibling();
+ if (refNode) {
+ node.moveTo(refNode, "child");
+ refNode.setExpanded();
+ node.setActive();
+ }
+ break;
+ case "outdent":
+ if (!node.isTopLevel()) {
+ node.moveTo(node.getParent(), "after");
+ node.setActive();
+ }
+ break;
+ // Remove:
+ case "remove":
+ refNode = node.getPrevSibling() || node.getParent();
+ node.remove();
+ if (refNode) {
+ refNode.setActive();
+ }
+ break;
+ // Add, edit (requires ext-edit):
+ case "addChild":
+ node.editCreateNode("child", "");
+ break;
+ case "addSibling":
+ node.editCreateNode("after", "");
+ break;
+ case "rename":
+ node.editStart();
+ break;
+ // Simple clipboard simulation:
+ // case "cut":
+ // clipboard = { mode: cmd, data: node };
+ // break;
+ // case "copy":
+ // clipboard = {
+ // mode: cmd,
+ // data: node.toDict(function(d, n) {
+ // delete d.key;
+ // }),
+ // };
+ // break;
+ // case "clear":
+ // clipboard = null;
+ // break;
+ // case "paste":
+ // if (clipboard.mode === "cut") {
+ // // refNode = node.getPrevSibling();
+ // clipboard.data.moveTo(node, "child");
+ // clipboard.data.setActive();
+ // } else if (clipboard.mode === "copy") {
+ // node.addChildren(clipboard.data).setActive();
+ // }
+ // break;
+ // Navigation commands:
+ case "down":
+ case "first":
+ case "last":
+ case "left":
+ case "parent":
+ case "right":
+ case "up":
+ return node.navigate(cmd);
+ default:
+ $.error("Unhandled command: '" + cmd + "'");
+ }
+ },
+ /** (experimental) Modify existing data model.
+ *
+ * @param {Array} patchList array of [key, NodePatch] arrays
+ * @returns {$.Promise} resolved, when all patches have been applied
+ * @see TreePatch
+ */
+ applyPatch: function (patchList) {
+ var dfd,
+ i,
+ p2,
+ key,
+ patch,
+ node,
+ patchCount = patchList.length,
+ deferredList = [];
+
+ for (i = 0; i < patchCount; i++) {
+ p2 = patchList[i];
+ _assert(
+ p2.length === 2,
+ "patchList must be an array of length-2-arrays"
+ );
+ key = p2[0];
+ patch = p2[1];
+ node = key === null ? this.rootNode : this.getNodeByKey(key);
+ if (node) {
+ dfd = new $.Deferred();
+ deferredList.push(dfd);
+ node.applyPatch(patch).always(_makeResolveFunc(dfd, node));
+ } else {
+ this.warn("could not find node with key '" + key + "'");
+ }
+ }
+ // Return a promise that is resolved, when ALL patches were applied
+ return $.when.apply($, deferredList).promise();
+ },
+ /* TODO: implement in dnd extension
+ cancelDrag: function() {
+ var dd = $.ui.ddmanager.current;
+ if(dd){
+ dd.cancel();
+ }
+ },
+ */
+ /** Remove all nodes.
+ * @since 2.14
+ */
+ clear: function (source) {
+ this._callHook("treeClear", this);
+ },
+ /** Return the number of nodes.
+ * @returns {integer}
+ */
+ count: function () {
+ return this.rootNode.countChildren();
+ },
+ /** Write to browser console if debugLevel >= 4 (prepending tree name)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ debug: function (msg) {
+ if (this.options.debugLevel >= 4) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("log", arguments);
+ }
+ },
+ /** Destroy this widget, restore previous markup and cleanup resources.
+ *
+ * @since 2.34
+ */
+ destroy: function () {
+ this.widget.destroy();
+ },
+ /** Enable (or disable) the tree control.
+ *
+ * @param {boolean} [flag=true] pass false to disable
+ * @since 2.30
+ */
+ enable: function (flag) {
+ if (flag === false) {
+ this.widget.disable();
+ } else {
+ this.widget.enable();
+ }
+ },
+ /** Temporarily suppress rendering to improve performance on bulk-updates.
+ *
+ * @param {boolean} flag
+ * @returns {boolean} previous status
+ * @since 2.19
+ */
+ enableUpdate: function (flag) {
+ flag = flag !== false;
+ if (!!this._enableUpdate === !!flag) {
+ return flag;
+ }
+ this._enableUpdate = flag;
+ if (flag) {
+ this.debug("enableUpdate(true): redraw "); //, this._dirtyRoots);
+ this._callHook("treeStructureChanged", this, "enableUpdate");
+ this.render();
+ } else {
+ // this._dirtyRoots = null;
+ this.debug("enableUpdate(false)...");
+ }
+ return !flag; // return previous value
+ },
+ /** Write error to browser console if debugLevel >= 1 (prepending tree info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ error: function (msg) {
+ if (this.options.debugLevel >= 1) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("error", arguments);
+ }
+ },
+ /** Expand (or collapse) all parent nodes.
+ *
+ * This convenience method uses `tree.visit()` and `tree.setExpanded()`
+ * internally.
+ *
+ * @param {boolean} [flag=true] pass false to collapse
+ * @param {object} [opts] passed to setExpanded()
+ * @since 2.30
+ */
+ expandAll: function (flag, opts) {
+ var prev = this.enableUpdate(false);
+
+ flag = flag !== false;
+ this.visit(function (node) {
+ if (
+ node.hasChildren() !== false &&
+ node.isExpanded() !== flag
+ ) {
+ node.setExpanded(flag, opts);
+ }
+ });
+ this.enableUpdate(prev);
+ },
+ /**Find all nodes that matches condition.
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode[]} array of nodes (may be empty)
+ * @see FancytreeNode#findAll
+ * @since 2.12
+ */
+ findAll: function (match) {
+ return this.rootNode.findAll(match);
+ },
+ /**Find first node that matches condition.
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode} matching node or null
+ * @see FancytreeNode#findFirst
+ * @since 2.12
+ */
+ findFirst: function (match) {
+ return this.rootNode.findFirst(match);
+ },
+ /** Find the next visible node that starts with `match`, starting at `startNode`
+ * and wrap-around at the end.
+ *
+ * @param {string|function} match
+ * @param {FancytreeNode} [startNode] defaults to first node
+ * @returns {FancytreeNode} matching node or null
+ */
+ findNextNode: function (match, startNode) {
+ //, visibleOnly) {
+ var res = null,
+ firstNode = this.getFirstChild();
+
+ match =
+ typeof match === "string"
+ ? _makeNodeTitleStartMatcher(match)
+ : match;
+ startNode = startNode || firstNode;
+
+ function _checkNode(n) {
+ // console.log("_check " + n)
+ if (match(n)) {
+ res = n;
+ }
+ if (res || n === startNode) {
+ return false;
+ }
+ }
+ this.visitRows(_checkNode, {
+ start: startNode,
+ includeSelf: false,
+ });
+ // Wrap around search
+ if (!res && startNode !== firstNode) {
+ this.visitRows(_checkNode, {
+ start: firstNode,
+ includeSelf: true,
+ });
+ }
+ return res;
+ },
+ /** Find a node relative to another node.
+ *
+ * @param {FancytreeNode} node
+ * @param {string|number} where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.
+ * (Alternatively the keyCode that would normally trigger this move,
+ * e.g. `$.ui.keyCode.LEFT` = 'left'.
+ * @param {boolean} [includeHidden=false] Not yet implemented
+ * @returns {FancytreeNode|null}
+ * @since v2.31
+ */
+ findRelatedNode: function (node, where, includeHidden) {
+ var res = null,
+ KC = $.ui.keyCode;
+
+ switch (where) {
+ case "parent":
+ case KC.BACKSPACE:
+ if (node.parent && node.parent.parent) {
+ res = node.parent;
+ }
+ break;
+ case "first":
+ case KC.HOME:
+ // First visible node
+ this.visit(function (n) {
+ if (n.isVisible()) {
+ res = n;
+ return false;
+ }
+ });
+ break;
+ case "last":
+ case KC.END:
+ this.visit(function (n) {
+ // last visible node
+ if (n.isVisible()) {
+ res = n;
+ }
+ });
+ break;
+ case "left":
+ case KC.LEFT:
+ if (node.expanded) {
+ node.setExpanded(false);
+ } else if (node.parent && node.parent.parent) {
+ res = node.parent;
+ }
+ break;
+ case "right":
+ case KC.RIGHT:
+ if (!node.expanded && (node.children || node.lazy)) {
+ node.setExpanded();
+ res = node;
+ } else if (node.children && node.children.length) {
+ res = node.children[0];
+ }
+ break;
+ case "up":
+ case KC.UP:
+ this.visitRows(
+ function (n) {
+ res = n;
+ return false;
+ },
+ { start: node, reverse: true, includeSelf: false }
+ );
+ break;
+ case "down":
+ case KC.DOWN:
+ this.visitRows(
+ function (n) {
+ res = n;
+ return false;
+ },
+ { start: node, includeSelf: false }
+ );
+ break;
+ default:
+ this.tree.warn("Unknown relation '" + where + "'.");
+ }
+ return res;
+ },
+ // TODO: fromDict
+ /**
+ * Generate INPUT elements that can be submitted with html forms.
+ *
+ * In selectMode 3 only the topmost selected nodes are considered, unless
+ * `opts.stopOnParents: false` is passed.
+ *
+ * @example
+ * // Generate input elements for active and selected nodes
+ * tree.generateFormElements();
+ * // Generate input elements selected nodes, using a custom `name` attribute
+ * tree.generateFormElements("cust_sel", false);
+ * // Generate input elements using a custom filter
+ * tree.generateFormElements(true, true, { filter: function(node) {
+ * return node.isSelected() && node.data.yes;
+ * }});
+ *
+ * @param {boolean | string} [selected=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID[]')
+ * @param {boolean | string} [active=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID_active')
+ * @param {object} [opts] default { filter: null, stopOnParents: true }
+ */
+ generateFormElements: function (selected, active, opts) {
+ opts = opts || {};
+
+ var nodeList,
+ selectedName =
+ typeof selected === "string"
+ ? selected
+ : "ft_" + this._id + "[]",
+ activeName =
+ typeof active === "string"
+ ? active
+ : "ft_" + this._id + "_active",
+ id = "fancytree_result_" + this._id,
+ $result = $("#" + id),
+ stopOnParents =
+ this.options.selectMode === 3 &&
+ opts.stopOnParents !== false;
+
+ if ($result.length) {
+ $result.empty();
+ } else {
+ $result = $("<div>", {
+ id: id,
+ })
+ .hide()
+ .insertAfter(this.$container);
+ }
+ if (active !== false && this.activeNode) {
+ $result.append(
+ $("<input>", {
+ type: "radio",
+ name: activeName,
+ value: this.activeNode.key,
+ checked: true,
+ })
+ );
+ }
+ function _appender(node) {
+ $result.append(
+ $("<input>", {
+ type: "checkbox",
+ name: selectedName,
+ value: node.key,
+ checked: true,
+ })
+ );
+ }
+ if (opts.filter) {
+ this.visit(function (node) {
+ var res = opts.filter(node);
+ if (res === "skip") {
+ return res;
+ }
+ if (res !== false) {
+ _appender(node);
+ }
+ });
+ } else if (selected !== false) {
+ nodeList = this.getSelectedNodes(stopOnParents);
+ $.each(nodeList, function (idx, node) {
+ _appender(node);
+ });
+ }
+ },
+ /**
+ * Return the currently active node or null.
+ * @returns {FancytreeNode}
+ */
+ getActiveNode: function () {
+ return this.activeNode;
+ },
+ /** Return the first top level node if any (not the invisible root node).
+ * @returns {FancytreeNode | null}
+ */
+ getFirstChild: function () {
+ return this.rootNode.getFirstChild();
+ },
+ /**
+ * Return node that has keyboard focus or null.
+ * @returns {FancytreeNode}
+ */
+ getFocusNode: function () {
+ return this.focusNode;
+ },
+ /**
+ * Return current option value.
+ * (Note: this is the preferred variant of `$().fancytree("option", "KEY")`)
+ *
+ * @param {string} name option name (may contain '.')
+ * @returns {any}
+ */
+ getOption: function (optionName) {
+ return this.widget.option(optionName);
+ },
+ /**
+ * Return node with a given key or null if not found.
+ *
+ * @param {string} key
+ * @param {FancytreeNode} [searchRoot] only search below this node
+ * @returns {FancytreeNode | null}
+ */
+ getNodeByKey: function (key, searchRoot) {
+ // Search the DOM by element ID (assuming this is faster than traversing all nodes).
+ var el, match;
+ // TODO: use tree.keyMap if available
+ // TODO: check opts.generateIds === true
+ if (!searchRoot) {
+ el = document.getElementById(this.options.idPrefix + key);
+ if (el) {
+ return el.ftnode ? el.ftnode : null;
+ }
+ }
+ // Not found in the DOM, but still may be in an unrendered part of tree
+ searchRoot = searchRoot || this.rootNode;
+ match = null;
+ key = "" + key; // Convert to string (#1005)
+ searchRoot.visit(function (node) {
+ if (node.key === key) {
+ match = node;
+ return false; // Stop iteration
+ }
+ }, true);
+ return match;
+ },
+ /** Return the invisible system root node.
+ * @returns {FancytreeNode}
+ */
+ getRootNode: function () {
+ return this.rootNode;
+ },
+ /**
+ * Return an array of selected nodes.
+ *
+ * Note: you cannot send this result via Ajax directly. Instead the
+ * node object need to be converted to plain objects, for example
+ * by using `$.map()` and `node.toDict()`.
+ * @param {boolean} [stopOnParents=false] only return the topmost selected
+ * node (useful with selectMode 3)
+ * @returns {FancytreeNode[]}
+ */
+ getSelectedNodes: function (stopOnParents) {
+ return this.rootNode.getSelectedNodes(stopOnParents);
+ },
+ /** Return true if the tree control has keyboard focus
+ * @returns {boolean}
+ */
+ hasFocus: function () {
+ // var ae = document.activeElement,
+ // hasFocus = !!(
+ // ae && $(ae).closest(".fancytree-container").length
+ // );
+
+ // if (hasFocus !== !!this._hasFocus) {
+ // this.warn(
+ // "hasFocus(): fix inconsistent container state, now: " +
+ // hasFocus
+ // );
+ // this._hasFocus = hasFocus;
+ // this.$container.toggleClass("fancytree-treefocus", hasFocus);
+ // }
+ // return hasFocus;
+ return !!this._hasFocus;
+ },
+ /** Write to browser console if debugLevel >= 3 (prepending tree name)
+ * @param {*} msg string or object or array of such
+ */
+ info: function (msg) {
+ if (this.options.debugLevel >= 3) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("info", arguments);
+ }
+ },
+ /** Return true if any node is currently beeing loaded, i.e. a Ajax request is pending.
+ * @returns {boolean}
+ * @since 2.32
+ */
+ isLoading: function () {
+ var res = false;
+
+ this.rootNode.visit(function (n) {
+ // also visit rootNode
+ if (n._isLoading || n._requestId) {
+ res = true;
+ return false;
+ }
+ }, true);
+ return res;
+ },
+ /*
+ TODO: isInitializing: function() {
+ return ( this.phase=="init" || this.phase=="postInit" );
+ },
+ TODO: isReloading: function() {
+ return ( this.phase=="init" || this.phase=="postInit" ) && this.options.persist && this.persistence.cookiesFound;
+ },
+ TODO: isUserEvent: function() {
+ return ( this.phase=="userEvent" );
+ },
+ */
+
+ /**
+ * Make sure that a node with a given ID is loaded, by traversing - and
+ * loading - its parents. This method is meant for lazy hierarchies.
+ * A callback is executed for every node as we go.
+ * @example
+ * // Resolve using node.key:
+ * tree.loadKeyPath("/_3/_23/_26/_27", function(node, status){
+ * if(status === "loaded") {
+ * console.log("loaded intermediate node " + node);
+ * }else if(status === "ok") {
+ * node.activate();
+ * }
+ * });
+ * // Use deferred promise:
+ * tree.loadKeyPath("/_3/_23/_26/_27").progress(function(data){
+ * if(data.status === "loaded") {
+ * console.log("loaded intermediate node " + data.node);
+ * }else if(data.status === "ok") {
+ * node.activate();
+ * }
+ * }).done(function(){
+ * ...
+ * });
+ * // Custom path segment resolver:
+ * tree.loadKeyPath("/321/431/21/2", {
+ * matchKey: function(node, key){
+ * return node.data.refKey === key;
+ * },
+ * callback: function(node, status){
+ * if(status === "loaded") {
+ * console.log("loaded intermediate node " + node);
+ * }else if(status === "ok") {
+ * node.activate();
+ * }
+ * }
+ * });
+ * @param {string | string[]} keyPathList one or more key paths (e.g. '/3/2_1/7')
+ * @param {function | object} optsOrCallback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error').
+ * Pass an object to define custom key matchers for the path segments: {callback: function, matchKey: function}.
+ * @returns {$.Promise}
+ */
+ loadKeyPath: function (keyPathList, optsOrCallback) {
+ var callback,
+ i,
+ path,
+ self = this,
+ dfd = new $.Deferred(),
+ parent = this.getRootNode(),
+ sep = this.options.keyPathSeparator,
+ pathSegList = [],
+ opts = $.extend({}, optsOrCallback);
+
+ // Prepare options
+ if (typeof optsOrCallback === "function") {
+ callback = optsOrCallback;
+ } else if (optsOrCallback && optsOrCallback.callback) {
+ callback = optsOrCallback.callback;
+ }
+ opts.callback = function (ctx, node, status) {
+ if (callback) {
+ callback.call(ctx, node, status);
+ }
+ dfd.notifyWith(ctx, [{ node: node, status: status }]);
+ };
+ if (opts.matchKey == null) {
+ opts.matchKey = function (node, key) {
+ return node.key === key;
+ };
+ }
+ // Convert array of path strings to array of segment arrays
+ if (!_isArray(keyPathList)) {
+ keyPathList = [keyPathList];
+ }
+ for (i = 0; i < keyPathList.length; i++) {
+ path = keyPathList[i];
+ // strip leading slash
+ if (path.charAt(0) === sep) {
+ path = path.substr(1);
+ }
+ // segListMap[path] = { parent: parent, segList: path.split(sep) };
+ pathSegList.push(path.split(sep));
+ // targetList.push({ parent: parent, segList: path.split(sep)/* , path: path*/});
+ }
+ // The timeout forces async behavior always (even if nodes are all loaded)
+ // This way a potential progress() event will fire.
+ setTimeout(function () {
+ self._loadKeyPathImpl(dfd, opts, parent, pathSegList).done(
+ function () {
+ dfd.resolve();
+ }
+ );
+ }, 0);
+ return dfd.promise();
+ },
+ /*
+ * Resolve a list of paths, relative to one parent node.
+ */
+ _loadKeyPathImpl: function (dfd, opts, parent, pathSegList) {
+ var deferredList,
+ i,
+ key,
+ node,
+ nodeKey,
+ remain,
+ remainMap,
+ tmpParent,
+ segList,
+ subDfd,
+ self = this;
+
+ function __findChild(parent, key) {
+ // console.log("__findChild", key, parent);
+ var i,
+ l,
+ cl = parent.children;
+
+ if (cl) {
+ for (i = 0, l = cl.length; i < l; i++) {
+ if (opts.matchKey(cl[i], key)) {
+ return cl[i];
+ }
+ }
+ }
+ return null;
+ }
+
+ // console.log("_loadKeyPathImpl, parent=", parent, ", pathSegList=", pathSegList);
+
+ // Pass 1:
+ // Handle all path segments for nodes that are already loaded.
+ // Collect distinct top-most lazy nodes in a map.
+ // Note that we can use node.key to de-dupe entries, even if a custom matcher would
+ // look for other node attributes.
+ // map[node.key] => {node: node, pathList: [list of remaining rest-paths]}
+ remainMap = {};
+
+ for (i = 0; i < pathSegList.length; i++) {
+ segList = pathSegList[i];
+ // target = targetList[i];
+
+ // Traverse and pop path segments (i.e. keys), until we hit a lazy, unloaded node
+ tmpParent = parent;
+ while (segList.length) {
+ key = segList.shift();
+ node = __findChild(tmpParent, key);
+ if (!node) {
+ this.warn(
+ "loadKeyPath: key not found: " +
+ key +
+ " (parent: " +
+ tmpParent +
+ ")"
+ );
+ opts.callback(this, key, "error");
+ break;
+ } else if (segList.length === 0) {
+ opts.callback(this, node, "ok");
+ break;
+ } else if (!node.lazy || node.hasChildren() !== undefined) {
+ opts.callback(this, node, "loaded");
+ tmpParent = node;
+ } else {
+ opts.callback(this, node, "loaded");
+ key = node.key; //target.segList.join(sep);
+ if (remainMap[key]) {
+ remainMap[key].pathSegList.push(segList);
+ } else {
+ remainMap[key] = {
+ parent: node,
+ pathSegList: [segList],
+ };
+ }
+ break;
+ }
+ }
+ }
+ // console.log("_loadKeyPathImpl AFTER pass 1, remainMap=", remainMap);
+
+ // Now load all lazy nodes and continue iteration for remaining paths
+ deferredList = [];
+
+ // Avoid jshint warning 'Don't make functions within a loop.':
+ function __lazyload(dfd, parent, pathSegList) {
+ // console.log("__lazyload", parent, "pathSegList=", pathSegList);
+ opts.callback(self, parent, "loading");
+ parent
+ .load()
+ .done(function () {
+ self._loadKeyPathImpl
+ .call(self, dfd, opts, parent, pathSegList)
+ .always(_makeResolveFunc(dfd, self));
+ })
+ .fail(function (errMsg) {
+ self.warn("loadKeyPath: error loading lazy " + parent);
+ opts.callback(self, node, "error");
+ dfd.rejectWith(self);
+ });
+ }
+ // remainMap contains parent nodes, each with a list of relative sub-paths.
+ // We start loading all of them now, and pass the the list to each loader.
+ for (nodeKey in remainMap) {
+ if (_hasProp(remainMap, nodeKey)) {
+ remain = remainMap[nodeKey];
+ // console.log("for(): remain=", remain, "remainMap=", remainMap);
+ // key = remain.segList.shift();
+ // node = __findChild(remain.parent, key);
+ // if (node == null) { // #576
+ // // Issue #576, refactored for v2.27:
+ // // The root cause was, that sometimes the wrong parent was used here
+ // // to find the next segment.
+ // // Falling back to getNodeByKey() was a hack that no longer works if a custom
+ // // matcher is used, because we cannot assume that a single segment-key is unique
+ // // throughout the tree.
+ // self.error("loadKeyPath: error loading child by key '" + key + "' (parent: " + target.parent + ")", target);
+ // // node = self.getNodeByKey(key);
+ // continue;
+ // }
+ subDfd = new $.Deferred();
+ deferredList.push(subDfd);
+ __lazyload(subDfd, remain.parent, remain.pathSegList);
+ }
+ }
+ // Return a promise that is resolved, when ALL paths were loaded
+ return $.when.apply($, deferredList).promise();
+ },
+ /** Re-fire beforeActivate, activate, and (optional) focus events.
+ * Calling this method in the `init` event, will activate the node that
+ * was marked 'active' in the source data, and optionally set the keyboard
+ * focus.
+ * @param [setFocus=false]
+ */
+ reactivate: function (setFocus) {
+ var res,
+ node = this.activeNode;
+
+ if (!node) {
+ return _getResolvedPromise();
+ }
+ this.activeNode = null; // Force re-activating
+ res = node.setActive(true, { noFocus: true });
+ if (setFocus) {
+ node.setFocus();
+ }
+ return res;
+ },
+ /** Reload tree from source and return a promise.
+ * @param [source] optional new source (defaults to initial source data)
+ * @returns {$.Promise}
+ */
+ reload: function (source) {
+ this._callHook("treeClear", this);
+ return this._callHook("treeLoad", this, source);
+ },
+ /**Render tree (i.e. create DOM elements for all top-level nodes).
+ * @param {boolean} [force=false] create DOM elemnts, even if parent is collapsed
+ * @param {boolean} [deep=false]
+ */
+ render: function (force, deep) {
+ return this.rootNode.render(force, deep);
+ },
+ /**(De)select all nodes.
+ * @param {boolean} [flag=true]
+ * @since 2.28
+ */
+ selectAll: function (flag) {
+ this.visit(function (node) {
+ node.setSelected(flag);
+ });
+ },
+ // TODO: selectKey: function(key, select)
+ // TODO: serializeArray: function(stopOnParents)
+ /**
+ * @param {boolean} [flag=true]
+ */
+ setFocus: function (flag) {
+ return this._callHook("treeSetFocus", this, flag);
+ },
+ /**
+ * Set current option value.
+ * (Note: this is the preferred variant of `$().fancytree("option", "KEY", VALUE)`)
+ * @param {string} name option name (may contain '.')
+ * @param {any} new value
+ */
+ setOption: function (optionName, value) {
+ return this.widget.option(optionName, value);
+ },
+ /**
+ * Call console.time() when in debug mode (verbose >= 4).
+ *
+ * @param {string} label
+ */
+ debugTime: function (label) {
+ if (this.options.debugLevel >= 4) {
+ window.console.time(this + " - " + label);
+ }
+ },
+ /**
+ * Call console.timeEnd() when in debug mode (verbose >= 4).
+ *
+ * @param {string} label
+ */
+ debugTimeEnd: function (label) {
+ if (this.options.debugLevel >= 4) {
+ window.console.timeEnd(this + " - " + label);
+ }
+ },
+ /**
+ * Return all nodes as nested list of {@link NodeData}.
+ *
+ * @param {boolean} [includeRoot=false] Returns the hidden system root node (and its children)
+ * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications.
+ * Return `false` to ignore this node or "skip" to include this node without its children.
+ * @returns {Array | object}
+ * @see FancytreeNode#toDict
+ */
+ toDict: function (includeRoot, callback) {
+ var res = this.rootNode.toDict(true, callback);
+ return includeRoot ? res : res.children;
+ },
+ /* Implicitly called for string conversions.
+ * @returns {string}
+ */
+ toString: function () {
+ return "Fancytree@" + this._id;
+ // return "<Fancytree(#" + this._id + ")>";
+ },
+ /* _trigger a widget event with additional node ctx.
+ * @see EventData
+ */
+ _triggerNodeEvent: function (type, node, originalEvent, extra) {
+ // this.debug("_trigger(" + type + "): '" + ctx.node.title + "'", ctx);
+ var ctx = this._makeHookContext(node, originalEvent, extra),
+ res = this.widget._trigger(type, originalEvent, ctx);
+ if (res !== false && ctx.result !== undefined) {
+ return ctx.result;
+ }
+ return res;
+ },
+ /* _trigger a widget event with additional tree data. */
+ _triggerTreeEvent: function (type, originalEvent, extra) {
+ // this.debug("_trigger(" + type + ")", ctx);
+ var ctx = this._makeHookContext(this, originalEvent, extra),
+ res = this.widget._trigger(type, originalEvent, ctx);
+
+ if (res !== false && ctx.result !== undefined) {
+ return ctx.result;
+ }
+ return res;
+ },
+ /** Call fn(node) for all nodes in hierarchical order (depth-first).
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and children only.
+ * @returns {boolean} false, if the iterator was stopped.
+ */
+ visit: function (fn) {
+ return this.rootNode.visit(fn, false);
+ },
+ /** Call fn(node) for all nodes in vertical order, top down (or bottom up).<br>
+ * Stop iteration, if fn() returns false.<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and children only.
+ * @param {object} [options]
+ * Defaults:
+ * {start: First top node, reverse: false, includeSelf: true, includeHidden: false}
+ * @returns {boolean} false if iteration was cancelled
+ * @since 2.28
+ */
+ visitRows: function (fn, opts) {
+ if (!this.rootNode.hasChildren()) {
+ return false;
+ }
+ if (opts && opts.reverse) {
+ delete opts.reverse;
+ return this._visitRowsUp(fn, opts);
+ }
+ opts = opts || {};
+
+ var i,
+ nextIdx,
+ parent,
+ res,
+ siblings,
+ siblingOfs = 0,
+ skipFirstNode = opts.includeSelf === false,
+ includeHidden = !!opts.includeHidden,
+ checkFilter = !includeHidden && this.enableFilter,
+ node = opts.start || this.rootNode.children[0];
+
+ parent = node.parent;
+ while (parent) {
+ // visit siblings
+ siblings = parent.children;
+ nextIdx = siblings.indexOf(node) + siblingOfs;
+ _assert(
+ nextIdx >= 0,
+ "Could not find " +
+ node +
+ " in parent's children: " +
+ parent
+ );
+
+ for (i = nextIdx; i < siblings.length; i++) {
+ node = siblings[i];
+ if (checkFilter && !node.match && !node.subMatchCount) {
+ continue;
+ }
+ if (!skipFirstNode && fn(node) === false) {
+ return false;
+ }
+ skipFirstNode = false;
+ // Dive into node's child nodes
+ if (
+ node.children &&
+ node.children.length &&
+ (includeHidden || node.expanded)
+ ) {
+ // Disable warning: Functions declared within loops referencing an outer
+ // scoped variable may lead to confusing semantics:
+ /*jshint -W083 */
+ res = node.visit(function (n) {
+ if (checkFilter && !n.match && !n.subMatchCount) {
+ return "skip";
+ }
+ if (fn(n) === false) {
+ return false;
+ }
+ if (!includeHidden && n.children && !n.expanded) {
+ return "skip";
+ }
+ }, false);
+ /*jshint +W083 */
+ if (res === false) {
+ return false;
+ }
+ }
+ }
+ // Visit parent nodes (bottom up)
+ node = parent;
+ parent = parent.parent;
+ siblingOfs = 1; //
+ }
+ return true;
+ },
+ /* Call fn(node) for all nodes in vertical order, bottom up.
+ */
+ _visitRowsUp: function (fn, opts) {
+ var children,
+ idx,
+ parent,
+ includeHidden = !!opts.includeHidden,
+ node = opts.start || this.rootNode.children[0];
+
+ while (true) {
+ parent = node.parent;
+ children = parent.children;
+
+ if (children[0] === node) {
+ // If this is already the first sibling, goto parent
+ node = parent;
+ if (!node.parent) {
+ break; // first node of the tree
+ }
+ children = parent.children;
+ } else {
+ // Otherwise, goto prev. sibling
+ idx = children.indexOf(node);
+ node = children[idx - 1];
+ // If the prev. sibling has children, follow down to last descendant
+ while (
+ // See: https://github.com/eslint/eslint/issues/11302
+ // eslint-disable-next-line no-unmodified-loop-condition
+ (includeHidden || node.expanded) &&
+ node.children &&
+ node.children.length
+ ) {
+ children = node.children;
+ parent = node;
+ node = children[children.length - 1];
+ }
+ }
+ // Skip invisible
+ if (!includeHidden && !node.isVisible()) {
+ continue;
+ }
+ if (fn(node) === false) {
+ return false;
+ }
+ }
+ },
+ /** Write warning to browser console if debugLevel >= 2 (prepending tree info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ warn: function (msg) {
+ if (this.options.debugLevel >= 2) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("warn", arguments);
+ }
+ },
+ };
+
+ /**
+ * These additional methods of the {@link Fancytree} class are 'hook functions'
+ * that can be used and overloaded by extensions.
+ *
+ * @see [writing extensions](https://github.com/mar10/fancytree/wiki/TutorialExtensions)
+ * @mixin Fancytree_Hooks
+ */
+ $.extend(
+ Fancytree.prototype,
+ /** @lends Fancytree_Hooks# */
+ {
+ /** Default handling for mouse click events.
+ *
+ * @param {EventData} ctx
+ */
+ nodeClick: function (ctx) {
+ var activate,
+ expand,
+ // event = ctx.originalEvent,
+ targetType = ctx.targetType,
+ node = ctx.node;
+
+ // this.debug("ftnode.onClick(" + event.type + "): ftnode:" + this + ", button:" + event.button + ", which: " + event.which, ctx);
+ // TODO: use switch
+ // TODO: make sure clicks on embedded <input> doesn't steal focus (see table sample)
+ if (targetType === "expander") {
+ if (node.isLoading()) {
+ // #495: we probably got a click event while a lazy load is pending.
+ // The 'expanded' state is not yet set, so 'toggle' would expand
+ // and trigger lazyLoad again.
+ // It would be better to allow to collapse/expand the status node
+ // while loading (instead of ignoring), but that would require some
+ // more work.
+ node.debug("Got 2nd click while loading: ignored");
+ return;
+ }
+ // Clicking the expander icon always expands/collapses
+ this._callHook("nodeToggleExpanded", ctx);
+ } else if (targetType === "checkbox") {
+ // Clicking the checkbox always (de)selects
+ this._callHook("nodeToggleSelected", ctx);
+ if (ctx.options.focusOnSelect) {
+ // #358
+ this._callHook("nodeSetFocus", ctx, true);
+ }
+ } else {
+ // Honor `clickFolderMode` for
+ expand = false;
+ activate = true;
+ if (node.folder) {
+ switch (ctx.options.clickFolderMode) {
+ case 2: // expand only
+ expand = true;
+ activate = false;
+ break;
+ case 3: // expand and activate
+ activate = true;
+ expand = true; //!node.isExpanded();
+ break;
+ // else 1 or 4: just activate
+ }
+ }
+ if (activate) {
+ this.nodeSetFocus(ctx);
+ this._callHook("nodeSetActive", ctx, true);
+ }
+ if (expand) {
+ if (!activate) {
+ // this._callHook("nodeSetFocus", ctx);
+ }
+ // this._callHook("nodeSetExpanded", ctx, true);
+ this._callHook("nodeToggleExpanded", ctx);
+ }
+ }
+ // Make sure that clicks stop, otherwise <a href='#'> jumps to the top
+ // if(event.target.localName === "a" && event.target.className === "fancytree-title"){
+ // event.preventDefault();
+ // }
+ // TODO: return promise?
+ },
+ /** Collapse all other children of same parent.
+ *
+ * @param {EventData} ctx
+ * @param {object} callOpts
+ */
+ nodeCollapseSiblings: function (ctx, callOpts) {
+ // TODO: return promise?
+ var ac,
+ i,
+ l,
+ node = ctx.node;
+
+ if (node.parent) {
+ ac = node.parent.children;
+ for (i = 0, l = ac.length; i < l; i++) {
+ if (ac[i] !== node && ac[i].expanded) {
+ this._callHook(
+ "nodeSetExpanded",
+ ac[i],
+ false,
+ callOpts
+ );
+ }
+ }
+ }
+ },
+ /** Default handling for mouse douleclick events.
+ * @param {EventData} ctx
+ */
+ nodeDblclick: function (ctx) {
+ // TODO: return promise?
+ if (
+ ctx.targetType === "title" &&
+ ctx.options.clickFolderMode === 4
+ ) {
+ // this.nodeSetFocus(ctx);
+ // this._callHook("nodeSetActive", ctx, true);
+ this._callHook("nodeToggleExpanded", ctx);
+ }
+ // TODO: prevent text selection on dblclicks
+ if (ctx.targetType === "title") {
+ ctx.originalEvent.preventDefault();
+ }
+ },
+ /** Default handling for mouse keydown events.
+ *
+ * NOTE: this may be called with node == null if tree (but no node) has focus.
+ * @param {EventData} ctx
+ */
+ nodeKeydown: function (ctx) {
+ // TODO: return promise?
+ var matchNode,
+ stamp,
+ _res,
+ focusNode,
+ event = ctx.originalEvent,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ which = event.which,
+ // #909: Use event.key, to get unicode characters.
+ // We can't use `/\w/.test(key)`, because that would
+ // only detect plain ascii alpha-numerics. But we still need
+ // to ignore modifier-only, whitespace, cursor-keys, etc.
+ key = event.key || String.fromCharCode(which),
+ specialModifiers = !!(
+ event.altKey ||
+ event.ctrlKey ||
+ event.metaKey
+ ),
+ isAlnum =
+ !MODIFIERS[which] &&
+ !SPECIAL_KEYCODES[which] &&
+ !specialModifiers,
+ $target = $(event.target),
+ handled = true,
+ activate = !(event.ctrlKey || !opts.autoActivate);
+
+ // (node || FT).debug("ftnode.nodeKeydown(" + event.type + "): ftnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+ // FT.debug( "eventToString(): " + FT.eventToString(event) + ", key='" + key + "', isAlnum: " + isAlnum );
+
+ // Set focus to active (or first node) if no other node has the focus yet
+ if (!node) {
+ focusNode = this.getActiveNode() || this.getFirstChild();
+ if (focusNode) {
+ focusNode.setFocus();
+ node = ctx.node = this.focusNode;
+ node.debug("Keydown force focus on active node");
+ }
+ }
+
+ if (
+ opts.quicksearch &&
+ isAlnum &&
+ !$target.is(":input:enabled")
+ ) {
+ // Allow to search for longer streaks if typed in quickly
+ stamp = Date.now();
+ if (stamp - tree.lastQuicksearchTime > 500) {
+ tree.lastQuicksearchTerm = "";
+ }
+ tree.lastQuicksearchTime = stamp;
+ tree.lastQuicksearchTerm += key;
+ // tree.debug("quicksearch find", tree.lastQuicksearchTerm);
+ matchNode = tree.findNextNode(
+ tree.lastQuicksearchTerm,
+ tree.getActiveNode()
+ );
+ if (matchNode) {
+ matchNode.setActive();
+ }
+ event.preventDefault();
+ return;
+ }
+ switch (FT.eventToString(event)) {
+ case "+":
+ case "=": // 187: '+' @ Chrome, Safari
+ tree.nodeSetExpanded(ctx, true);
+ break;
+ case "-":
+ tree.nodeSetExpanded(ctx, false);
+ break;
+ case "space":
+ if (node.isPagingNode()) {
+ tree._triggerNodeEvent("clickPaging", ctx, event);
+ } else if (
+ FT.evalOption("checkbox", node, node, opts, false)
+ ) {
+ // #768
+ tree.nodeToggleSelected(ctx);
+ } else {
+ tree.nodeSetActive(ctx, true);
+ }
+ break;
+ case "return":
+ tree.nodeSetActive(ctx, true);
+ break;
+ case "home":
+ case "end":
+ case "backspace":
+ case "left":
+ case "right":
+ case "up":
+ case "down":
+ _res = node.navigate(event.which, activate);
+ break;
+ default:
+ handled = false;
+ }
+ if (handled) {
+ event.preventDefault();
+ }
+ },
+
+ // /** Default handling for mouse keypress events. */
+ // nodeKeypress: function(ctx) {
+ // var event = ctx.originalEvent;
+ // },
+
+ // /** Trigger lazyLoad event (async). */
+ // nodeLazyLoad: function(ctx) {
+ // var node = ctx.node;
+ // if(this._triggerNodeEvent())
+ // },
+ /** Load child nodes (async).
+ *
+ * @param {EventData} ctx
+ * @param {object[]|object|string|$.Promise|function} source
+ * @returns {$.Promise} The deferred will be resolved as soon as the (ajax)
+ * data was rendered.
+ */
+ nodeLoadChildren: function (ctx, source) {
+ var ajax,
+ delay,
+ ajaxDfd = null,
+ resultDfd,
+ isAsync = true,
+ tree = ctx.tree,
+ node = ctx.node,
+ nodePrevParent = node.parent,
+ tag = "nodeLoadChildren",
+ requestId = Date.now();
+
+ // `source` is a callback: use the returned result instead:
+ if (_isFunction(source)) {
+ source = source.call(tree, { type: "source" }, ctx);
+ _assert(
+ !_isFunction(source),
+ "source callback must not return another function"
+ );
+ }
+ // `source` is already a promise:
+ if (_isFunction(source.then)) {
+ // _assert(_isFunction(source.always), "Expected jQuery?");
+ ajaxDfd = source;
+ } else if (source.url) {
+ // `source` is an Ajax options object
+ ajax = $.extend({}, ctx.options.ajax, source);
+ if (ajax.debugDelay) {
+ // Simulate a slow server
+ delay = ajax.debugDelay;
+ delete ajax.debugDelay; // remove debug option
+ if (_isArray(delay)) {
+ // random delay range [min..max]
+ delay =
+ delay[0] +
+ Math.random() * (delay[1] - delay[0]);
+ }
+ node.warn(
+ "nodeLoadChildren waiting debugDelay " +
+ Math.round(delay) +
+ " ms ..."
+ );
+ ajaxDfd = $.Deferred(function (ajaxDfd) {
+ setTimeout(function () {
+ $.ajax(ajax)
+ .done(function () {
+ ajaxDfd.resolveWith(this, arguments);
+ })
+ .fail(function () {
+ ajaxDfd.rejectWith(this, arguments);
+ });
+ }, delay);
+ });
+ } else {
+ ajaxDfd = $.ajax(ajax);
+ }
+ } else if ($.isPlainObject(source) || _isArray(source)) {
+ // `source` is already a constant dict or list, but we convert
+ // to a thenable for unified processing.
+ // 2020-01-03: refactored.
+ // `ajaxDfd = $.when(source)` would do the trick, but the returned
+ // promise will resolve async, which broke some tests and
+ // would probably also break current implementations out there.
+ // So we mock-up a thenable that resolves synchronously:
+ ajaxDfd = {
+ then: function (resolve, reject) {
+ resolve(source, null, null);
+ },
+ };
+ isAsync = false;
+ } else {
+ $.error("Invalid source type: " + source);
+ }
+
+ // Check for overlapping requests
+ if (node._requestId) {
+ node.warn(
+ "Recursive load request #" +
+ requestId +
+ " while #" +
+ node._requestId +
+ " is pending."
+ );
+ node._requestId = requestId;
+ // node.debug("Send load request #" + requestId);
+ }
+
+ if (isAsync) {
+ tree.debugTime(tag);
+ tree.nodeSetStatus(ctx, "loading");
+ }
+
+ // The async Ajax request has now started...
+ // Defer the deferred:
+ // we want to be able to reject invalid responses, even if
+ // the raw HTTP Ajax XHR resolved as Ok.
+ // We use the ajaxDfd.then() syntax here, which is compatible with
+ // jQuery and ECMA6.
+ // However resultDfd is a jQuery deferred, which is currently the
+ // expected result type of nodeLoadChildren()
+ resultDfd = new $.Deferred();
+ ajaxDfd.then(
+ function (data, textStatus, jqXHR) {
+ // ajaxDfd was resolved, but we reject or resolve resultDfd
+ // depending on the response data
+ var errorObj, res;
+
+ if (
+ (source.dataType === "json" ||
+ source.dataType === "jsonp") &&
+ typeof data === "string"
+ ) {
+ $.error(
+ "Ajax request returned a string (did you get the JSON dataType wrong?)."
+ );
+ }
+ if (node._requestId && node._requestId > requestId) {
+ // The expected request time stamp is later than `requestId`
+ // (which was kept as as closure variable to this handler function)
+ // node.warn("Ignored load response for obsolete request #" + requestId + " (expected #" + node._requestId + ")");
+ resultDfd.rejectWith(this, [
+ RECURSIVE_REQUEST_ERROR,
+ ]);
+ return;
+ // } else {
+ // node.debug("Response returned for load request #" + requestId);
+ }
+ if (node.parent === null && nodePrevParent !== null) {
+ resultDfd.rejectWith(this, [
+ INVALID_REQUEST_TARGET_ERROR,
+ ]);
+ return;
+ }
+ // Allow to adjust the received response data in the `postProcess` event.
+ if (ctx.options.postProcess) {
+ // The handler may either
+ // - modify `ctx.response` in-place (and leave `ctx.result` undefined)
+ // => res = undefined
+ // - return a replacement in `ctx.result`
+ // => res = <new data>
+ // If res contains an `error` property, an error status is displayed
+ try {
+ res = tree._triggerNodeEvent(
+ "postProcess",
+ ctx,
+ ctx.originalEvent,
+ {
+ response: data,
+ error: null,
+ dataType: source.dataType,
+ }
+ );
+ if (res.error) {
+ tree.warn(
+ "postProcess returned error:",
+ res
+ );
+ }
+ } catch (e) {
+ res = {
+ error: e,
+ message: "" + e,
+ details: "postProcess failed",
+ };
+ }
+ if (res.error) {
+ // Either postProcess failed with an exception, or the returned
+ // result object has an 'error' property attached:
+ errorObj = $.isPlainObject(res.error)
+ ? res.error
+ : { message: res.error };
+ errorObj = tree._makeHookContext(
+ node,
+ null,
+ errorObj
+ );
+ resultDfd.rejectWith(this, [errorObj]);
+ return;
+ }
+ if (
+ _isArray(res) ||
+ ($.isPlainObject(res) && _isArray(res.children))
+ ) {
+ // Use `ctx.result` if valid
+ // (otherwise use existing data, which may have been modified in-place)
+ data = res;
+ }
+ } else if (
+ data &&
+ _hasProp(data, "d") &&
+ ctx.options.enableAspx
+ ) {
+ // Process ASPX WebMethod JSON object inside "d" property
+ // (only if no postProcess event was defined)
+ if (ctx.options.enableAspx === 42) {
+ tree.warn(
+ "The default for enableAspx will change to `false` in the fututure. " +
+ "Pass `enableAspx: true` or implement postProcess to silence this warning."
+ );
+ }
+ data =
+ typeof data.d === "string"
+ ? $.parseJSON(data.d)
+ : data.d;
+ }
+ resultDfd.resolveWith(this, [data]);
+ },
+ function (jqXHR, textStatus, errorThrown) {
+ // ajaxDfd was rejected, so we reject resultDfd as well
+ var errorObj = tree._makeHookContext(node, null, {
+ error: jqXHR,
+ args: Array.prototype.slice.call(arguments),
+ message: errorThrown,
+ details: jqXHR.status + ": " + errorThrown,
+ });
+ resultDfd.rejectWith(this, [errorObj]);
+ }
+ );
+
+ // The async Ajax request has now started.
+ // resultDfd will be resolved/rejected after the response arrived,
+ // was postProcessed, and checked.
+ // Now we implement the UI update and add the data to the tree.
+ // We also return this promise to the caller.
+ resultDfd
+ .done(function (data) {
+ tree.nodeSetStatus(ctx, "ok");
+ var children, metaData, noDataRes;
+
+ if ($.isPlainObject(data)) {
+ // We got {foo: 'abc', children: [...]}
+ // Copy extra properties to tree.data.foo
+ _assert(
+ node.isRootNode(),
+ "source may only be an object for root nodes (expecting an array of child objects otherwise)"
+ );
+ _assert(
+ _isArray(data.children),
+ "if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"
+ );
+ metaData = data;
+ children = data.children;
+ delete metaData.children;
+ // Copy some attributes to tree.data
+ $.each(TREE_ATTRS, function (i, attr) {
+ if (metaData[attr] !== undefined) {
+ tree[attr] = metaData[attr];
+ delete metaData[attr];
+ }
+ });
+ // Copy all other attributes to tree.data.NAME
+ $.extend(tree.data, metaData);
+ } else {
+ children = data;
+ }
+ _assert(
+ _isArray(children),
+ "expected array of children"
+ );
+ node._setChildren(children);
+
+ if (tree.options.nodata && children.length === 0) {
+ if (_isFunction(tree.options.nodata)) {
+ noDataRes = tree.options.nodata.call(
+ tree,
+ { type: "nodata" },
+ ctx
+ );
+ } else if (
+ tree.options.nodata === true &&
+ node.isRootNode()
+ ) {
+ noDataRes = tree.options.strings.noData;
+ } else if (
+ typeof tree.options.nodata === "string" &&
+ node.isRootNode()
+ ) {
+ noDataRes = tree.options.nodata;
+ }
+ if (noDataRes) {
+ node.setStatus("nodata", noDataRes);
+ }
+ }
+ // trigger fancytreeloadchildren
+ tree._triggerNodeEvent("loadChildren", node);
+ })
+ .fail(function (error) {
+ var ctxErr;
+
+ if (error === RECURSIVE_REQUEST_ERROR) {
+ node.warn(
+ "Ignored response for obsolete load request #" +
+ requestId +
+ " (expected #" +
+ node._requestId +
+ ")"
+ );
+ return;
+ } else if (error === INVALID_REQUEST_TARGET_ERROR) {
+ node.warn(
+ "Lazy parent node was removed while loading: discarding response."
+ );
+ return;
+ } else if (error.node && error.error && error.message) {
+ // error is already a context object
+ ctxErr = error;
+ } else {
+ ctxErr = tree._makeHookContext(node, null, {
+ error: error, // it can be jqXHR or any custom error
+ args: Array.prototype.slice.call(arguments),
+ message: error
+ ? error.message || error.toString()
+ : "",
+ });
+ if (ctxErr.message === "[object Object]") {
+ ctxErr.message = "";
+ }
+ }
+ node.warn(
+ "Load children failed (" + ctxErr.message + ")",
+ ctxErr
+ );
+ if (
+ tree._triggerNodeEvent(
+ "loadError",
+ ctxErr,
+ null
+ ) !== false
+ ) {
+ tree.nodeSetStatus(
+ ctx,
+ "error",
+ ctxErr.message,
+ ctxErr.details
+ );
+ }
+ })
+ .always(function () {
+ node._requestId = null;
+ if (isAsync) {
+ tree.debugTimeEnd(tag);
+ }
+ });
+
+ return resultDfd.promise();
+ },
+ /** [Not Implemented] */
+ nodeLoadKeyPath: function (ctx, keyPathList) {
+ // TODO: implement and improve
+ // http://code.google.com/p/dynatree/issues/detail?id=222
+ },
+ /**
+ * Remove a single direct child of ctx.node.
+ * @param {EventData} ctx
+ * @param {FancytreeNode} childNode dircect child of ctx.node
+ */
+ nodeRemoveChild: function (ctx, childNode) {
+ var idx,
+ node = ctx.node,
+ // opts = ctx.options,
+ subCtx = $.extend({}, ctx, { node: childNode }),
+ children = node.children;
+
+ // FT.debug("nodeRemoveChild()", node.toString(), childNode.toString());
+
+ if (children.length === 1) {
+ _assert(childNode === children[0], "invalid single child");
+ return this.nodeRemoveChildren(ctx);
+ }
+ if (
+ this.activeNode &&
+ (childNode === this.activeNode ||
+ this.activeNode.isDescendantOf(childNode))
+ ) {
+ this.activeNode.setActive(false); // TODO: don't fire events
+ }
+ if (
+ this.focusNode &&
+ (childNode === this.focusNode ||
+ this.focusNode.isDescendantOf(childNode))
+ ) {
+ this.focusNode = null;
+ }
+ // TODO: persist must take care to clear select and expand cookies
+ this.nodeRemoveMarkup(subCtx);
+ this.nodeRemoveChildren(subCtx);
+ idx = $.inArray(childNode, children);
+ _assert(idx >= 0, "invalid child");
+ // Notify listeners
+ node.triggerModifyChild("remove", childNode);
+ // Unlink to support GC
+ childNode.visit(function (n) {
+ n.parent = null;
+ }, true);
+ this._callHook("treeRegisterNode", this, false, childNode);
+ // remove from child list
+ children.splice(idx, 1);
+ },
+ /**Remove HTML markup for all descendents of ctx.node.
+ * @param {EventData} ctx
+ */
+ nodeRemoveChildMarkup: function (ctx) {
+ var node = ctx.node;
+
+ // FT.debug("nodeRemoveChildMarkup()", node.toString());
+ // TODO: Unlink attr.ftnode to support GC
+ if (node.ul) {
+ if (node.isRootNode()) {
+ $(node.ul).empty();
+ } else {
+ $(node.ul).remove();
+ node.ul = null;
+ }
+ node.visit(function (n) {
+ n.li = n.ul = null;
+ });
+ }
+ },
+ /**Remove all descendants of ctx.node.
+ * @param {EventData} ctx
+ */
+ nodeRemoveChildren: function (ctx) {
+ var //subCtx,
+ tree = ctx.tree,
+ node = ctx.node,
+ children = node.children;
+ // opts = ctx.options;
+
+ // FT.debug("nodeRemoveChildren()", node.toString());
+ if (!children) {
+ return;
+ }
+ if (this.activeNode && this.activeNode.isDescendantOf(node)) {
+ this.activeNode.setActive(false); // TODO: don't fire events
+ }
+ if (this.focusNode && this.focusNode.isDescendantOf(node)) {
+ this.focusNode = null;
+ }
+ // TODO: persist must take care to clear select and expand cookies
+ this.nodeRemoveChildMarkup(ctx);
+ // Unlink children to support GC
+ // TODO: also delete this.children (not possible using visit())
+ // subCtx = $.extend({}, ctx);
+ node.triggerModifyChild("remove", null);
+ node.visit(function (n) {
+ n.parent = null;
+ tree._callHook("treeRegisterNode", tree, false, n);
+ });
+ if (node.lazy) {
+ // 'undefined' would be interpreted as 'not yet loaded' for lazy nodes
+ node.children = [];
+ } else {
+ node.children = null;
+ }
+ if (!node.isRootNode()) {
+ node.expanded = false; // #449, #459
+ }
+ this.nodeRenderStatus(ctx);
+ },
+ /**Remove HTML markup for ctx.node and all its descendents.
+ * @param {EventData} ctx
+ */
+ nodeRemoveMarkup: function (ctx) {
+ var node = ctx.node;
+ // FT.debug("nodeRemoveMarkup()", node.toString());
+ // TODO: Unlink attr.ftnode to support GC
+ if (node.li) {
+ $(node.li).remove();
+ node.li = null;
+ }
+ this.nodeRemoveChildMarkup(ctx);
+ },
+ /**
+ * Create `<li><span>..</span> .. </li>` tags for this node.
+ *
+ * This method takes care that all HTML markup is created that is required
+ * to display this node in its current state.
+ *
+ * Call this method to create new nodes, or after the strucuture
+ * was changed (e.g. after moving this node or adding/removing children)
+ * nodeRenderTitle() and nodeRenderStatus() are implied.
+ *
+ * ```html
+ * <li id='KEY' ftnode=NODE>
+ * <span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'>
+ * <span class="fancytree-expander"></span>
+ * <span class="fancytree-checkbox"></span> // only present in checkbox mode
+ * <span class="fancytree-icon"></span>
+ * <a href="#" class="fancytree-title"> Node 1 </a>
+ * </span>
+ * <ul> // only present if node has children
+ * <li id='KEY' ftnode=NODE> child1 ... </li>
+ * <li id='KEY' ftnode=NODE> child2 ... </li>
+ * </ul>
+ * </li>
+ * ```
+ *
+ * @param {EventData} ctx
+ * @param {boolean} [force=false] re-render, even if html markup was already created
+ * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+ * @param {boolean} [collapsed=false] force root node to be collapsed, so we can apply animated expand later
+ */
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ /* This method must take care of all cases where the current data mode
+ * (i.e. node hierarchy) does not match the current markup.
+ *
+ * - node was not yet rendered:
+ * create markup
+ * - node was rendered: exit fast
+ * - children have been added
+ * - children have been removed
+ */
+ var childLI,
+ childNode1,
+ childNode2,
+ i,
+ l,
+ next,
+ subCtx,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ aria = opts.aria,
+ firstTime = false,
+ parent = node.parent,
+ isRootNode = !parent,
+ children = node.children,
+ successorLi = null;
+ // FT.debug("nodeRender(" + !!force + ", " + !!deep + ")", node.toString());
+
+ if (tree._enableUpdate === false) {
+ // tree.debug("no render", tree._enableUpdate);
+ return;
+ }
+ if (!isRootNode && !parent.ul) {
+ // Calling node.collapse on a deep, unrendered node
+ return;
+ }
+ _assert(isRootNode || parent.ul, "parent UL must exist");
+
+ // Render the node
+ if (!isRootNode) {
+ // Discard markup on force-mode, or if it is not linked to parent <ul>
+ if (
+ node.li &&
+ (force || node.li.parentNode !== node.parent.ul)
+ ) {
+ if (node.li.parentNode === node.parent.ul) {
+ // #486: store following node, so we can insert the new markup there later
+ successorLi = node.li.nextSibling;
+ } else {
+ // May happen, when a top-level node was dropped over another
+ this.debug(
+ "Unlinking " +
+ node +
+ " (must be child of " +
+ node.parent +
+ ")"
+ );
+ }
+ // this.debug("nodeRemoveMarkup...");
+ this.nodeRemoveMarkup(ctx);
+ }
+ // Create <li><span /> </li>
+ // node.debug("render...");
+ if (node.li) {
+ // this.nodeRenderTitle(ctx);
+ this.nodeRenderStatus(ctx);
+ } else {
+ // node.debug("render... really");
+ firstTime = true;
+ node.li = document.createElement("li");
+ node.li.ftnode = node;
+
+ if (node.key && opts.generateIds) {
+ node.li.id = opts.idPrefix + node.key;
+ }
+ node.span = document.createElement("span");
+ node.span.className = "fancytree-node";
+ if (aria && !node.tr) {
+ $(node.li).attr("role", "treeitem");
+ }
+ node.li.appendChild(node.span);
+
+ // Create inner HTML for the <span> (expander, checkbox, icon, and title)
+ this.nodeRenderTitle(ctx);
+
+ // Allow tweaking and binding, after node was created for the first time
+ if (opts.createNode) {
+ opts.createNode.call(
+ tree,
+ { type: "createNode" },
+ ctx
+ );
+ }
+ }
+ // Allow tweaking after node state was rendered
+ if (opts.renderNode) {
+ opts.renderNode.call(tree, { type: "renderNode" }, ctx);
+ }
+ }
+
+ // Visit child nodes
+ if (children) {
+ if (isRootNode || node.expanded || deep === true) {
+ // Create a UL to hold the children
+ if (!node.ul) {
+ node.ul = document.createElement("ul");
+ if (
+ (collapsed === true && !_recursive) ||
+ !node.expanded
+ ) {
+ // hide top UL, so we can use an animation to show it later
+ node.ul.style.display = "none";
+ }
+ if (aria) {
+ $(node.ul).attr("role", "group");
+ }
+ if (node.li) {
+ // issue #67
+ node.li.appendChild(node.ul);
+ } else {
+ node.tree.$div.append(node.ul);
+ }
+ }
+ // Add child markup
+ for (i = 0, l = children.length; i < l; i++) {
+ subCtx = $.extend({}, ctx, { node: children[i] });
+ this.nodeRender(subCtx, force, deep, false, true);
+ }
+ // Remove <li> if nodes have moved to another parent
+ childLI = node.ul.firstChild;
+ while (childLI) {
+ childNode2 = childLI.ftnode;
+ if (childNode2 && childNode2.parent !== node) {
+ node.debug(
+ "_fixParent: remove missing " + childNode2,
+ childLI
+ );
+ next = childLI.nextSibling;
+ childLI.parentNode.removeChild(childLI);
+ childLI = next;
+ } else {
+ childLI = childLI.nextSibling;
+ }
+ }
+ // Make sure, that <li> order matches node.children order.
+ childLI = node.ul.firstChild;
+ for (i = 0, l = children.length - 1; i < l; i++) {
+ childNode1 = children[i];
+ childNode2 = childLI.ftnode;
+ if (childNode1 === childNode2) {
+ childLI = childLI.nextSibling;
+ } else {
+ // node.debug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2);
+ node.ul.insertBefore(
+ childNode1.li,
+ childNode2.li
+ );
+ }
+ }
+ }
+ } else {
+ // No children: remove markup if any
+ if (node.ul) {
+ // alert("remove child markup for " + node);
+ this.warn("remove child markup for " + node);
+ this.nodeRemoveChildMarkup(ctx);
+ }
+ }
+ if (!isRootNode) {
+ // Update element classes according to node state
+ // this.nodeRenderStatus(ctx);
+ // Finally add the whole structure to the DOM, so the browser can render
+ if (firstTime) {
+ // #486: successorLi is set, if we re-rendered (i.e. discarded)
+ // existing markup, which we want to insert at the same position.
+ // (null is equivalent to append)
+ // parent.ul.appendChild(node.li);
+ parent.ul.insertBefore(node.li, successorLi);
+ }
+ }
+ },
+ /** Create HTML inside the node's outer `<span>` (i.e. expander, checkbox,
+ * icon, and title).
+ *
+ * nodeRenderStatus() is implied.
+ * @param {EventData} ctx
+ * @param {string} [title] optinal new title
+ */
+ nodeRenderTitle: function (ctx, title) {
+ // set node connector images, links and text
+ var checkbox,
+ className,
+ icon,
+ nodeTitle,
+ role,
+ tabindex,
+ tooltip,
+ iconTooltip,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ aria = opts.aria,
+ level = node.getLevel(),
+ ares = [];
+
+ if (title !== undefined) {
+ node.title = title;
+ }
+ if (!node.span || tree._enableUpdate === false) {
+ // Silently bail out if node was not rendered yet, assuming
+ // node.render() will be called as the node becomes visible
+ return;
+ }
+ // Connector (expanded, expandable or simple)
+ role =
+ aria && node.hasChildren() !== false
+ ? " role='button'"
+ : "";
+ if (level < opts.minExpandLevel) {
+ if (!node.lazy) {
+ node.expanded = true;
+ }
+ if (level > 1) {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-expander fancytree-expander-fixed'></span>"
+ );
+ }
+ // .. else (i.e. for root level) skip expander/connector alltogether
+ } else {
+ ares.push(
+ "<span " + role + " class='fancytree-expander'></span>"
+ );
+ }
+ // Checkbox mode
+ checkbox = FT.evalOption("checkbox", node, node, opts, false);
+
+ if (checkbox && !node.isStatusNode()) {
+ role = aria ? " role='checkbox'" : "";
+ className = "fancytree-checkbox";
+ if (
+ checkbox === "radio" ||
+ (node.parent && node.parent.radiogroup)
+ ) {
+ className += " fancytree-radio";
+ }
+ ares.push(
+ "<span " + role + " class='" + className + "'></span>"
+ );
+ }
+ // Folder or doctype icon
+ if (node.data.iconClass !== undefined) {
+ // 2015-11-16
+ // Handle / warn about backward compatibility
+ if (node.icon) {
+ $.error(
+ "'iconClass' node option is deprecated since v2.14.0: use 'icon' only instead"
+ );
+ } else {
+ node.warn(
+ "'iconClass' node option is deprecated since v2.14.0: use 'icon' instead"
+ );
+ node.icon = node.data.iconClass;
+ }
+ }
+ // If opts.icon is a callback and returns something other than undefined, use that
+ // else if node.icon is a boolean or string, use that
+ // else if opts.icon is a boolean or string, use that
+ // else show standard icon (which may be different for folders or documents)
+ icon = FT.evalOption("icon", node, node, opts, true);
+ // if( typeof icon !== "boolean" ) {
+ // // icon is defined, but not true/false: must be a string
+ // icon = "" + icon;
+ // }
+ if (icon !== false) {
+ role = aria ? " role='presentation'" : "";
+
+ iconTooltip = FT.evalOption(
+ "iconTooltip",
+ node,
+ node,
+ opts,
+ null
+ );
+ iconTooltip = iconTooltip
+ ? " title='" + _escapeTooltip(iconTooltip) + "'"
+ : "";
+
+ if (typeof icon === "string") {
+ if (TEST_IMG.test(icon)) {
+ // node.icon is an image url. Prepend imagePath
+ icon =
+ icon.charAt(0) === "/"
+ ? icon
+ : (opts.imagePath || "") + icon;
+ ares.push(
+ "<img src='" +
+ icon +
+ "' class='fancytree-icon'" +
+ iconTooltip +
+ " alt='' />"
+ );
+ } else {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-custom-icon " +
+ icon +
+ "'" +
+ iconTooltip +
+ "></span>"
+ );
+ }
+ } else if (icon.text) {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-custom-icon " +
+ (icon.addClass || "") +
+ "'" +
+ iconTooltip +
+ ">" +
+ FT.escapeHtml(icon.text) +
+ "</span>"
+ );
+ } else if (icon.html) {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-custom-icon " +
+ (icon.addClass || "") +
+ "'" +
+ iconTooltip +
+ ">" +
+ icon.html +
+ "</span>"
+ );
+ } else {
+ // standard icon: theme css will take care of this
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-icon'" +
+ iconTooltip +
+ "></span>"
+ );
+ }
+ }
+ // Node title
+ nodeTitle = "";
+ if (opts.renderTitle) {
+ nodeTitle =
+ opts.renderTitle.call(
+ tree,
+ { type: "renderTitle" },
+ ctx
+ ) || "";
+ }
+ if (!nodeTitle) {
+ tooltip = FT.evalOption("tooltip", node, node, opts, null);
+ if (tooltip === true) {
+ tooltip = node.title;
+ }
+ // if( node.tooltip ) {
+ // tooltip = node.tooltip;
+ // } else if ( opts.tooltip ) {
+ // tooltip = opts.tooltip === true ? node.title : opts.tooltip.call(tree, node);
+ // }
+ tooltip = tooltip
+ ? " title='" + _escapeTooltip(tooltip) + "'"
+ : "";
+ tabindex = opts.titlesTabbable ? " tabindex='0'" : "";
+
+ nodeTitle =
+ "<span class='fancytree-title'" +
+ tooltip +
+ tabindex +
+ ">" +
+ (opts.escapeTitles
+ ? FT.escapeHtml(node.title)
+ : node.title) +
+ "</span>";
+ }
+ ares.push(nodeTitle);
+ // Note: this will trigger focusout, if node had the focus
+ //$(node.span).html(ares.join("")); // it will cleanup the jQuery data currently associated with SPAN (if any), but it executes more slowly
+ node.span.innerHTML = ares.join("");
+ // Update CSS classes
+ this.nodeRenderStatus(ctx);
+ if (opts.enhanceTitle) {
+ ctx.$title = $(">span.fancytree-title", node.span);
+ nodeTitle =
+ opts.enhanceTitle.call(
+ tree,
+ { type: "enhanceTitle" },
+ ctx
+ ) || "";
+ }
+ },
+ /** Update element classes according to node state.
+ * @param {EventData} ctx
+ */
+ nodeRenderStatus: function (ctx) {
+ // Set classes for current status
+ var $ariaElem,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ // nodeContainer = node[tree.nodeContainerAttrName],
+ hasChildren = node.hasChildren(),
+ isLastSib = node.isLastSibling(),
+ aria = opts.aria,
+ cn = opts._classNames,
+ cnList = [],
+ statusElem = node[tree.statusClassPropName];
+
+ if (!statusElem || tree._enableUpdate === false) {
+ // if this function is called for an unrendered node, ignore it (will be updated on nect render anyway)
+ return;
+ }
+ if (aria) {
+ $ariaElem = $(node.tr || node.li);
+ }
+ // Build a list of class names that we will add to the node <span>
+ cnList.push(cn.node);
+ if (tree.activeNode === node) {
+ cnList.push(cn.active);
+ // $(">span.fancytree-title", statusElem).attr("tabindex", "0");
+ // tree.$container.removeAttr("tabindex");
+ // }else{
+ // $(">span.fancytree-title", statusElem).removeAttr("tabindex");
+ // tree.$container.attr("tabindex", "0");
+ }
+ if (tree.focusNode === node) {
+ cnList.push(cn.focused);
+ }
+ if (node.expanded) {
+ cnList.push(cn.expanded);
+ }
+ if (aria) {
+ if (hasChildren === false) {
+ $ariaElem.removeAttr("aria-expanded");
+ } else {
+ $ariaElem.attr("aria-expanded", Boolean(node.expanded));
+ }
+ }
+ if (node.folder) {
+ cnList.push(cn.folder);
+ }
+ if (hasChildren !== false) {
+ cnList.push(cn.hasChildren);
+ }
+ // TODO: required?
+ if (isLastSib) {
+ cnList.push(cn.lastsib);
+ }
+ if (node.lazy && node.children == null) {
+ cnList.push(cn.lazy);
+ }
+ if (node.partload) {
+ cnList.push(cn.partload);
+ }
+ if (node.partsel) {
+ cnList.push(cn.partsel);
+ }
+ if (FT.evalOption("unselectable", node, node, opts, false)) {
+ cnList.push(cn.unselectable);
+ }
+ if (node._isLoading) {
+ cnList.push(cn.loading);
+ }
+ if (node._error) {
+ cnList.push(cn.error);
+ }
+ if (node.statusNodeType) {
+ cnList.push(cn.statusNodePrefix + node.statusNodeType);
+ }
+ if (node.selected) {
+ cnList.push(cn.selected);
+ if (aria) {
+ $ariaElem.attr("aria-selected", true);
+ }
+ } else if (aria) {
+ $ariaElem.attr("aria-selected", false);
+ }
+ if (node.extraClasses) {
+ cnList.push(node.extraClasses);
+ }
+ // IE6 doesn't correctly evaluate multiple class names,
+ // so we create combined class names that can be used in the CSS
+ if (hasChildren === false) {
+ cnList.push(
+ cn.combinedExpanderPrefix + "n" + (isLastSib ? "l" : "")
+ );
+ } else {
+ cnList.push(
+ cn.combinedExpanderPrefix +
+ (node.expanded ? "e" : "c") +
+ (node.lazy && node.children == null ? "d" : "") +
+ (isLastSib ? "l" : "")
+ );
+ }
+ cnList.push(
+ cn.combinedIconPrefix +
+ (node.expanded ? "e" : "c") +
+ (node.folder ? "f" : "")
+ );
+ // node.span.className = cnList.join(" ");
+ statusElem.className = cnList.join(" ");
+
+ // TODO: we should not set this in the <span> tag also, if we set it here:
+ // Maybe most (all) of the classes should be set in LI instead of SPAN?
+ if (node.li) {
+ // #719: we have to consider that there may be already other classes:
+ $(node.li).toggleClass(cn.lastsib, isLastSib);
+ }
+ },
+ /** Activate node.
+ * flag defaults to true.
+ * If flag is true, the node is activated (must be a synchronous operation)
+ * If flag is false, the node is deactivated (must be a synchronous operation)
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}
+ * @returns {$.Promise}
+ */
+ nodeSetActive: function (ctx, flag, callOpts) {
+ // Handle user click / [space] / [enter], according to clickFolderMode.
+ callOpts = callOpts || {};
+ var subCtx,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ noEvents = callOpts.noEvents === true,
+ noFocus = callOpts.noFocus === true,
+ scroll = callOpts.scrollIntoView !== false,
+ isActive = node === tree.activeNode;
+
+ // flag defaults to true
+ flag = flag !== false;
+ // node.debug("nodeSetActive", flag);
+
+ if (isActive === flag) {
+ // Nothing to do
+ return _getResolvedPromise(node);
+ }
+ // #1042: don't scroll between mousedown/-up when clicking an embedded link
+ if (
+ scroll &&
+ ctx.originalEvent &&
+ $(ctx.originalEvent.target).is("a,:checkbox")
+ ) {
+ node.info("Not scrolling while clicking an embedded link.");
+ scroll = false;
+ }
+ if (
+ flag &&
+ !noEvents &&
+ this._triggerNodeEvent(
+ "beforeActivate",
+ node,
+ ctx.originalEvent
+ ) === false
+ ) {
+ // Callback returned false
+ return _getRejectedPromise(node, ["rejected"]);
+ }
+ if (flag) {
+ if (tree.activeNode) {
+ _assert(
+ tree.activeNode !== node,
+ "node was active (inconsistency)"
+ );
+ subCtx = $.extend({}, ctx, { node: tree.activeNode });
+ tree.nodeSetActive(subCtx, false);
+ _assert(
+ tree.activeNode === null,
+ "deactivate was out of sync?"
+ );
+ }
+
+ if (opts.activeVisible) {
+ // If no focus is set (noFocus: true) and there is no focused node, this node is made visible.
+ // scroll = noFocus && tree.focusNode == null;
+ // #863: scroll by default (unless `scrollIntoView: false` was passed)
+ node.makeVisible({ scrollIntoView: scroll });
+ }
+ tree.activeNode = node;
+ tree.nodeRenderStatus(ctx);
+ if (!noFocus) {
+ tree.nodeSetFocus(ctx);
+ }
+ if (!noEvents) {
+ tree._triggerNodeEvent(
+ "activate",
+ node,
+ ctx.originalEvent
+ );
+ }
+ } else {
+ _assert(
+ tree.activeNode === node,
+ "node was not active (inconsistency)"
+ );
+ tree.activeNode = null;
+ this.nodeRenderStatus(ctx);
+ if (!noEvents) {
+ ctx.tree._triggerNodeEvent(
+ "deactivate",
+ node,
+ ctx.originalEvent
+ );
+ }
+ }
+ return _getResolvedPromise(node);
+ },
+ /** Expand or collapse node, return Deferred.promise.
+ *
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ * @param {object} [opts] additional options. Defaults to `{noAnimation: false, noEvents: false}`
+ * @returns {$.Promise} The deferred will be resolved as soon as the (lazy)
+ * data was retrieved, rendered, and the expand animation finished.
+ */
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ callOpts = callOpts || {};
+ var _afterLoad,
+ dfd,
+ i,
+ l,
+ parents,
+ prevAC,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ noAnimation = callOpts.noAnimation === true,
+ noEvents = callOpts.noEvents === true;
+
+ // flag defaults to true
+ flag = flag !== false;
+
+ // node.debug("nodeSetExpanded(" + flag + ")");
+
+ if ($(node.li).hasClass(opts._classNames.animating)) {
+ node.warn(
+ "setExpanded(" + flag + ") while animating: ignored."
+ );
+ return _getRejectedPromise(node, ["recursion"]);
+ }
+
+ if ((node.expanded && flag) || (!node.expanded && !flag)) {
+ // Nothing to do
+ // node.debug("nodeSetExpanded(" + flag + "): nothing to do");
+ return _getResolvedPromise(node);
+ } else if (flag && !node.lazy && !node.hasChildren()) {
+ // Prevent expanding of empty nodes
+ // return _getRejectedPromise(node, ["empty"]);
+ return _getResolvedPromise(node);
+ } else if (!flag && node.getLevel() < opts.minExpandLevel) {
+ // Prevent collapsing locked levels
+ return _getRejectedPromise(node, ["locked"]);
+ } else if (
+ !noEvents &&
+ this._triggerNodeEvent(
+ "beforeExpand",
+ node,
+ ctx.originalEvent
+ ) === false
+ ) {
+ // Callback returned false
+ return _getRejectedPromise(node, ["rejected"]);
+ }
+ // If this node inside a collpased node, no animation and scrolling is needed
+ if (!noAnimation && !node.isVisible()) {
+ noAnimation = callOpts.noAnimation = true;
+ }
+
+ dfd = new $.Deferred();
+
+ // Auto-collapse mode: collapse all siblings
+ if (flag && !node.expanded && opts.autoCollapse) {
+ parents = node.getParentList(false, true);
+ prevAC = opts.autoCollapse;
+ try {
+ opts.autoCollapse = false;
+ for (i = 0, l = parents.length; i < l; i++) {
+ // TODO: should return promise?
+ this._callHook(
+ "nodeCollapseSiblings",
+ parents[i],
+ callOpts
+ );
+ }
+ } finally {
+ opts.autoCollapse = prevAC;
+ }
+ }
+ // Trigger expand/collapse after expanding
+ dfd.done(function () {
+ var lastChild = node.getLastChild();
+
+ if (
+ flag &&
+ opts.autoScroll &&
+ !noAnimation &&
+ lastChild &&
+ tree._enableUpdate
+ ) {
+ // Scroll down to last child, but keep current node visible
+ lastChild
+ .scrollIntoView(true, { topNode: node })
+ .always(function () {
+ if (!noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ });
+ } else {
+ if (!noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ }
+ });
+ // vvv Code below is executed after loading finished:
+ _afterLoad = function (callback) {
+ var cn = opts._classNames,
+ isVisible,
+ isExpanded,
+ effect = opts.toggleEffect;
+
+ node.expanded = flag;
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ flag ? "expand" : "collapse"
+ );
+ // Create required markup, but make sure the top UL is hidden, so we
+ // can animate later
+ tree._callHook("nodeRender", ctx, false, false, true);
+
+ // Hide children, if node is collapsed
+ if (node.ul) {
+ isVisible = node.ul.style.display !== "none";
+ isExpanded = !!node.expanded;
+ if (isVisible === isExpanded) {
+ node.warn(
+ "nodeSetExpanded: UL.style.display already set"
+ );
+ } else if (!effect || noAnimation) {
+ node.ul.style.display =
+ node.expanded || !parent ? "" : "none";
+ } else {
+ // The UI toggle() effect works with the ext-wide extension,
+ // while jQuery.animate() has problems when the title span
+ // has position: absolute.
+ // Since jQuery UI 1.12, the blind effect requires the parent
+ // element to have 'position: relative'.
+ // See #716, #717
+ $(node.li).addClass(cn.animating); // #717
+
+ if (_isFunction($(node.ul)[effect.effect])) {
+ // tree.debug( "use jquery." + effect.effect + " method" );
+ $(node.ul)[effect.effect]({
+ duration: effect.duration,
+ always: function () {
+ // node.debug("fancytree-animating end: " + node.li.className);
+ $(this).removeClass(cn.animating); // #716
+ $(node.li).removeClass(cn.animating); // #717
+ callback();
+ },
+ });
+ } else {
+ // The UI toggle() effect works with the ext-wide extension,
+ // while jQuery.animate() has problems when the title span
+ // has positon: absolute.
+ // Since jQuery UI 1.12, the blind effect requires the parent
+ // element to have 'position: relative'.
+ // See #716, #717
+ // tree.debug("use specified effect (" + effect.effect + ") with the jqueryui.toggle method");
+
+ // try to stop an animation that might be already in progress
+ $(node.ul).stop(true, true); //< does not work after resetLazy has been called for a node whose animation wasn't complete and effect was "blind"
+
+ // dirty fix to remove a defunct animation (effect: "blind") after resetLazy has been called
+ $(node.ul)
+ .parent()
+ .find(".ui-effects-placeholder")
+ .remove();
+
+ $(node.ul).toggle(
+ effect.effect,
+ effect.options,
+ effect.duration,
+ function () {
+ // node.debug("fancytree-animating end: " + node.li.className);
+ $(this).removeClass(cn.animating); // #716
+ $(node.li).removeClass(cn.animating); // #717
+ callback();
+ }
+ );
+ }
+ return;
+ }
+ }
+ callback();
+ };
+ // ^^^ Code above is executed after loading finshed.
+
+ // Load lazy nodes, if any. Then continue with _afterLoad()
+ if (flag && node.lazy && node.hasChildren() === undefined) {
+ // node.debug("nodeSetExpanded: load start...");
+ node.load()
+ .done(function () {
+ // node.debug("nodeSetExpanded: load done");
+ if (dfd.notifyWith) {
+ // requires jQuery 1.6+
+ dfd.notifyWith(node, ["loaded"]);
+ }
+ _afterLoad(function () {
+ dfd.resolveWith(node);
+ });
+ })
+ .fail(function (errMsg) {
+ _afterLoad(function () {
+ dfd.rejectWith(node, [
+ "load failed (" + errMsg + ")",
+ ]);
+ });
+ });
+ /*
+ var source = tree._triggerNodeEvent("lazyLoad", node, ctx.originalEvent);
+ _assert(typeof source !== "boolean", "lazyLoad event must return source in data.result");
+ node.debug("nodeSetExpanded: load start...");
+ this._callHook("nodeLoadChildren", ctx, source).done(function(){
+ node.debug("nodeSetExpanded: load done");
+ if(dfd.notifyWith){ // requires jQuery 1.6+
+ dfd.notifyWith(node, ["loaded"]);
+ }
+ _afterLoad.call(tree);
+ }).fail(function(errMsg){
+ dfd.rejectWith(node, ["load failed (" + errMsg + ")"]);
+ });
+ */
+ } else {
+ _afterLoad(function () {
+ dfd.resolveWith(node);
+ });
+ }
+ // node.debug("nodeSetExpanded: returns");
+ return dfd.promise();
+ },
+ /** Focus or blur this node.
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ */
+ nodeSetFocus: function (ctx, flag) {
+ // ctx.node.debug("nodeSetFocus(" + flag + ")");
+ var ctx2,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = tree.options,
+ // et = ctx.originalEvent && ctx.originalEvent.type,
+ isInput = ctx.originalEvent
+ ? $(ctx.originalEvent.target).is(":input")
+ : false;
+
+ flag = flag !== false;
+
+ // (node || tree).debug("nodeSetFocus(" + flag + "), event: " + et + ", isInput: "+ isInput);
+ // Blur previous node if any
+ if (tree.focusNode) {
+ if (tree.focusNode === node && flag) {
+ // node.debug("nodeSetFocus(" + flag + "): nothing to do");
+ return;
+ }
+ ctx2 = $.extend({}, ctx, { node: tree.focusNode });
+ tree.focusNode = null;
+ this._triggerNodeEvent("blur", ctx2);
+ this._callHook("nodeRenderStatus", ctx2);
+ }
+ // Set focus to container and node
+ if (flag) {
+ if (!this.hasFocus()) {
+ node.debug("nodeSetFocus: forcing container focus");
+ this._callHook("treeSetFocus", ctx, true, {
+ calledByNode: true,
+ });
+ }
+ node.makeVisible({ scrollIntoView: false });
+ tree.focusNode = node;
+ if (opts.titlesTabbable) {
+ if (!isInput) {
+ // #621
+ $(node.span).find(".fancytree-title").focus();
+ }
+ }
+ if (opts.aria) {
+ // Set active descendant to node's span ID (create one, if needed)
+ $(tree.$container).attr(
+ "aria-activedescendant",
+ $(node.tr || node.li)
+ .uniqueId()
+ .attr("id")
+ );
+ // "ftal_" + opts.idPrefix + node.key);
+ }
+ // $(node.span).find(".fancytree-title").focus();
+ this._triggerNodeEvent("focus", ctx);
+
+ // determine if we have focus on or inside tree container
+ var hasFancytreeFocus =
+ document.activeElement === tree.$container.get(0) ||
+ $(document.activeElement, tree.$container).length >= 1;
+
+ if (!hasFancytreeFocus) {
+ // We cannot set KB focus to a node, so use the tree container
+ // #563, #570: IE scrolls on every call to .focus(), if the container
+ // is partially outside the viewport. So do it only, when absolutely
+ // necessary.
+ $(tree.$container).focus();
+ }
+
+ // if( opts.autoActivate ){
+ // tree.nodeSetActive(ctx, true);
+ // }
+ if (opts.autoScroll) {
+ node.scrollIntoView();
+ }
+ this._callHook("nodeRenderStatus", ctx);
+ }
+ },
+ /** (De)Select node, return new status (sync).
+ *
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ * @param {object} [opts] additional options. Defaults to {noEvents: false,
+ * propagateDown: null, propagateUp: null,
+ * callback: null,
+ * }
+ * @returns {boolean} previous status
+ */
+ nodeSetSelected: function (ctx, flag, callOpts) {
+ callOpts = callOpts || {};
+ var node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ noEvents = callOpts.noEvents === true,
+ parent = node.parent;
+
+ // flag defaults to true
+ flag = flag !== false;
+
+ // node.debug("nodeSetSelected(" + flag + ")", ctx);
+
+ // Cannot (de)select unselectable nodes directly (only by propagation or
+ // by setting the `.selected` property)
+ if (FT.evalOption("unselectable", node, node, opts, false)) {
+ return;
+ }
+
+ // Remember the user's intent, in case down -> up propagation prevents
+ // applying it to node.selected
+ node._lastSelectIntent = flag; // Confusing use of '!'
+
+ // Nothing to do?
+ if (!!node.selected === flag) {
+ if (opts.selectMode === 3 && node.partsel && !flag) {
+ // If propagation prevented selecting this node last time, we still
+ // want to allow to apply setSelected(false) now
+ } else {
+ return flag;
+ }
+ }
+
+ if (
+ !noEvents &&
+ this._triggerNodeEvent(
+ "beforeSelect",
+ node,
+ ctx.originalEvent
+ ) === false
+ ) {
+ return !!node.selected;
+ }
+ if (flag && opts.selectMode === 1) {
+ // single selection mode (we don't uncheck all tree nodes, for performance reasons)
+ if (tree.lastSelectedNode) {
+ tree.lastSelectedNode.setSelected(false);
+ }
+ node.selected = flag;
+ } else if (
+ opts.selectMode === 3 &&
+ parent &&
+ !parent.radiogroup &&
+ !node.radiogroup
+ ) {
+ // multi-hierarchical selection mode
+ node.selected = flag;
+ node.fixSelection3AfterClick(callOpts);
+ } else if (parent && parent.radiogroup) {
+ node.visitSiblings(function (n) {
+ n._changeSelectStatusAttrs(flag && n === node);
+ }, true);
+ } else {
+ // default: selectMode: 2, multi selection mode
+ node.selected = flag;
+ }
+ this.nodeRenderStatus(ctx);
+ tree.lastSelectedNode = flag ? node : null;
+ if (!noEvents) {
+ tree._triggerNodeEvent("select", ctx);
+ }
+ },
+ /** Show node status (ok, loading, error, nodata) using styles and a dummy child node.
+ *
+ * @param {EventData} ctx
+ * @param status
+ * @param message
+ * @param details
+ * @since 2.3
+ */
+ nodeSetStatus: function (ctx, status, message, details) {
+ var node = ctx.node,
+ tree = ctx.tree;
+
+ function _clearStatusNode() {
+ // Remove dedicated dummy node, if any
+ var firstChild = node.children ? node.children[0] : null;
+ if (firstChild && firstChild.isStatusNode()) {
+ try {
+ // I've seen exceptions here with loadKeyPath...
+ if (node.ul) {
+ node.ul.removeChild(firstChild.li);
+ firstChild.li = null; // avoid leaks (DT issue 215)
+ }
+ } catch (e) {}
+ if (node.children.length === 1) {
+ node.children = [];
+ } else {
+ node.children.shift();
+ }
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ "clearStatusNode"
+ );
+ }
+ }
+ function _setStatusNode(data, type) {
+ // Create/modify the dedicated dummy node for 'loading...' or
+ // 'error!' status. (only called for direct child of the invisible
+ // system root)
+ var firstChild = node.children ? node.children[0] : null;
+ if (firstChild && firstChild.isStatusNode()) {
+ $.extend(firstChild, data);
+ firstChild.statusNodeType = type;
+ tree._callHook("nodeRenderTitle", firstChild);
+ } else {
+ node._setChildren([data]);
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ "setStatusNode"
+ );
+ node.children[0].statusNodeType = type;
+ tree.render();
+ }
+ return node.children[0];
+ }
+
+ switch (status) {
+ case "ok":
+ _clearStatusNode();
+ node._isLoading = false;
+ node._error = null;
+ node.renderStatus();
+ break;
+ case "loading":
+ if (!node.parent) {
+ _setStatusNode(
+ {
+ title:
+ tree.options.strings.loading +
+ (message ? " (" + message + ")" : ""),
+ // icon: true, // needed for 'loding' icon
+ checkbox: false,
+ tooltip: details,
+ },
+ status
+ );
+ }
+ node._isLoading = true;
+ node._error = null;
+ node.renderStatus();
+ break;
+ case "error":
+ _setStatusNode(
+ {
+ title:
+ tree.options.strings.loadError +
+ (message ? " (" + message + ")" : ""),
+ // icon: false,
+ checkbox: false,
+ tooltip: details,
+ },
+ status
+ );
+ node._isLoading = false;
+ node._error = { message: message, details: details };
+ node.renderStatus();
+ break;
+ case "nodata":
+ _setStatusNode(
+ {
+ title: message || tree.options.strings.noData,
+ // icon: false,
+ checkbox: false,
+ tooltip: details,
+ },
+ status
+ );
+ node._isLoading = false;
+ node._error = null;
+ node.renderStatus();
+ break;
+ default:
+ $.error("invalid node status " + status);
+ }
+ },
+ /**
+ *
+ * @param {EventData} ctx
+ */
+ nodeToggleExpanded: function (ctx) {
+ return this.nodeSetExpanded(ctx, !ctx.node.expanded);
+ },
+ /**
+ * @param {EventData} ctx
+ */
+ nodeToggleSelected: function (ctx) {
+ var node = ctx.node,
+ flag = !node.selected;
+
+ // In selectMode: 3 this node may be unselected+partsel, even if
+ // setSelected(true) was called before, due to `unselectable` children.
+ // In this case, we now toggle as `setSelected(false)`
+ if (
+ node.partsel &&
+ !node.selected &&
+ node._lastSelectIntent === true
+ ) {
+ flag = false;
+ node.selected = true; // so it is not considered 'nothing to do'
+ }
+ node._lastSelectIntent = flag;
+ return this.nodeSetSelected(ctx, flag);
+ },
+ /** Remove all nodes.
+ * @param {EventData} ctx
+ */
+ treeClear: function (ctx) {
+ var tree = ctx.tree;
+ tree.activeNode = null;
+ tree.focusNode = null;
+ tree.$div.find(">ul.fancytree-container").empty();
+ // TODO: call destructors and remove reference loops
+ tree.rootNode.children = null;
+ tree._callHook("treeStructureChanged", ctx, "clear");
+ },
+ /** Widget was created (called only once, even it re-initialized).
+ * @param {EventData} ctx
+ */
+ treeCreate: function (ctx) {},
+ /** Widget was destroyed.
+ * @param {EventData} ctx
+ */
+ treeDestroy: function (ctx) {
+ this.$div.find(">ul.fancytree-container").remove();
+ if (this.$source) {
+ this.$source.removeClass("fancytree-helper-hidden");
+ }
+ },
+ /** Widget was (re-)initialized.
+ * @param {EventData} ctx
+ */
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ opts = tree.options;
+
+ //this.debug("Fancytree.treeInit()");
+ // Add container to the TAB chain
+ // See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant
+ // #577: Allow to set tabindex to "0", "-1" and ""
+ tree.$container.attr("tabindex", opts.tabindex);
+
+ // Copy some attributes to tree.data
+ $.each(TREE_ATTRS, function (i, attr) {
+ if (opts[attr] !== undefined) {
+ tree.info("Move option " + attr + " to tree");
+ tree[attr] = opts[attr];
+ delete opts[attr];
+ }
+ });
+
+ if (opts.checkboxAutoHide) {
+ tree.$container.addClass("fancytree-checkbox-auto-hide");
+ }
+ if (opts.rtl) {
+ tree.$container
+ .attr("DIR", "RTL")
+ .addClass("fancytree-rtl");
+ } else {
+ tree.$container
+ .removeAttr("DIR")
+ .removeClass("fancytree-rtl");
+ }
+ if (opts.aria) {
+ tree.$container.attr("role", "tree");
+ if (opts.selectMode !== 1) {
+ tree.$container.attr("aria-multiselectable", true);
+ }
+ }
+ this.treeLoad(ctx);
+ },
+ /** Parse Fancytree from source, as configured in the options.
+ * @param {EventData} ctx
+ * @param {object} [source] optional new source (use last data otherwise)
+ */
+ treeLoad: function (ctx, source) {
+ var metaData,
+ type,
+ $ul,
+ tree = ctx.tree,
+ $container = ctx.widget.element,
+ dfd,
+ // calling context for root node
+ rootCtx = $.extend({}, ctx, { node: this.rootNode });
+
+ if (tree.rootNode.children) {
+ this.treeClear(ctx);
+ }
+ source = source || this.options.source;
+
+ if (!source) {
+ type = $container.data("type") || "html";
+ switch (type) {
+ case "html":
+ // There should be an embedded `<ul>` with initial nodes,
+ // but another `<ul class='fancytree-container'>` is appended
+ // to the tree's <div> on startup anyway.
+ $ul = $container
+ .find(">ul")
+ .not(".fancytree-container")
+ .first();
+
+ if ($ul.length) {
+ $ul.addClass(
+ "ui-fancytree-source fancytree-helper-hidden"
+ );
+ source = $.ui.fancytree.parseHtml($ul);
+ // allow to init tree.data.foo from <ul data-foo=''>
+ this.data = $.extend(
+ this.data,
+ _getElementDataAsDict($ul)
+ );
+ } else {
+ FT.warn(
+ "No `source` option was passed and container does not contain `<ul>`: assuming `source: []`."
+ );
+ source = [];
+ }
+ break;
+ case "json":
+ source = $.parseJSON($container.text());
+ // $container already contains the <ul>, but we remove the plain (json) text
+ // $container.empty();
+ $container
+ .contents()
+ .filter(function () {
+ return this.nodeType === 3;
+ })
+ .remove();
+ if ($.isPlainObject(source)) {
+ // We got {foo: 'abc', children: [...]}
+ _assert(
+ _isArray(source.children),
+ "if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"
+ );
+ metaData = source;
+ source = source.children;
+ delete metaData.children;
+ // Copy some attributes to tree.data
+ $.each(TREE_ATTRS, function (i, attr) {
+ if (metaData[attr] !== undefined) {
+ tree[attr] = metaData[attr];
+ delete metaData[attr];
+ }
+ });
+ // Copy extra properties to tree.data.foo
+ $.extend(tree.data, metaData);
+ }
+ break;
+ default:
+ $.error("Invalid data-type: " + type);
+ }
+ } else if (typeof source === "string") {
+ // TODO: source is an element ID
+ $.error("Not implemented");
+ }
+
+ // preInit is fired when the widget markup is created, but nodes
+ // not yet loaded
+ tree._triggerTreeEvent("preInit", null);
+
+ // Trigger fancytreeinit after nodes have been loaded
+ dfd = this.nodeLoadChildren(rootCtx, source)
+ .done(function () {
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ "loadChildren"
+ );
+ tree.render();
+ if (ctx.options.selectMode === 3) {
+ tree.rootNode.fixSelection3FromEndNodes();
+ }
+ if (tree.activeNode && tree.options.activeVisible) {
+ tree.activeNode.makeVisible();
+ }
+ tree._triggerTreeEvent("init", null, { status: true });
+ })
+ .fail(function () {
+ tree.render();
+ tree._triggerTreeEvent("init", null, { status: false });
+ });
+ return dfd;
+ },
+ /** Node was inserted into or removed from the tree.
+ * @param {EventData} ctx
+ * @param {boolean} add
+ * @param {FancytreeNode} node
+ */
+ treeRegisterNode: function (ctx, add, node) {
+ ctx.tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ add ? "addNode" : "removeNode"
+ );
+ },
+ /** Widget got focus.
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ */
+ treeSetFocus: function (ctx, flag, callOpts) {
+ var targetNode;
+
+ flag = flag !== false;
+
+ // this.debug("treeSetFocus(" + flag + "), callOpts: ", callOpts, this.hasFocus());
+ // this.debug(" focusNode: " + this.focusNode);
+ // this.debug(" activeNode: " + this.activeNode);
+ if (flag !== this.hasFocus()) {
+ this._hasFocus = flag;
+ if (!flag && this.focusNode) {
+ // Node also looses focus if widget blurs
+ this.focusNode.setFocus(false);
+ } else if (flag && (!callOpts || !callOpts.calledByNode)) {
+ $(this.$container).focus();
+ }
+ this.$container.toggleClass("fancytree-treefocus", flag);
+ this._triggerTreeEvent(flag ? "focusTree" : "blurTree");
+ if (flag && !this.activeNode) {
+ // #712: Use last mousedowned node ('click' event fires after focusin)
+ targetNode =
+ this._lastMousedownNode || this.getFirstChild();
+ if (targetNode) {
+ targetNode.setFocus();
+ }
+ }
+ }
+ },
+ /** Widget option was set using `$().fancytree("option", "KEY", VALUE)`.
+ *
+ * Note: `key` may reference a nested option, e.g. 'dnd5.scroll'.
+ * In this case `value`contains the complete, modified `dnd5` option hash.
+ * We can check for changed values like
+ * if( value.scroll !== tree.options.dnd5.scroll ) {...}
+ *
+ * @param {EventData} ctx
+ * @param {string} key option name
+ * @param {any} value option value
+ */
+ treeSetOption: function (ctx, key, value) {
+ var tree = ctx.tree,
+ callDefault = true,
+ callCreate = false,
+ callRender = false;
+
+ switch (key) {
+ case "aria":
+ case "checkbox":
+ case "icon":
+ case "minExpandLevel":
+ case "tabindex":
+ // tree._callHook("treeCreate", tree);
+ callCreate = true;
+ callRender = true;
+ break;
+ case "checkboxAutoHide":
+ tree.$container.toggleClass(
+ "fancytree-checkbox-auto-hide",
+ !!value
+ );
+ break;
+ case "escapeTitles":
+ case "tooltip":
+ callRender = true;
+ break;
+ case "rtl":
+ if (value === false) {
+ tree.$container
+ .removeAttr("DIR")
+ .removeClass("fancytree-rtl");
+ } else {
+ tree.$container
+ .attr("DIR", "RTL")
+ .addClass("fancytree-rtl");
+ }
+ callRender = true;
+ break;
+ case "source":
+ callDefault = false;
+ tree._callHook("treeLoad", tree, value);
+ callRender = true;
+ break;
+ }
+ tree.debug(
+ "set option " +
+ key +
+ "=" +
+ value +
+ " <" +
+ typeof value +
+ ">"
+ );
+ if (callDefault) {
+ if (this.widget._super) {
+ // jQuery UI 1.9+
+ this.widget._super.call(this.widget, key, value);
+ } else {
+ // jQuery UI <= 1.8, we have to manually invoke the _setOption method from the base widget
+ $.Widget.prototype._setOption.call(
+ this.widget,
+ key,
+ value
+ );
+ }
+ }
+ if (callCreate) {
+ tree._callHook("treeCreate", tree);
+ }
+ if (callRender) {
+ tree.render(true, false); // force, not-deep
+ }
+ },
+ /** A Node was added, removed, moved, or it's visibility changed.
+ * @param {EventData} ctx
+ */
+ treeStructureChanged: function (ctx, type) {},
+ }
+ );
+
+ /*******************************************************************************
+ * jQuery UI widget boilerplate
+ */
+
+ /**
+ * The plugin (derrived from [jQuery.Widget](http://api.jqueryui.com/jQuery.widget/)).
+ *
+ * **Note:**
+ * These methods implement the standard jQuery UI widget API.
+ * It is recommended to use methods of the {Fancytree} instance instead
+ *
+ * @example
+ * // DEPRECATED: Access jQuery UI widget methods and members:
+ * var tree = $("#tree").fancytree("getTree");
+ * var node = $("#tree").fancytree("getActiveNode");
+ *
+ * // RECOMMENDED: Use the Fancytree object API
+ * var tree = $.ui.fancytree.getTree("#tree");
+ * var node = tree.getActiveNode();
+ *
+ * // or you may already have stored the tree instance upon creation:
+ * import {createTree, version} from 'jquery.fancytree'
+ * const tree = createTree('#tree', { ... });
+ * var node = tree.getActiveNode();
+ *
+ * @see {Fancytree_Static#getTree}
+ * @deprecated Use methods of the {Fancytree} instance instead
+ * @mixin Fancytree_Widget
+ */
+
+ $.widget(
+ "ui.fancytree",
+ /** @lends Fancytree_Widget# */
+ {
+ /**These options will be used as defaults
+ * @type {FancytreeOptions}
+ */
+ options: {
+ activeVisible: true,
+ ajax: {
+ type: "GET",
+ cache: false, // false: Append random '_' argument to the request url to prevent caching.
+ // timeout: 0, // >0: Make sure we get an ajax error if server is unreachable
+ dataType: "json", // Expect json format and pass json object to callbacks.
+ },
+ aria: true,
+ autoActivate: true,
+ autoCollapse: false,
+ autoScroll: false,
+ checkbox: false,
+ clickFolderMode: 4,
+ copyFunctionsToData: false,
+ debugLevel: null, // 0..4 (null: use global setting $.ui.fancytree.debugLevel)
+ disabled: false, // TODO: required anymore?
+ enableAspx: 42, // TODO: this is truethy, but distinguishable from true: default will change to false in the future
+ escapeTitles: false,
+ extensions: [],
+ focusOnSelect: false,
+ generateIds: false,
+ icon: true,
+ idPrefix: "ft_",
+ keyboard: true,
+ keyPathSeparator: "/",
+ minExpandLevel: 1,
+ nodata: true, // (bool, string, or callback) display message, when no data available
+ quicksearch: false,
+ rtl: false,
+ scrollOfs: { top: 0, bottom: 0 },
+ scrollParent: null,
+ selectMode: 2,
+ strings: {
+ loading: "Loading...", // &#8230; would be escaped when escapeTitles is true
+ loadError: "Load error!",
+ moreData: "More...",
+ noData: "No data.",
+ },
+ tabindex: "0",
+ titlesTabbable: false,
+ toggleEffect: { effect: "slideToggle", duration: 200 }, //< "toggle" or "slideToggle" to use jQuery instead of jQueryUI for toggleEffect animation
+ tooltip: false,
+ treeId: null,
+ _classNames: {
+ active: "fancytree-active",
+ animating: "fancytree-animating",
+ combinedExpanderPrefix: "fancytree-exp-",
+ combinedIconPrefix: "fancytree-ico-",
+ error: "fancytree-error",
+ expanded: "fancytree-expanded",
+ focused: "fancytree-focused",
+ folder: "fancytree-folder",
+ hasChildren: "fancytree-has-children",
+ lastsib: "fancytree-lastsib",
+ lazy: "fancytree-lazy",
+ loading: "fancytree-loading",
+ node: "fancytree-node",
+ partload: "fancytree-partload",
+ partsel: "fancytree-partsel",
+ radio: "fancytree-radio",
+ selected: "fancytree-selected",
+ statusNodePrefix: "fancytree-statusnode-",
+ unselectable: "fancytree-unselectable",
+ },
+ // events
+ lazyLoad: null,
+ postProcess: null,
+ },
+ _deprecationWarning: function (name) {
+ var tree = this.tree;
+
+ if (tree && tree.options.debugLevel >= 3) {
+ tree.warn(
+ "$().fancytree('" +
+ name +
+ "') is deprecated (see https://wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Widget.html"
+ );
+ }
+ },
+ /* Set up the widget, Called on first $().fancytree() */
+ _create: function () {
+ this.tree = new Fancytree(this);
+
+ this.$source =
+ this.source || this.element.data("type") === "json"
+ ? this.element
+ : this.element.find(">ul").first();
+ // Subclass Fancytree instance with all enabled extensions
+ var extension,
+ extName,
+ i,
+ opts = this.options,
+ extensions = opts.extensions,
+ base = this.tree;
+
+ for (i = 0; i < extensions.length; i++) {
+ extName = extensions[i];
+ extension = $.ui.fancytree._extensions[extName];
+ if (!extension) {
+ $.error(
+ "Could not apply extension '" +
+ extName +
+ "' (it is not registered, did you forget to include it?)"
+ );
+ }
+ // Add extension options as tree.options.EXTENSION
+ // _assert(!this.tree.options[extName], "Extension name must not exist as option name: " + extName);
+
+ // console.info("extend " + extName, extension.options, this.tree.options[extName])
+ // issue #876: we want to replace custom array-options, not merge them
+ this.tree.options[extName] = _simpleDeepMerge(
+ {},
+ extension.options,
+ this.tree.options[extName]
+ );
+ // this.tree.options[extName] = $.extend(true, {}, extension.options, this.tree.options[extName]);
+
+ // console.info("extend " + extName + " =>", this.tree.options[extName])
+ // console.info("extend " + extName + " org default =>", extension.options)
+
+ // Add a namespace tree.ext.EXTENSION, to hold instance data
+ _assert(
+ this.tree.ext[extName] === undefined,
+ "Extension name must not exist as Fancytree.ext attribute: '" +
+ extName +
+ "'"
+ );
+ // this.tree[extName] = extension;
+ this.tree.ext[extName] = {};
+ // Subclass Fancytree methods using proxies.
+ _subclassObject(this.tree, base, extension, extName);
+ // current extension becomes base for the next extension
+ base = extension;
+ }
+ //
+ if (opts.icons !== undefined) {
+ // 2015-11-16
+ if (opts.icon === true) {
+ this.tree.warn(
+ "'icons' tree option is deprecated since v2.14.0: use 'icon' instead"
+ );
+ opts.icon = opts.icons;
+ } else {
+ $.error(
+ "'icons' tree option is deprecated since v2.14.0: use 'icon' only instead"
+ );
+ }
+ }
+ if (opts.iconClass !== undefined) {
+ // 2015-11-16
+ if (opts.icon) {
+ $.error(
+ "'iconClass' tree option is deprecated since v2.14.0: use 'icon' only instead"
+ );
+ } else {
+ this.tree.warn(
+ "'iconClass' tree option is deprecated since v2.14.0: use 'icon' instead"
+ );
+ opts.icon = opts.iconClass;
+ }
+ }
+ if (opts.tabbable !== undefined) {
+ // 2016-04-04
+ opts.tabindex = opts.tabbable ? "0" : "-1";
+ this.tree.warn(
+ "'tabbable' tree option is deprecated since v2.17.0: use 'tabindex='" +
+ opts.tabindex +
+ "' instead"
+ );
+ }
+ //
+ this.tree._callHook("treeCreate", this.tree);
+ // Note: 'fancytreecreate' event is fired by widget base class
+ // this.tree._triggerTreeEvent("create");
+ },
+
+ /* Called on every $().fancytree() */
+ _init: function () {
+ this.tree._callHook("treeInit", this.tree);
+ // TODO: currently we call bind after treeInit, because treeInit
+ // might change tree.$container.
+ // It would be better, to move event binding into hooks altogether
+ this._bind();
+ },
+
+ /* Use the _setOption method to respond to changes to options. */
+ _setOption: function (key, value) {
+ return this.tree._callHook(
+ "treeSetOption",
+ this.tree,
+ key,
+ value
+ );
+ },
+
+ /** Use the destroy method to clean up any modifications your widget has made to the DOM */
+ _destroy: function () {
+ this._unbind();
+ this.tree._callHook("treeDestroy", this.tree);
+ // In jQuery UI 1.8, you must invoke the destroy method from the base widget
+ // $.Widget.prototype.destroy.call(this);
+ // TODO: delete tree and nodes to make garbage collect easier?
+ // TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method
+ },
+
+ // -------------------------------------------------------------------------
+
+ /* Remove all event handlers for our namespace */
+ _unbind: function () {
+ var ns = this.tree._ns;
+ this.element.off(ns);
+ this.tree.$container.off(ns);
+ $(document).off(ns);
+ },
+ /* Add mouse and kyboard handlers to the container */
+ _bind: function () {
+ var self = this,
+ opts = this.options,
+ tree = this.tree,
+ ns = tree._ns;
+ // selstartEvent = ( $.support.selectstart ? "selectstart" : "mousedown" )
+
+ // Remove all previuous handlers for this tree
+ this._unbind();
+
+ //alert("keydown" + ns + "foc=" + tree.hasFocus() + tree.$container);
+ // tree.debug("bind events; container: ", tree.$container);
+ tree.$container
+ .on("focusin" + ns + " focusout" + ns, function (event) {
+ var node = FT.getNode(event),
+ flag = event.type === "focusin";
+
+ if (!flag && node && $(event.target).is("a")) {
+ // #764
+ node.debug(
+ "Ignored focusout on embedded <a> element."
+ );
+ return;
+ }
+ // tree.treeOnFocusInOut.call(tree, event);
+ // tree.debug("Tree container got event " + event.type, node, event, FT.getEventTarget(event));
+ if (flag) {
+ if (tree._getExpiringValue("focusin")) {
+ // #789: IE 11 may send duplicate focusin events
+ tree.debug("Ignored double focusin.");
+ return;
+ }
+ tree._setExpiringValue("focusin", true, 50);
+
+ if (!node) {
+ // #789: IE 11 may send focusin before mousdown(?)
+ node = tree._getExpiringValue("mouseDownNode");
+ if (node) {
+ tree.debug(
+ "Reconstruct mouse target for focusin from recent event."
+ );
+ }
+ }
+ }
+ if (node) {
+ // For example clicking into an <input> that is part of a node
+ tree._callHook(
+ "nodeSetFocus",
+ tree._makeHookContext(node, event),
+ flag
+ );
+ } else {
+ if (
+ tree.tbody &&
+ $(event.target).parents(
+ "table.fancytree-container > thead"
+ ).length
+ ) {
+ // #767: ignore events in the table's header
+ tree.debug(
+ "Ignore focus event outside table body.",
+ event
+ );
+ } else {
+ tree._callHook("treeSetFocus", tree, flag);
+ }
+ }
+ })
+ .on(
+ "selectstart" + ns,
+ "span.fancytree-title",
+ function (event) {
+ // prevent mouse-drags to select text ranges
+ // tree.debug("<span title> got event " + event.type);
+ event.preventDefault();
+ }
+ )
+ .on("keydown" + ns, function (event) {
+ // TODO: also bind keyup and keypress
+ // tree.debug("got event " + event.type + ", hasFocus:" + tree.hasFocus());
+ // if(opts.disabled || opts.keyboard === false || !tree.hasFocus() ){
+ if (opts.disabled || opts.keyboard === false) {
+ return true;
+ }
+ var res,
+ node = tree.focusNode, // node may be null
+ ctx = tree._makeHookContext(node || tree, event),
+ prevPhase = tree.phase;
+
+ try {
+ tree.phase = "userEvent";
+ // If a 'fancytreekeydown' handler returns false, skip the default
+ // handling (implemented by tree.nodeKeydown()).
+ if (node) {
+ res = tree._triggerNodeEvent(
+ "keydown",
+ node,
+ event
+ );
+ } else {
+ res = tree._triggerTreeEvent("keydown", event);
+ }
+ if (res === "preventNav") {
+ res = true; // prevent keyboard navigation, but don't prevent default handling of embedded input controls
+ } else if (res !== false) {
+ res = tree._callHook("nodeKeydown", ctx);
+ }
+ return res;
+ } finally {
+ tree.phase = prevPhase;
+ }
+ })
+ .on("mousedown" + ns, function (event) {
+ var et = FT.getEventTarget(event);
+ // self.tree.debug("event(" + event.type + "): node: ", et.node);
+ // #712: Store the clicked node, so we can use it when we get a focusin event
+ // ('click' event fires after focusin)
+ // tree.debug("event(" + event.type + "): node: ", et.node);
+ tree._lastMousedownNode = et ? et.node : null;
+ // #789: Store the node also for a short period, so we can use it
+ // in a *resulting* focusin event
+ tree._setExpiringValue(
+ "mouseDownNode",
+ tree._lastMousedownNode
+ );
+ })
+ .on("click" + ns + " dblclick" + ns, function (event) {
+ if (opts.disabled) {
+ return true;
+ }
+ var ctx,
+ et = FT.getEventTarget(event),
+ node = et.node,
+ tree = self.tree,
+ prevPhase = tree.phase;
+
+ // self.tree.debug("event(" + event.type + "): node: ", node);
+ if (!node) {
+ return true; // Allow bubbling of other events
+ }
+ ctx = tree._makeHookContext(node, event);
+ // self.tree.debug("event(" + event.type + "): node: ", node);
+ try {
+ tree.phase = "userEvent";
+ switch (event.type) {
+ case "click":
+ ctx.targetType = et.type;
+ if (node.isPagingNode()) {
+ return (
+ tree._triggerNodeEvent(
+ "clickPaging",
+ ctx,
+ event
+ ) === true
+ );
+ }
+ return tree._triggerNodeEvent(
+ "click",
+ ctx,
+ event
+ ) === false
+ ? false
+ : tree._callHook("nodeClick", ctx);
+ case "dblclick":
+ ctx.targetType = et.type;
+ return tree._triggerNodeEvent(
+ "dblclick",
+ ctx,
+ event
+ ) === false
+ ? false
+ : tree._callHook("nodeDblclick", ctx);
+ }
+ } finally {
+ tree.phase = prevPhase;
+ }
+ });
+ },
+ /** Return the active node or null.
+ * @returns {FancytreeNode}
+ * @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getActiveNode: function () {
+ this._deprecationWarning("getActiveNode");
+ return this.tree.activeNode;
+ },
+ /** Return the matching node or null.
+ * @param {string} key
+ * @returns {FancytreeNode}
+ * @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getNodeByKey: function (key) {
+ this._deprecationWarning("getNodeByKey");
+ return this.tree.getNodeByKey(key);
+ },
+ /** Return the invisible system root node.
+ * @returns {FancytreeNode}
+ * @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getRootNode: function () {
+ this._deprecationWarning("getRootNode");
+ return this.tree.rootNode;
+ },
+ /** Return the current tree instance.
+ * @returns {Fancytree}
+ * @deprecated Use `$.ui.fancytree.getTree()` instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getTree: function () {
+ this._deprecationWarning("getTree");
+ return this.tree;
+ },
+ }
+ );
+
+ // $.ui.fancytree was created by the widget factory. Create a local shortcut:
+ FT = $.ui.fancytree;
+
+ /**
+ * Static members in the `$.ui.fancytree` namespace.
+ * This properties and methods can be accessed without instantiating a concrete
+ * Fancytree instance.
+ *
+ * @example
+ * // Access static members:
+ * var node = $.ui.fancytree.getNode(element);
+ * alert($.ui.fancytree.version);
+ *
+ * @mixin Fancytree_Static
+ */
+ $.extend(
+ $.ui.fancytree,
+ /** @lends Fancytree_Static# */
+ {
+ /** Version number `"MAJOR.MINOR.PATCH"`
+ * @type {string} */
+ version: "2.38.3", // Set to semver by 'grunt release'
+ /** @type {string}
+ * @description `"production" for release builds` */
+ buildType: "production", // Set to 'production' by 'grunt build'
+ /** @type {int}
+ * @description 0: silent .. 5: verbose (default: 3 for release builds). */
+ debugLevel: 3, // Set to 3 by 'grunt build'
+ // Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel
+
+ _nextId: 1,
+ _nextNodeKey: 1,
+ _extensions: {},
+ // focusTree: null,
+
+ /** Expose class object as `$.ui.fancytree._FancytreeClass`.
+ * Useful to extend `$.ui.fancytree._FancytreeClass.prototype`.
+ * @type {Fancytree}
+ */
+ _FancytreeClass: Fancytree,
+ /** Expose class object as $.ui.fancytree._FancytreeNodeClass
+ * Useful to extend `$.ui.fancytree._FancytreeNodeClass.prototype`.
+ * @type {FancytreeNode}
+ */
+ _FancytreeNodeClass: FancytreeNode,
+ /* Feature checks to provide backwards compatibility */
+ jquerySupports: {
+ // http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+ positionMyOfs: isVersionAtLeast($.ui.version, 1, 9),
+ },
+ /** Throw an error if condition fails (debug method).
+ * @param {boolean} cond
+ * @param {string} msg
+ */
+ assert: function (cond, msg) {
+ return _assert(cond, msg);
+ },
+ /** Create a new Fancytree instance on a target element.
+ *
+ * @param {Element | jQueryObject | string} el Target DOM element or selector
+ * @param {FancytreeOptions} [opts] Fancytree options
+ * @returns {Fancytree} new tree instance
+ * @example
+ * var tree = $.ui.fancytree.createTree("#tree", {
+ * source: {url: "my/webservice"}
+ * }); // Create tree for this matching element
+ *
+ * @since 2.25
+ */
+ createTree: function (el, opts) {
+ var $tree = $(el).fancytree(opts);
+ return FT.getTree($tree);
+ },
+ /** Return a function that executes *fn* at most every *timeout* ms.
+ * @param {integer} timeout
+ * @param {function} fn
+ * @param {boolean} [invokeAsap=false]
+ * @param {any} [ctx]
+ */
+ debounce: function (timeout, fn, invokeAsap, ctx) {
+ var timer;
+ if (arguments.length === 3 && typeof invokeAsap !== "boolean") {
+ ctx = invokeAsap;
+ invokeAsap = false;
+ }
+ return function () {
+ var args = arguments;
+ ctx = ctx || this;
+ // eslint-disable-next-line no-unused-expressions
+ invokeAsap && !timer && fn.apply(ctx, args);
+ clearTimeout(timer);
+ timer = setTimeout(function () {
+ // eslint-disable-next-line no-unused-expressions
+ invokeAsap || fn.apply(ctx, args);
+ timer = null;
+ }, timeout);
+ };
+ },
+ /** Write message to console if debugLevel >= 4
+ * @param {string} msg
+ */
+ debug: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 4) {
+ consoleApply("log", arguments);
+ }
+ },
+ /** Write error message to console if debugLevel >= 1.
+ * @param {string} msg
+ */
+ error: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 1) {
+ consoleApply("error", arguments);
+ }
+ },
+ /** Convert `<`, `>`, `&`, `"`, `'`, and `/` to the equivalent entities.
+ *
+ * @param {string} s
+ * @returns {string}
+ */
+ escapeHtml: function (s) {
+ return ("" + s).replace(REX_HTML, function (s) {
+ return ENTITY_MAP[s];
+ });
+ },
+ /** Make jQuery.position() arguments backwards compatible, i.e. if
+ * jQuery UI version <= 1.8, convert
+ * { my: "left+3 center", at: "left bottom", of: $target }
+ * to
+ * { my: "left center", at: "left bottom", of: $target, offset: "3 0" }
+ *
+ * See http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+ * and http://jsfiddle.net/mar10/6xtu9a4e/
+ *
+ * @param {object} opts
+ * @returns {object} the (potentially modified) original opts hash object
+ */
+ fixPositionOptions: function (opts) {
+ if (opts.offset || ("" + opts.my + opts.at).indexOf("%") >= 0) {
+ $.error(
+ "expected new position syntax (but '%' is not supported)"
+ );
+ }
+ if (!$.ui.fancytree.jquerySupports.positionMyOfs) {
+ var // parse 'left+3 center' into ['left+3 center', 'left', '+3', 'center', undefined]
+ myParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(
+ opts.my
+ ),
+ atParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(
+ opts.at
+ ),
+ // convert to numbers
+ dx =
+ (myParts[2] ? +myParts[2] : 0) +
+ (atParts[2] ? +atParts[2] : 0),
+ dy =
+ (myParts[4] ? +myParts[4] : 0) +
+ (atParts[4] ? +atParts[4] : 0);
+
+ opts = $.extend({}, opts, {
+ // make a copy and overwrite
+ my: myParts[1] + " " + myParts[3],
+ at: atParts[1] + " " + atParts[3],
+ });
+ if (dx || dy) {
+ opts.offset = "" + dx + " " + dy;
+ }
+ }
+ return opts;
+ },
+ /** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.
+ *
+ * @param {Event} event Mouse event, e.g. click, ...
+ * @returns {object} Return a {node: FancytreeNode, type: TYPE} object
+ * TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+ */
+ getEventTarget: function (event) {
+ var $target,
+ tree,
+ tcn = event && event.target ? event.target.className : "",
+ res = { node: this.getNode(event.target), type: undefined };
+ // We use a fast version of $(res.node).hasClass()
+ // See http://jsperf.com/test-for-classname/2
+ if (/\bfancytree-title\b/.test(tcn)) {
+ res.type = "title";
+ } else if (/\bfancytree-expander\b/.test(tcn)) {
+ res.type =
+ res.node.hasChildren() === false
+ ? "prefix"
+ : "expander";
+ // }else if( /\bfancytree-checkbox\b/.test(tcn) || /\bfancytree-radio\b/.test(tcn) ){
+ } else if (/\bfancytree-checkbox\b/.test(tcn)) {
+ res.type = "checkbox";
+ } else if (/\bfancytree(-custom)?-icon\b/.test(tcn)) {
+ res.type = "icon";
+ } else if (/\bfancytree-node\b/.test(tcn)) {
+ // Somewhere near the title
+ res.type = "title";
+ } else if (event && event.target) {
+ $target = $(event.target);
+ if ($target.is("ul[role=group]")) {
+ // #nnn: Clicking right to a node may hit the surrounding UL
+ tree = res.node && res.node.tree;
+ (tree || FT).debug("Ignoring click on outer UL.");
+ res.node = null;
+ } else if ($target.closest(".fancytree-title").length) {
+ // #228: clicking an embedded element inside a title
+ res.type = "title";
+ } else if ($target.closest(".fancytree-checkbox").length) {
+ // E.g. <svg> inside checkbox span
+ res.type = "checkbox";
+ } else if ($target.closest(".fancytree-expander").length) {
+ res.type = "expander";
+ }
+ }
+ return res;
+ },
+ /** Return a string describing the affected node region for a mouse event.
+ *
+ * @param {Event} event Mouse event, e.g. click, mousemove, ...
+ * @returns {string} 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+ */
+ getEventTargetType: function (event) {
+ return this.getEventTarget(event).type;
+ },
+ /** Return a FancytreeNode instance from element, event, or jQuery object.
+ *
+ * @param {Element | jQueryObject | Event} el
+ * @returns {FancytreeNode} matching node or null
+ */
+ getNode: function (el) {
+ if (el instanceof FancytreeNode) {
+ return el; // el already was a FancytreeNode
+ } else if (el instanceof $) {
+ el = el[0]; // el was a jQuery object: use the DOM element
+ } else if (el.originalEvent !== undefined) {
+ el = el.target; // el was an Event
+ }
+ while (el) {
+ if (el.ftnode) {
+ return el.ftnode;
+ }
+ el = el.parentNode;
+ }
+ return null;
+ },
+ /** Return a Fancytree instance, from element, index, event, or jQueryObject.
+ *
+ * @param {Element | jQueryObject | Event | integer | string} [el]
+ * @returns {Fancytree} matching tree or null
+ * @example
+ * $.ui.fancytree.getTree(); // Get first Fancytree instance on page
+ * $.ui.fancytree.getTree(1); // Get second Fancytree instance on page
+ * $.ui.fancytree.getTree(event); // Get tree for this mouse- or keyboard event
+ * $.ui.fancytree.getTree("foo"); // Get tree for this `opts.treeId`
+ * $.ui.fancytree.getTree("#tree"); // Get tree for this matching element
+ *
+ * @since 2.13
+ */
+ getTree: function (el) {
+ var widget,
+ orgEl = el;
+
+ if (el instanceof Fancytree) {
+ return el; // el already was a Fancytree
+ }
+ if (el === undefined) {
+ el = 0; // get first tree
+ }
+ if (typeof el === "number") {
+ el = $(".fancytree-container").eq(el); // el was an integer: return nth instance
+ } else if (typeof el === "string") {
+ // `el` may be a treeId or a selector:
+ el = $("#ft-id-" + orgEl).eq(0);
+ if (!el.length) {
+ el = $(orgEl).eq(0); // el was a selector: use first match
+ }
+ } else if (
+ el instanceof Element ||
+ el instanceof HTMLDocument
+ ) {
+ el = $(el);
+ } else if (el instanceof $) {
+ el = el.eq(0); // el was a jQuery object: use the first
+ } else if (el.originalEvent !== undefined) {
+ el = $(el.target); // el was an Event
+ }
+ // el is a jQuery object wit one element here
+ el = el.closest(":ui-fancytree");
+ widget = el.data("ui-fancytree") || el.data("fancytree"); // the latter is required by jQuery <= 1.8
+ return widget ? widget.tree : null;
+ },
+ /** Return an option value that has a default, but may be overridden by a
+ * callback or a node instance attribute.
+ *
+ * Evaluation sequence:
+ *
+ * If `tree.options.<optionName>` is a callback that returns something, use that.
+ * Else if `node.<optionName>` is defined, use that.
+ * Else if `tree.options.<optionName>` is a value, use that.
+ * Else use `defaultValue`.
+ *
+ * @param {string} optionName name of the option property (on node and tree)
+ * @param {FancytreeNode} node passed to the callback
+ * @param {object} nodeObject where to look for the local option property, e.g. `node` or `node.data`
+ * @param {object} treeOption where to look for the tree option, e.g. `tree.options` or `tree.options.dnd5`
+ * @param {any} [defaultValue]
+ * @returns {any}
+ *
+ * @example
+ * // Check for node.foo, tree,options.foo(), and tree.options.foo:
+ * $.ui.fancytree.evalOption("foo", node, node, tree.options);
+ * // Check for node.data.bar, tree,options.qux.bar(), and tree.options.qux.bar:
+ * $.ui.fancytree.evalOption("bar", node, node.data, tree.options.qux);
+ *
+ * @since 2.22
+ */
+ evalOption: function (
+ optionName,
+ node,
+ nodeObject,
+ treeOptions,
+ defaultValue
+ ) {
+ var ctx,
+ res,
+ tree = node.tree,
+ treeOpt = treeOptions[optionName],
+ nodeOpt = nodeObject[optionName];
+
+ if (_isFunction(treeOpt)) {
+ ctx = {
+ node: node,
+ tree: tree,
+ widget: tree.widget,
+ options: tree.widget.options,
+ typeInfo: tree.types[node.type] || {},
+ };
+ res = treeOpt.call(tree, { type: optionName }, ctx);
+ if (res == null) {
+ res = nodeOpt;
+ }
+ } else {
+ res = nodeOpt == null ? treeOpt : nodeOpt;
+ }
+ if (res == null) {
+ res = defaultValue; // no option set at all: return default
+ }
+ return res;
+ },
+ /** Set expander, checkbox, or node icon, supporting string and object format.
+ *
+ * @param {Element | jQueryObject} span
+ * @param {string} baseClass
+ * @param {string | object} icon
+ * @since 2.27
+ */
+ setSpanIcon: function (span, baseClass, icon) {
+ var $span = $(span);
+
+ if (typeof icon === "string") {
+ $span.attr("class", baseClass + " " + icon);
+ } else {
+ // support object syntax: { text: ligature, addClasse: classname }
+ if (icon.text) {
+ $span.text("" + icon.text);
+ } else if (icon.html) {
+ span.innerHTML = icon.html;
+ }
+ $span.attr(
+ "class",
+ baseClass + " " + (icon.addClass || "")
+ );
+ }
+ },
+ /** Convert a keydown or mouse event to a canonical string like 'ctrl+a',
+ * 'ctrl+shift+f2', 'shift+leftdblclick'.
+ *
+ * This is especially handy for switch-statements in event handlers.
+ *
+ * @param {event}
+ * @returns {string}
+ *
+ * @example
+
+ switch( $.ui.fancytree.eventToString(event) ) {
+ case "-":
+ tree.nodeSetExpanded(ctx, false);
+ break;
+ case "shift+return":
+ tree.nodeSetActive(ctx, true);
+ break;
+ case "down":
+ res = node.navigate(event.which, activate);
+ break;
+ default:
+ handled = false;
+ }
+ if( handled ){
+ event.preventDefault();
+ }
+ */
+ eventToString: function (event) {
+ // Poor-man's hotkeys. See here for a complete implementation:
+ // https://github.com/jeresig/jquery.hotkeys
+ var which = event.which,
+ et = event.type,
+ s = [];
+
+ if (event.altKey) {
+ s.push("alt");
+ }
+ if (event.ctrlKey) {
+ s.push("ctrl");
+ }
+ if (event.metaKey) {
+ s.push("meta");
+ }
+ if (event.shiftKey) {
+ s.push("shift");
+ }
+
+ if (et === "click" || et === "dblclick") {
+ s.push(MOUSE_BUTTONS[event.button] + et);
+ } else if (et === "wheel") {
+ s.push(et);
+ } else if (!IGNORE_KEYCODES[which]) {
+ s.push(
+ SPECIAL_KEYCODES[which] ||
+ String.fromCharCode(which).toLowerCase()
+ );
+ }
+ return s.join("+");
+ },
+ /** Write message to console if debugLevel >= 3
+ * @param {string} msg
+ */
+ info: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 3) {
+ consoleApply("info", arguments);
+ }
+ },
+ /* @deprecated: use eventToString(event) instead.
+ */
+ keyEventToString: function (event) {
+ this.warn(
+ "keyEventToString() is deprecated: use eventToString()"
+ );
+ return this.eventToString(event);
+ },
+ /** Return a wrapped handler method, that provides `this._super`.
+ *
+ * @example
+ // Implement `opts.createNode` event to add the 'draggable' attribute
+ $.ui.fancytree.overrideMethod(ctx.options, "createNode", function(event, data) {
+ // Default processing if any
+ this._super.apply(this, arguments);
+ // Add 'draggable' attribute
+ data.node.span.draggable = true;
+ });
+ *
+ * @param {object} instance
+ * @param {string} methodName
+ * @param {function} handler
+ * @param {object} [context] optional context
+ */
+ overrideMethod: function (instance, methodName, handler, context) {
+ var prevSuper,
+ _super = instance[methodName] || $.noop;
+
+ instance[methodName] = function () {
+ var self = context || this;
+
+ try {
+ prevSuper = self._super;
+ self._super = _super;
+ return handler.apply(self, arguments);
+ } finally {
+ self._super = prevSuper;
+ }
+ };
+ },
+ /**
+ * Parse tree data from HTML <ul> markup
+ *
+ * @param {jQueryObject} $ul
+ * @returns {NodeData[]}
+ */
+ parseHtml: function ($ul) {
+ var classes,
+ className,
+ extraClasses,
+ i,
+ iPos,
+ l,
+ tmp,
+ tmp2,
+ $children = $ul.find(">li"),
+ children = [];
+
+ $children.each(function () {
+ var allData,
+ lowerCaseAttr,
+ $li = $(this),
+ $liSpan = $li.find(">span", this).first(),
+ $liA = $liSpan.length ? null : $li.find(">a").first(),
+ d = { tooltip: null, data: {} };
+
+ if ($liSpan.length) {
+ d.title = $liSpan.html();
+ } else if ($liA && $liA.length) {
+ // If a <li><a> tag is specified, use it literally and extract href/target.
+ d.title = $liA.html();
+ d.data.href = $liA.attr("href");
+ d.data.target = $liA.attr("target");
+ d.tooltip = $liA.attr("title");
+ } else {
+ // If only a <li> tag is specified, use the trimmed string up to
+ // the next child <ul> tag.
+ d.title = $li.html();
+ iPos = d.title.search(/<ul/i);
+ if (iPos >= 0) {
+ d.title = d.title.substring(0, iPos);
+ }
+ }
+ d.title = _trim(d.title);
+
+ // Make sure all fields exist
+ for (i = 0, l = CLASS_ATTRS.length; i < l; i++) {
+ d[CLASS_ATTRS[i]] = undefined;
+ }
+ // Initialize to `true`, if class is set and collect extraClasses
+ classes = this.className.split(" ");
+ extraClasses = [];
+ for (i = 0, l = classes.length; i < l; i++) {
+ className = classes[i];
+ if (CLASS_ATTR_MAP[className]) {
+ d[className] = true;
+ } else {
+ extraClasses.push(className);
+ }
+ }
+ d.extraClasses = extraClasses.join(" ");
+
+ // Parse node options from ID, title and class attributes
+ tmp = $li.attr("title");
+ if (tmp) {
+ d.tooltip = tmp; // overrides <a title='...'>
+ }
+ tmp = $li.attr("id");
+ if (tmp) {
+ d.key = tmp;
+ }
+ // Translate hideCheckbox -> checkbox:false
+ if ($li.attr("hideCheckbox")) {
+ d.checkbox = false;
+ }
+ // Add <li data-NAME='...'> as node.data.NAME
+ allData = _getElementDataAsDict($li);
+ if (allData && !$.isEmptyObject(allData)) {
+ // #507: convert data-hidecheckbox (lower case) to hideCheckbox
+ for (lowerCaseAttr in NODE_ATTR_LOWERCASE_MAP) {
+ if (_hasProp(allData, lowerCaseAttr)) {
+ allData[
+ NODE_ATTR_LOWERCASE_MAP[lowerCaseAttr]
+ ] = allData[lowerCaseAttr];
+ delete allData[lowerCaseAttr];
+ }
+ }
+ // #56: Allow to set special node.attributes from data-...
+ for (i = 0, l = NODE_ATTRS.length; i < l; i++) {
+ tmp = NODE_ATTRS[i];
+ tmp2 = allData[tmp];
+ if (tmp2 != null) {
+ delete allData[tmp];
+ d[tmp] = tmp2;
+ }
+ }
+ // All other data-... goes to node.data...
+ $.extend(d.data, allData);
+ }
+ // Recursive reading of child nodes, if LI tag contains an UL tag
+ $ul = $li.find(">ul").first();
+ if ($ul.length) {
+ d.children = $.ui.fancytree.parseHtml($ul);
+ } else {
+ d.children = d.lazy ? undefined : null;
+ }
+ children.push(d);
+ // FT.debug("parse ", d, children);
+ });
+ return children;
+ },
+ /** Add Fancytree extension definition to the list of globally available extensions.
+ *
+ * @param {object} definition
+ */
+ registerExtension: function (definition) {
+ _assert(
+ definition.name != null,
+ "extensions must have a `name` property."
+ );
+ _assert(
+ definition.version != null,
+ "extensions must have a `version` property."
+ );
+ $.ui.fancytree._extensions[definition.name] = definition;
+ },
+ /** Replacement for the deprecated `jQuery.trim()`.
+ *
+ * @param {string} text
+ */
+ trim: _trim,
+ /** Inverse of escapeHtml().
+ *
+ * @param {string} s
+ * @returns {string}
+ */
+ unescapeHtml: function (s) {
+ var e = document.createElement("div");
+ e.innerHTML = s;
+ return e.childNodes.length === 0
+ ? ""
+ : e.childNodes[0].nodeValue;
+ },
+ /** Write warning message to console if debugLevel >= 2.
+ * @param {string} msg
+ */
+ warn: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 2) {
+ consoleApply("warn", arguments);
+ }
+ },
+ }
+ );
+
+ // Value returned by `require('jquery.fancytree')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.childcounter.js' */// Extending Fancytree
+// ===================
+//
+// See also the [live demo](https://wwWendt.de/tech/fancytree/demo/sample-ext-childcounter.html) of this code.
+//
+// Every extension should have a comment header containing some information
+// about the author, copyright and licensing. Also a pointer to the latest
+// source code.
+// Prefix with `/*!` so the comment is not removed by the minifier.
+
+/*!
+ * jquery.fancytree.childcounter.js
+ *
+ * Add a child counter bubble to tree nodes.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+// To keep the global namespace clean, we wrap everything in a closure.
+// The UMD wrapper pattern defines the dependencies on jQuery and the
+// Fancytree core module, and makes sure that we can use the `require()`
+// syntax with package loaders.
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ // Consider to use [strict mode](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
+ "use strict";
+
+ // The [coding guidelines](http://contribute.jquery.org/style-guide/js/)
+ // require jshint /eslint compliance.
+ // But for this sample, we want to allow unused variables for demonstration purpose.
+
+ /*eslint-disable no-unused-vars */
+
+ // Adding methods
+ // --------------
+
+ // New member functions can be added to the `Fancytree` class.
+ // This function will be available for every tree instance:
+ //
+ // var tree = $.ui.fancytree.getTree("#tree");
+ // tree.countSelected(false);
+
+ $.ui.fancytree._FancytreeClass.prototype.countSelected = function (
+ topOnly
+ ) {
+ var tree = this,
+ treeOptions = tree.options;
+
+ return tree.getSelectedNodes(topOnly).length;
+ };
+
+ // The `FancytreeNode` class can also be easily extended. This would be called
+ // like
+ // node.updateCounters();
+ //
+ // It is also good practice to add a docstring comment.
+ /**
+ * [ext-childcounter] Update counter badges for `node` and its parents.
+ * May be called in the `loadChildren` event, to update parents of lazy loaded
+ * nodes.
+ * @alias FancytreeNode#updateCounters
+ * @requires jquery.fancytree.childcounters.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.updateCounters = function () {
+ var node = this,
+ $badge = $("span.fancytree-childcounter", node.span),
+ extOpts = node.tree.options.childcounter,
+ count = node.countChildren(extOpts.deep);
+
+ node.data.childCounter = count;
+ if (
+ (count || !extOpts.hideZeros) &&
+ (!node.isExpanded() || !extOpts.hideExpanded)
+ ) {
+ if (!$badge.length) {
+ $badge = $("<span class='fancytree-childcounter'/>").appendTo(
+ $(
+ "span.fancytree-icon,span.fancytree-custom-icon",
+ node.span
+ )
+ );
+ }
+ $badge.text(count);
+ } else {
+ $badge.remove();
+ }
+ if (extOpts.deep && !node.isTopLevel() && !node.isRootNode()) {
+ node.parent.updateCounters();
+ }
+ };
+
+ // Finally, we can extend the widget API and create functions that are called
+ // like so:
+ //
+ // $("#tree").fancytree("widgetMethod1", "abc");
+
+ $.ui.fancytree.prototype.widgetMethod1 = function (arg1) {
+ var tree = this.tree;
+ return arg1;
+ };
+
+ // Register a Fancytree extension
+ // ------------------------------
+ // A full blown extension, extension is available for all trees and can be
+ // enabled like so (see also the [live demo](https://wwWendt.de/tech/fancytree/demo/sample-ext-childcounter.html)):
+ //
+ // <script src="../src/jquery.fancytree.js"></script>
+ // <script src="../src/jquery.fancytree.childcounter.js"></script>
+ // ...
+ //
+ // $("#tree").fancytree({
+ // extensions: ["childcounter"],
+ // childcounter: {
+ // hideExpanded: true
+ // },
+ // ...
+ // });
+ //
+
+ /* 'childcounter' extension */
+ $.ui.fancytree.registerExtension({
+ // Every extension must be registered by a unique name.
+ name: "childcounter",
+ // Version information should be compliant with [semver](http://semver.org)
+ version: "2.38.3",
+
+ // Extension specific options and their defaults.
+ // This options will be available as `tree.options.childcounter.hideExpanded`
+
+ options: {
+ deep: true,
+ hideZeros: true,
+ hideExpanded: false,
+ },
+
+ // Attributes other than `options` (or functions) can be defined here, and
+ // will be added to the tree.ext.EXTNAME namespace, in this case `tree.ext.childcounter.foo`.
+ // They can also be accessed as `this._local.foo` from within the extension
+ // methods.
+ foo: 42,
+
+ // Local functions are prefixed with an underscore '_'.
+ // Callable as `this._local._appendCounter()`.
+
+ _appendCounter: function (bar) {
+ var tree = this;
+ },
+
+ // **Override virtual methods for this extension.**
+ //
+ // Fancytree implements a number of 'hook methods', prefixed by 'node...' or 'tree...'.
+ // with a `ctx` argument (see [EventData](https://wwWendt.de/tech/fancytree/doc/jsdoc/global.html#EventData)
+ // for details) and an extended calling context:<br>
+ // `this` : the Fancytree instance<br>
+ // `this._local`: the namespace that contains extension attributes and private methods (same as this.ext.EXTNAME)<br>
+ // `this._super`: the virtual function that was overridden (member of previous extension or Fancytree)
+ //
+ // See also the [complete list of available hook functions](https://wwWendt.de/tech/fancytree/doc/jsdoc/Fancytree_Hooks.html).
+
+ /* Init */
+ // `treeInit` is triggered when a tree is initalized. We can set up classes or
+ // bind event handlers here...
+ treeInit: function (ctx) {
+ var tree = this, // same as ctx.tree,
+ opts = ctx.options,
+ extOpts = ctx.options.childcounter;
+ // Optionally check for dependencies with other extensions
+ /* this._requireExtension("glyph", false, false); */
+ // Call the base implementation
+ this._superApply(arguments);
+ // Add a class to the tree container
+ this.$container.addClass("fancytree-ext-childcounter");
+ },
+
+ // Destroy this tree instance (we only call the default implementation, so
+ // this method could as well be omitted).
+
+ treeDestroy: function (ctx) {
+ this._superApply(arguments);
+ },
+
+ // Overload the `renderTitle` hook, to append a counter badge
+ nodeRenderTitle: function (ctx, title) {
+ var node = ctx.node,
+ extOpts = ctx.options.childcounter,
+ count =
+ node.data.childCounter == null
+ ? node.countChildren(extOpts.deep)
+ : +node.data.childCounter;
+ // Let the base implementation render the title
+ // We use `_super()` instead of `_superApply()` here, since it is a little bit
+ // more performant when called often
+ this._super(ctx, title);
+ // Append a counter badge
+ if (
+ (count || !extOpts.hideZeros) &&
+ (!node.isExpanded() || !extOpts.hideExpanded)
+ ) {
+ $(
+ "span.fancytree-icon,span.fancytree-custom-icon",
+ node.span
+ ).append(
+ $("<span class='fancytree-childcounter'/>").text(count)
+ );
+ }
+ },
+ // Overload the `setExpanded` hook, so the counters are updated
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var tree = ctx.tree,
+ node = ctx.node;
+ // Let the base implementation expand/collapse the node, then redraw the title
+ // after the animation has finished
+ return this._superApply(arguments).always(function () {
+ tree.nodeRenderTitle(ctx);
+ });
+ },
+
+ // End of extension definition
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.clones.js' *//*!
+ *
+ * jquery.fancytree.clones.js
+ * Support faster lookup of nodes by key and shared ref-ids.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ var _assert = $.ui.fancytree.assert;
+
+ /* Return first occurrence of member from array. */
+ function _removeArrayMember(arr, elem) {
+ // TODO: use Array.indexOf for IE >= 9
+ var i;
+ for (i = arr.length - 1; i >= 0; i--) {
+ if (arr[i] === elem) {
+ arr.splice(i, 1);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
+ *
+ * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
+ * @see http://github.com/garycourt/murmurhash-js
+ * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
+ * @see http://sites.google.com/site/murmurhash/
+ *
+ * @param {string} key ASCII only
+ * @param {boolean} [asString=false]
+ * @param {number} seed Positive integer only
+ * @return {number} 32-bit positive integer hash
+ */
+ function hashMurmur3(key, asString, seed) {
+ /*eslint-disable no-bitwise */
+ var h1b,
+ k1,
+ remainder = key.length & 3,
+ bytes = key.length - remainder,
+ h1 = seed,
+ c1 = 0xcc9e2d51,
+ c2 = 0x1b873593,
+ i = 0;
+
+ while (i < bytes) {
+ k1 =
+ (key.charCodeAt(i) & 0xff) |
+ ((key.charCodeAt(++i) & 0xff) << 8) |
+ ((key.charCodeAt(++i) & 0xff) << 16) |
+ ((key.charCodeAt(++i) & 0xff) << 24);
+ ++i;
+
+ k1 =
+ ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) &
+ 0xffffffff;
+ k1 = (k1 << 15) | (k1 >>> 17);
+ k1 =
+ ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) &
+ 0xffffffff;
+
+ h1 ^= k1;
+ h1 = (h1 << 13) | (h1 >>> 19);
+ h1b =
+ ((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 =
+ (h1b & 0xffff) +
+ 0x6b64 +
+ ((((h1b >>> 16) + 0xe654) & 0xffff) << 16);
+ }
+
+ k1 = 0;
+
+ switch (remainder) {
+ case 3:
+ k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
+ // fall through
+ case 2:
+ k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
+ // fall through
+ case 1:
+ k1 ^= key.charCodeAt(i) & 0xff;
+
+ k1 =
+ ((k1 & 0xffff) * c1 +
+ ((((k1 >>> 16) * c1) & 0xffff) << 16)) &
+ 0xffffffff;
+ k1 = (k1 << 15) | (k1 >>> 17);
+ k1 =
+ ((k1 & 0xffff) * c2 +
+ ((((k1 >>> 16) * c2) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 ^= k1;
+ }
+
+ h1 ^= key.length;
+
+ h1 ^= h1 >>> 16;
+ h1 =
+ ((h1 & 0xffff) * 0x85ebca6b +
+ ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 ^= h1 >>> 13;
+ h1 =
+ ((h1 & 0xffff) * 0xc2b2ae35 +
+ ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 ^= h1 >>> 16;
+
+ if (asString) {
+ // Convert to 8 digit hex string
+ return ("0000000" + (h1 >>> 0).toString(16)).substr(-8);
+ }
+ return h1 >>> 0;
+ /*eslint-enable no-bitwise */
+ }
+
+ /*
+ * Return a unique key for node by calculating the hash of the parents refKey-list.
+ */
+ function calcUniqueKey(node) {
+ var key,
+ h1,
+ path = $.map(node.getParentList(false, true), function (e) {
+ return e.refKey || e.key;
+ });
+
+ path = path.join("/");
+ // 32-bit has a high probability of collisions, so we pump up to 64-bit
+ // https://security.stackexchange.com/q/209882/207588
+
+ h1 = hashMurmur3(path, true);
+ key = "id_" + h1 + hashMurmur3(h1 + path, true);
+
+ return key;
+ }
+
+ /**
+ * [ext-clones] Return a list of clone-nodes (i.e. same refKey) or null.
+ * @param {boolean} [includeSelf=false]
+ * @returns {FancytreeNode[] | null}
+ *
+ * @alias FancytreeNode#getCloneList
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.getCloneList = function (
+ includeSelf
+ ) {
+ var key,
+ tree = this.tree,
+ refList = tree.refMap[this.refKey] || null,
+ keyMap = tree.keyMap;
+
+ if (refList) {
+ key = this.key;
+ // Convert key list to node list
+ if (includeSelf) {
+ refList = $.map(refList, function (val) {
+ return keyMap[val];
+ });
+ } else {
+ refList = $.map(refList, function (val) {
+ return val === key ? null : keyMap[val];
+ });
+ if (refList.length < 1) {
+ refList = null;
+ }
+ }
+ }
+ return refList;
+ };
+
+ /**
+ * [ext-clones] Return true if this node has at least another clone with same refKey.
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#isClone
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.isClone = function () {
+ var refKey = this.refKey || null,
+ refList = (refKey && this.tree.refMap[refKey]) || null;
+ return !!(refList && refList.length > 1);
+ };
+
+ /**
+ * [ext-clones] Update key and/or refKey for an existing node.
+ * @param {string} key
+ * @param {string} refKey
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#reRegister
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.reRegister = function (
+ key,
+ refKey
+ ) {
+ key = key == null ? null : "" + key;
+ refKey = refKey == null ? null : "" + refKey;
+ // this.debug("reRegister", key, refKey);
+
+ var tree = this.tree,
+ prevKey = this.key,
+ prevRefKey = this.refKey,
+ keyMap = tree.keyMap,
+ refMap = tree.refMap,
+ refList = refMap[prevRefKey] || null,
+ // curCloneKeys = refList ? node.getCloneList(true),
+ modified = false;
+
+ // Key has changed: update all references
+ if (key != null && key !== this.key) {
+ if (keyMap[key]) {
+ $.error(
+ "[ext-clones] reRegister(" +
+ key +
+ "): already exists: " +
+ this
+ );
+ }
+ // Update keyMap
+ delete keyMap[prevKey];
+ keyMap[key] = this;
+ // Update refMap
+ if (refList) {
+ refMap[prevRefKey] = $.map(refList, function (e) {
+ return e === prevKey ? key : e;
+ });
+ }
+ this.key = key;
+ modified = true;
+ }
+
+ // refKey has changed
+ if (refKey != null && refKey !== this.refKey) {
+ // Remove previous refKeys
+ if (refList) {
+ if (refList.length === 1) {
+ delete refMap[prevRefKey];
+ } else {
+ refMap[prevRefKey] = $.map(refList, function (e) {
+ return e === prevKey ? null : e;
+ });
+ }
+ }
+ // Add refKey
+ if (refMap[refKey]) {
+ refMap[refKey].append(key);
+ } else {
+ refMap[refKey] = [this.key];
+ }
+ this.refKey = refKey;
+ modified = true;
+ }
+ return modified;
+ };
+
+ /**
+ * [ext-clones] Define a refKey for an existing node.
+ * @param {string} refKey
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#setRefKey
+ * @requires jquery.fancytree.clones.js
+ * @since 2.16
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.setRefKey = function (refKey) {
+ return this.reRegister(null, refKey);
+ };
+
+ /**
+ * [ext-clones] Return all nodes with a given refKey (null if not found).
+ * @param {string} refKey
+ * @param {FancytreeNode} [rootNode] optionally restrict results to descendants of this node
+ * @returns {FancytreeNode[] | null}
+ * @alias Fancytree#getNodesByRef
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.getNodesByRef = function (
+ refKey,
+ rootNode
+ ) {
+ var keyMap = this.keyMap,
+ refList = this.refMap[refKey] || null;
+
+ if (refList) {
+ // Convert key list to node list
+ if (rootNode) {
+ refList = $.map(refList, function (val) {
+ var node = keyMap[val];
+ return node.isDescendantOf(rootNode) ? node : null;
+ });
+ } else {
+ refList = $.map(refList, function (val) {
+ return keyMap[val];
+ });
+ }
+ if (refList.length < 1) {
+ refList = null;
+ }
+ }
+ return refList;
+ };
+
+ /**
+ * [ext-clones] Replace a refKey with a new one.
+ * @param {string} oldRefKey
+ * @param {string} newRefKey
+ * @alias Fancytree#changeRefKey
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.changeRefKey = function (
+ oldRefKey,
+ newRefKey
+ ) {
+ var i,
+ node,
+ keyMap = this.keyMap,
+ refList = this.refMap[oldRefKey] || null;
+
+ if (refList) {
+ for (i = 0; i < refList.length; i++) {
+ node = keyMap[refList[i]];
+ node.refKey = newRefKey;
+ }
+ delete this.refMap[oldRefKey];
+ this.refMap[newRefKey] = refList;
+ }
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "clones",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers
+ highlightClones: false, // set 'fancytree-clone' class on any node that has at least one clone
+ },
+
+ treeCreate: function (ctx) {
+ this._superApply(arguments);
+ ctx.tree.refMap = {};
+ ctx.tree.keyMap = {};
+ },
+ treeInit: function (ctx) {
+ this.$container.addClass("fancytree-ext-clones");
+ _assert(ctx.options.defaultKey == null);
+ // Generate unique / reproducible default keys
+ ctx.options.defaultKey = function (node) {
+ return calcUniqueKey(node);
+ };
+ // The default implementation loads initial data
+ this._superApply(arguments);
+ },
+ treeClear: function (ctx) {
+ ctx.tree.refMap = {};
+ ctx.tree.keyMap = {};
+ return this._superApply(arguments);
+ },
+ treeRegisterNode: function (ctx, add, node) {
+ var refList,
+ len,
+ tree = ctx.tree,
+ keyMap = tree.keyMap,
+ refMap = tree.refMap,
+ key = node.key,
+ refKey = node && node.refKey != null ? "" + node.refKey : null;
+
+ // ctx.tree.debug("clones.treeRegisterNode", add, node);
+
+ if (node.isStatusNode()) {
+ return this._super(ctx, add, node);
+ }
+
+ if (add) {
+ if (keyMap[node.key] != null) {
+ var other = keyMap[node.key],
+ msg =
+ "clones.treeRegisterNode: duplicate key '" +
+ node.key +
+ "': /" +
+ node.getPath(true) +
+ " => " +
+ other.getPath(true);
+ // Sometimes this exception is not visible in the console,
+ // so we also write it:
+ tree.error(msg);
+ $.error(msg);
+ }
+ keyMap[key] = node;
+
+ if (refKey) {
+ refList = refMap[refKey];
+ if (refList) {
+ refList.push(key);
+ if (
+ refList.length === 2 &&
+ ctx.options.clones.highlightClones
+ ) {
+ // Mark peer node, if it just became a clone (no need to
+ // mark current node, since it will be rendered later anyway)
+ keyMap[refList[0]].renderStatus();
+ }
+ } else {
+ refMap[refKey] = [key];
+ }
+ // node.debug("clones.treeRegisterNode: add clone =>", refMap[refKey]);
+ }
+ } else {
+ if (keyMap[key] == null) {
+ $.error(
+ "clones.treeRegisterNode: node.key not registered: " +
+ node.key
+ );
+ }
+ delete keyMap[key];
+ if (refKey) {
+ refList = refMap[refKey];
+ // node.debug("clones.treeRegisterNode: remove clone BEFORE =>", refMap[refKey]);
+ if (refList) {
+ len = refList.length;
+ if (len <= 1) {
+ _assert(len === 1);
+ _assert(refList[0] === key);
+ delete refMap[refKey];
+ } else {
+ _removeArrayMember(refList, key);
+ // Unmark peer node, if this was the only clone
+ if (
+ len === 2 &&
+ ctx.options.clones.highlightClones
+ ) {
+ // node.debug("clones.treeRegisterNode: last =>", node.getCloneList());
+ keyMap[refList[0]].renderStatus();
+ }
+ }
+ // node.debug("clones.treeRegisterNode: remove clone =>", refMap[refKey]);
+ }
+ }
+ }
+ return this._super(ctx, add, node);
+ },
+ nodeRenderStatus: function (ctx) {
+ var $span,
+ res,
+ node = ctx.node;
+
+ res = this._super(ctx);
+
+ if (ctx.options.clones.highlightClones) {
+ $span = $(node[ctx.tree.statusClassPropName]);
+ // Only if span already exists
+ if ($span.length && node.isClone()) {
+ // node.debug("clones.nodeRenderStatus: ", ctx.options.clones.highlightClones);
+ $span.addClass("fancytree-clone");
+ }
+ }
+ return res;
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var res,
+ scpn = ctx.tree.statusClassPropName,
+ node = ctx.node;
+
+ res = this._superApply(arguments);
+
+ if (ctx.options.clones.highlightActiveClones && node.isClone()) {
+ $.each(node.getCloneList(true), function (idx, n) {
+ // n.debug("clones.nodeSetActive: ", flag !== false);
+ $(n[scpn]).toggleClass(
+ "fancytree-active-clone",
+ flag !== false
+ );
+ });
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.dnd5.js' *//*!
+ * jquery.fancytree.dnd5.js
+ *
+ * Drag-and-drop support (native HTML5).
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+/*
+ #TODO
+ Compatiblity when dragging between *separate* windows:
+
+ Drag from Chrome Edge FF IE11 Safari
+ To Chrome ok ok ok NO ?
+ Edge ok ok ok NO ?
+ FF ok ok ok NO ?
+ IE 11 ok ok ok ok ?
+ Safari ? ? ? ? ok
+
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var FT = $.ui.fancytree,
+ isMac = /Mac/.test(navigator.platform),
+ classDragSource = "fancytree-drag-source",
+ classDragRemove = "fancytree-drag-remove",
+ classDropAccept = "fancytree-drop-accept",
+ classDropAfter = "fancytree-drop-after",
+ classDropBefore = "fancytree-drop-before",
+ classDropOver = "fancytree-drop-over",
+ classDropReject = "fancytree-drop-reject",
+ classDropTarget = "fancytree-drop-target",
+ nodeMimeType = "application/x-fancytree-node",
+ $dropMarker = null,
+ $dragImage,
+ $extraHelper,
+ SOURCE_NODE = null,
+ SOURCE_NODE_LIST = null,
+ $sourceList = null,
+ DRAG_ENTER_RESPONSE = null,
+ // SESSION_DATA = null, // plain object passed to events as `data`
+ SUGGESTED_DROP_EFFECT = null,
+ REQUESTED_DROP_EFFECT = null,
+ REQUESTED_EFFECT_ALLOWED = null,
+ LAST_HIT_MODE = null,
+ DRAG_OVER_STAMP = null; // Time when a node entered the 'over' hitmode
+
+ /* */
+ function _clearGlobals() {
+ DRAG_ENTER_RESPONSE = null;
+ DRAG_OVER_STAMP = null;
+ REQUESTED_DROP_EFFECT = null;
+ REQUESTED_EFFECT_ALLOWED = null;
+ SUGGESTED_DROP_EFFECT = null;
+ SOURCE_NODE = null;
+ SOURCE_NODE_LIST = null;
+ if ($sourceList) {
+ $sourceList.removeClass(classDragSource + " " + classDragRemove);
+ }
+ $sourceList = null;
+ if ($dropMarker) {
+ $dropMarker.hide();
+ }
+ // Take this badge off of me - I can't use it anymore:
+ if ($extraHelper) {
+ $extraHelper.remove();
+ $extraHelper = null;
+ }
+ }
+
+ /* Convert number to string and prepend +/-; return empty string for 0.*/
+ function offsetString(n) {
+ // eslint-disable-next-line no-nested-ternary
+ return n === 0 ? "" : n > 0 ? "+" + n : "" + n;
+ }
+
+ /* Convert a dragEnter() or dragOver() response to a canonical form.
+ * Return false or plain object
+ * @param {string|object|boolean} r
+ * @return {object|false}
+ */
+ function normalizeDragEnterResponse(r) {
+ var res;
+
+ if (!r) {
+ return false;
+ }
+ if ($.isPlainObject(r)) {
+ res = {
+ over: !!r.over,
+ before: !!r.before,
+ after: !!r.after,
+ };
+ } else if (Array.isArray(r)) {
+ res = {
+ over: $.inArray("over", r) >= 0,
+ before: $.inArray("before", r) >= 0,
+ after: $.inArray("after", r) >= 0,
+ };
+ } else {
+ res = {
+ over: r === true || r === "over",
+ before: r === true || r === "before",
+ after: r === true || r === "after",
+ };
+ }
+ if (Object.keys(res).length === 0) {
+ return false;
+ }
+ // if( Object.keys(res).length === 1 ) {
+ // res.unique = res[0];
+ // }
+ return res;
+ }
+
+ /* Convert a dataTransfer.effectAllowed to a canonical form.
+ * Return false or plain object
+ * @param {string|boolean} r
+ * @return {object|false}
+ */
+ // function normalizeEffectAllowed(r) {
+ // if (!r || r === "none") {
+ // return false;
+ // }
+ // var all = r === "all",
+ // res = {
+ // copy: all || /copy/i.test(r),
+ // link: all || /link/i.test(r),
+ // move: all || /move/i.test(r),
+ // };
+
+ // return res;
+ // }
+
+ /* Implement auto scrolling when drag cursor is in top/bottom area of scroll parent. */
+ function autoScroll(tree, event) {
+ var spOfs,
+ scrollTop,
+ delta,
+ dndOpts = tree.options.dnd5,
+ sp = tree.$scrollParent[0],
+ sensitivity = dndOpts.scrollSensitivity,
+ speed = dndOpts.scrollSpeed,
+ scrolled = 0;
+
+ if (sp !== document && sp.tagName !== "HTML") {
+ spOfs = tree.$scrollParent.offset();
+ scrollTop = sp.scrollTop;
+ if (spOfs.top + sp.offsetHeight - event.pageY < sensitivity) {
+ delta =
+ sp.scrollHeight -
+ tree.$scrollParent.innerHeight() -
+ scrollTop;
+ // console.log ("sp.offsetHeight: " + sp.offsetHeight
+ // + ", spOfs.top: " + spOfs.top
+ // + ", scrollTop: " + scrollTop
+ // + ", innerHeight: " + tree.$scrollParent.innerHeight()
+ // + ", scrollHeight: " + sp.scrollHeight
+ // + ", delta: " + delta
+ // );
+ if (delta > 0) {
+ sp.scrollTop = scrolled = scrollTop + speed;
+ }
+ } else if (scrollTop > 0 && event.pageY - spOfs.top < sensitivity) {
+ sp.scrollTop = scrolled = scrollTop - speed;
+ }
+ } else {
+ scrollTop = $(document).scrollTop();
+ if (scrollTop > 0 && event.pageY - scrollTop < sensitivity) {
+ scrolled = scrollTop - speed;
+ $(document).scrollTop(scrolled);
+ } else if (
+ $(window).height() - (event.pageY - scrollTop) <
+ sensitivity
+ ) {
+ scrolled = scrollTop + speed;
+ $(document).scrollTop(scrolled);
+ }
+ }
+ if (scrolled) {
+ tree.debug("autoScroll: " + scrolled + "px");
+ }
+ return scrolled;
+ }
+
+ /* Guess dropEffect from modifier keys.
+ * Using rules suggested here:
+ * https://ux.stackexchange.com/a/83769
+ * @returns
+ * 'copy', 'link', 'move', or 'none'
+ */
+ function evalEffectModifiers(tree, event, effectDefault) {
+ var res = effectDefault;
+
+ if (isMac) {
+ if (event.metaKey && event.altKey) {
+ // Mac: [Control] + [Option]
+ res = "link";
+ } else if (event.ctrlKey) {
+ // Chrome on Mac: [Control]
+ res = "link";
+ } else if (event.metaKey) {
+ // Mac: [Command]
+ res = "move";
+ } else if (event.altKey) {
+ // Mac: [Option]
+ res = "copy";
+ }
+ } else {
+ if (event.ctrlKey) {
+ // Windows: [Ctrl]
+ res = "copy";
+ } else if (event.shiftKey) {
+ // Windows: [Shift]
+ res = "move";
+ } else if (event.altKey) {
+ // Windows: [Alt]
+ res = "link";
+ }
+ }
+ if (res !== SUGGESTED_DROP_EFFECT) {
+ tree.info(
+ "evalEffectModifiers: " +
+ event.type +
+ " - evalEffectModifiers(): " +
+ SUGGESTED_DROP_EFFECT +
+ " -> " +
+ res
+ );
+ }
+ SUGGESTED_DROP_EFFECT = res;
+ // tree.debug("evalEffectModifiers: " + res);
+ return res;
+ }
+ /*
+ * Check if the previous callback (dragEnter, dragOver, ...) has changed
+ * the `data` object and apply those settings.
+ *
+ * Safari:
+ * It seems that `dataTransfer.dropEffect` can only be set on dragStart, and will remain
+ * even if the cursor changes when [Alt] or [Ctrl] are pressed (?)
+ * Using rules suggested here:
+ * https://ux.stackexchange.com/a/83769
+ * @returns
+ * 'copy', 'link', 'move', or 'none'
+ */
+ function prepareDropEffectCallback(event, data) {
+ var tree = data.tree,
+ dataTransfer = data.dataTransfer;
+
+ if (event.type === "dragstart") {
+ data.effectAllowed = tree.options.dnd5.effectAllowed;
+ data.dropEffect = tree.options.dnd5.dropEffectDefault;
+ } else {
+ data.effectAllowed = REQUESTED_EFFECT_ALLOWED;
+ data.dropEffect = REQUESTED_DROP_EFFECT;
+ }
+ data.dropEffectSuggested = evalEffectModifiers(
+ tree,
+ event,
+ tree.options.dnd5.dropEffectDefault
+ );
+ data.isMove = data.dropEffect === "move";
+ data.files = dataTransfer.files || [];
+
+ // if (REQUESTED_EFFECT_ALLOWED !== dataTransfer.effectAllowed) {
+ // tree.warn(
+ // "prepareDropEffectCallback(" +
+ // event.type +
+ // "): dataTransfer.effectAllowed changed from " +
+ // REQUESTED_EFFECT_ALLOWED +
+ // " -> " +
+ // dataTransfer.effectAllowed
+ // );
+ // }
+ // if (REQUESTED_DROP_EFFECT !== dataTransfer.dropEffect) {
+ // tree.warn(
+ // "prepareDropEffectCallback(" +
+ // event.type +
+ // "): dataTransfer.dropEffect changed from requested " +
+ // REQUESTED_DROP_EFFECT +
+ // " to " +
+ // dataTransfer.dropEffect
+ // );
+ // }
+ }
+
+ function applyDropEffectCallback(event, data, allowDrop) {
+ var tree = data.tree,
+ dataTransfer = data.dataTransfer;
+
+ if (
+ event.type !== "dragstart" &&
+ REQUESTED_EFFECT_ALLOWED !== data.effectAllowed
+ ) {
+ tree.warn(
+ "effectAllowed should only be changed in dragstart event: " +
+ event.type +
+ ": data.effectAllowed changed from " +
+ REQUESTED_EFFECT_ALLOWED +
+ " -> " +
+ data.effectAllowed
+ );
+ }
+
+ if (allowDrop === false) {
+ tree.info("applyDropEffectCallback: allowDrop === false");
+ data.effectAllowed = "none";
+ data.dropEffect = "none";
+ }
+ // if (REQUESTED_DROP_EFFECT !== data.dropEffect) {
+ // tree.debug(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): data.dropEffect changed from previous " +
+ // REQUESTED_DROP_EFFECT +
+ // " to " +
+ // data.dropEffect
+ // );
+ // }
+
+ data.isMove = data.dropEffect === "move";
+ // data.isMove = data.dropEffectSuggested === "move";
+
+ // `effectAllowed` must only be defined in dragstart event, so we
+ // store it in a global variable for reference
+ if (event.type === "dragstart") {
+ REQUESTED_EFFECT_ALLOWED = data.effectAllowed;
+ REQUESTED_DROP_EFFECT = data.dropEffect;
+ }
+
+ // if (REQUESTED_DROP_EFFECT !== dataTransfer.dropEffect) {
+ // data.tree.info(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): dataTransfer.dropEffect changed from " +
+ // REQUESTED_DROP_EFFECT +
+ // " -> " +
+ // dataTransfer.dropEffect
+ // );
+ // }
+ dataTransfer.effectAllowed = REQUESTED_EFFECT_ALLOWED;
+ dataTransfer.dropEffect = REQUESTED_DROP_EFFECT;
+
+ // tree.debug(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): set " +
+ // dataTransfer.dropEffect +
+ // "/" +
+ // dataTransfer.effectAllowed
+ // );
+ // if (REQUESTED_DROP_EFFECT !== dataTransfer.dropEffect) {
+ // data.tree.warn(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): could not set dataTransfer.dropEffect to " +
+ // REQUESTED_DROP_EFFECT +
+ // ": got " +
+ // dataTransfer.dropEffect
+ // );
+ // }
+ return REQUESTED_DROP_EFFECT;
+ }
+
+ /* Handle dragover event (fired every x ms) on valid drop targets.
+ *
+ * - Auto-scroll when cursor is in border regions
+ * - Apply restrictioan like 'preventVoidMoves'
+ * - Calculate hit mode
+ * - Calculate drop effect
+ * - Trigger dragOver() callback to let user modify hit mode and drop effect
+ * - Adjust the drop marker accordingly
+ *
+ * @returns hitMode
+ */
+ function handleDragOver(event, data) {
+ // Implement auto-scrolling
+ if (data.options.dnd5.scroll) {
+ autoScroll(data.tree, event);
+ }
+ // Bail out with previous response if we get an invalid dragover
+ if (!data.node) {
+ data.tree.warn("Ignored dragover for non-node"); //, event, data);
+ return LAST_HIT_MODE;
+ }
+
+ var markerOffsetX,
+ nodeOfs,
+ pos,
+ relPosY,
+ hitMode = null,
+ tree = data.tree,
+ options = tree.options,
+ dndOpts = options.dnd5,
+ targetNode = data.node,
+ sourceNode = data.otherNode,
+ markerAt = "center",
+ $target = $(targetNode.span),
+ $targetTitle = $target.find("span.fancytree-title");
+
+ if (DRAG_ENTER_RESPONSE === false) {
+ tree.debug("Ignored dragover, since dragenter returned false.");
+ return false;
+ } else if (typeof DRAG_ENTER_RESPONSE === "string") {
+ $.error("assert failed: dragenter returned string");
+ }
+ // Calculate hitMode from relative cursor position.
+ nodeOfs = $target.offset();
+ relPosY = (event.pageY - nodeOfs.top) / $target.height();
+ if (event.pageY === undefined) {
+ tree.warn("event.pageY is undefined: see issue #1013.");
+ }
+
+ if (DRAG_ENTER_RESPONSE.after && relPosY > 0.75) {
+ hitMode = "after";
+ } else if (
+ !DRAG_ENTER_RESPONSE.over &&
+ DRAG_ENTER_RESPONSE.after &&
+ relPosY > 0.5
+ ) {
+ hitMode = "after";
+ } else if (DRAG_ENTER_RESPONSE.before && relPosY <= 0.25) {
+ hitMode = "before";
+ } else if (
+ !DRAG_ENTER_RESPONSE.over &&
+ DRAG_ENTER_RESPONSE.before &&
+ relPosY <= 0.5
+ ) {
+ hitMode = "before";
+ } else if (DRAG_ENTER_RESPONSE.over) {
+ hitMode = "over";
+ }
+ // Prevent no-ops like 'before source node'
+ // TODO: these are no-ops when moving nodes, but not in copy mode
+ if (dndOpts.preventVoidMoves && data.dropEffect === "move") {
+ if (targetNode === sourceNode) {
+ targetNode.debug("Drop over source node prevented.");
+ hitMode = null;
+ } else if (
+ hitMode === "before" &&
+ sourceNode &&
+ targetNode === sourceNode.getNextSibling()
+ ) {
+ targetNode.debug("Drop after source node prevented.");
+ hitMode = null;
+ } else if (
+ hitMode === "after" &&
+ sourceNode &&
+ targetNode === sourceNode.getPrevSibling()
+ ) {
+ targetNode.debug("Drop before source node prevented.");
+ hitMode = null;
+ } else if (
+ hitMode === "over" &&
+ sourceNode &&
+ sourceNode.parent === targetNode &&
+ sourceNode.isLastSibling()
+ ) {
+ targetNode.debug("Drop last child over own parent prevented.");
+ hitMode = null;
+ }
+ }
+ // Let callback modify the calculated hitMode
+ data.hitMode = hitMode;
+ if (hitMode && dndOpts.dragOver) {
+ prepareDropEffectCallback(event, data);
+ dndOpts.dragOver(targetNode, data);
+ var allowDrop = !!hitMode;
+ applyDropEffectCallback(event, data, allowDrop);
+ hitMode = data.hitMode;
+ }
+ LAST_HIT_MODE = hitMode;
+ //
+ if (hitMode === "after" || hitMode === "before" || hitMode === "over") {
+ markerOffsetX = dndOpts.dropMarkerOffsetX || 0;
+ switch (hitMode) {
+ case "before":
+ markerAt = "top";
+ markerOffsetX += dndOpts.dropMarkerInsertOffsetX || 0;
+ break;
+ case "after":
+ markerAt = "bottom";
+ markerOffsetX += dndOpts.dropMarkerInsertOffsetX || 0;
+ break;
+ }
+
+ pos = {
+ my: "left" + offsetString(markerOffsetX) + " center",
+ at: "left " + markerAt,
+ of: $targetTitle,
+ };
+ if (options.rtl) {
+ pos.my = "right" + offsetString(-markerOffsetX) + " center";
+ pos.at = "right " + markerAt;
+ // console.log("rtl", pos);
+ }
+ $dropMarker
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropOver, hitMode === "over")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .show()
+ .position(FT.fixPositionOptions(pos));
+ } else {
+ $dropMarker.hide();
+ // console.log("hide dropmarker")
+ }
+
+ $(targetNode.span)
+ .toggleClass(
+ classDropTarget,
+ hitMode === "after" ||
+ hitMode === "before" ||
+ hitMode === "over"
+ )
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .toggleClass(classDropAccept, hitMode === "over")
+ .toggleClass(classDropReject, hitMode === false);
+
+ return hitMode;
+ }
+
+ /*
+ * Handle dragstart drag dragend events on the container
+ */
+ function onDragEvent(event) {
+ var json,
+ tree = this,
+ dndOpts = tree.options.dnd5,
+ node = FT.getNode(event),
+ dataTransfer =
+ event.dataTransfer || event.originalEvent.dataTransfer,
+ data = {
+ tree: tree,
+ node: node,
+ options: tree.options,
+ originalEvent: event.originalEvent,
+ widget: tree.widget,
+ dataTransfer: dataTransfer,
+ useDefaultImage: true,
+ dropEffect: undefined,
+ dropEffectSuggested: undefined,
+ effectAllowed: undefined, // set by dragstart
+ files: undefined, // only for drop events
+ isCancelled: undefined, // set by dragend
+ isMove: undefined,
+ };
+
+ switch (event.type) {
+ case "dragstart":
+ if (!node) {
+ tree.info("Ignored dragstart on a non-node.");
+ return false;
+ }
+ // Store current source node in different formats
+ SOURCE_NODE = node;
+
+ // Also optionally store selected nodes
+ if (dndOpts.multiSource === false) {
+ SOURCE_NODE_LIST = [node];
+ } else if (dndOpts.multiSource === true) {
+ if (node.isSelected()) {
+ SOURCE_NODE_LIST = tree.getSelectedNodes();
+ } else {
+ SOURCE_NODE_LIST = [node];
+ }
+ } else {
+ SOURCE_NODE_LIST = dndOpts.multiSource(node, data);
+ }
+ // Cache as array of jQuery objects for faster access:
+ $sourceList = $(
+ $.map(SOURCE_NODE_LIST, function (n) {
+ return n.span;
+ })
+ );
+ // Set visual feedback
+ $sourceList.addClass(classDragSource);
+
+ // Set payload
+ // Note:
+ // Transfer data is only accessible on dragstart and drop!
+ // For all other events the formats and kinds in the drag
+ // data store list of items representing dragged data can be
+ // enumerated, but the data itself is unavailable and no new
+ // data can be added.
+ var nodeData = node.toDict(true, dndOpts.sourceCopyHook);
+ nodeData.treeId = node.tree._id;
+ json = JSON.stringify(nodeData);
+ try {
+ dataTransfer.setData(nodeMimeType, json);
+ dataTransfer.setData("text/html", $(node.span).html());
+ dataTransfer.setData("text/plain", node.title);
+ } catch (ex) {
+ // IE only accepts 'text' type
+ tree.warn(
+ "Could not set data (IE only accepts 'text') - " + ex
+ );
+ }
+ // We always need to set the 'text' type if we want to drag
+ // Because IE 11 only accepts this single type.
+ // If we pass JSON here, IE can can access all node properties,
+ // even when the source lives in another window. (D'n'd inside
+ // the same window will always work.)
+ // The drawback is, that in this case ALL browsers will see
+ // the JSON representation as 'text', so dragging
+ // to a text field will insert the JSON string instead of
+ // the node title.
+ if (dndOpts.setTextTypeJson) {
+ dataTransfer.setData("text", json);
+ } else {
+ dataTransfer.setData("text", node.title);
+ }
+
+ // Set the allowed drag modes (combinations of move, copy, and link)
+ // (effectAllowed can only be set in the dragstart event.)
+ // This can be overridden in the dragStart() callback
+ prepareDropEffectCallback(event, data);
+
+ // Let user cancel or modify above settings
+ // Realize potential changes by previous callback
+ if (dndOpts.dragStart(node, data) === false) {
+ // Cancel dragging
+ // dataTransfer.dropEffect = "none";
+ _clearGlobals();
+ return false;
+ }
+ applyDropEffectCallback(event, data);
+
+ // Unless user set `data.useDefaultImage` to false in dragStart,
+ // generata a default drag image now:
+ $extraHelper = null;
+
+ if (data.useDefaultImage) {
+ // Set the title as drag image (otherwise it would contain the expander)
+ $dragImage = $(node.span).find(".fancytree-title");
+
+ if (SOURCE_NODE_LIST && SOURCE_NODE_LIST.length > 1) {
+ // Add a counter badge to node title if dragging more than one node.
+ // We want this, because the element that is used as drag image
+ // must be *visible* in the DOM, so we cannot create some hidden
+ // custom markup.
+ // See https://kryogenix.org/code/browser/custom-drag-image.html
+ // Also, since IE 11 and Edge don't support setDragImage() alltogether,
+ // it gives som feedback to the user.
+ // The badge will be removed later on drag end.
+ $extraHelper = $(
+ "<span class='fancytree-childcounter'/>"
+ )
+ .text("+" + (SOURCE_NODE_LIST.length - 1))
+ .appendTo($dragImage);
+ }
+ if (dataTransfer.setDragImage) {
+ // IE 11 and Edge do not support this
+ dataTransfer.setDragImage($dragImage[0], -10, -10);
+ }
+ }
+ return true;
+
+ case "drag":
+ // Called every few milliseconds (no matter if the
+ // cursor is over a valid drop target)
+ // data.tree.info("drag", SOURCE_NODE)
+ prepareDropEffectCallback(event, data);
+ dndOpts.dragDrag(node, data);
+ applyDropEffectCallback(event, data);
+
+ $sourceList.toggleClass(classDragRemove, data.isMove);
+ break;
+
+ case "dragend":
+ // Called at the end of a d'n'd process (after drop)
+ // Note caveat: If drop removed the dragged source element,
+ // we may not get this event, since the target does not exist
+ // anymore
+ prepareDropEffectCallback(event, data);
+
+ _clearGlobals();
+
+ data.isCancelled = !LAST_HIT_MODE;
+ dndOpts.dragEnd(node, data, !LAST_HIT_MODE);
+ // applyDropEffectCallback(event, data);
+ break;
+ }
+ }
+ /*
+ * Handle dragenter dragover dragleave drop events on the container
+ */
+ function onDropEvent(event) {
+ var json,
+ allowAutoExpand,
+ nodeData,
+ isSourceFtNode,
+ r,
+ res,
+ tree = this,
+ dndOpts = tree.options.dnd5,
+ allowDrop = null,
+ node = FT.getNode(event),
+ dataTransfer =
+ event.dataTransfer || event.originalEvent.dataTransfer,
+ data = {
+ tree: tree,
+ node: node,
+ options: tree.options,
+ originalEvent: event.originalEvent,
+ widget: tree.widget,
+ hitMode: DRAG_ENTER_RESPONSE,
+ dataTransfer: dataTransfer,
+ otherNode: SOURCE_NODE || null,
+ otherNodeList: SOURCE_NODE_LIST || null,
+ otherNodeData: null, // set by drop event
+ useDefaultImage: true,
+ dropEffect: undefined,
+ dropEffectSuggested: undefined,
+ effectAllowed: undefined, // set by dragstart
+ files: null, // list of File objects (may be [])
+ isCancelled: undefined, // set by drop event
+ isMove: undefined,
+ };
+
+ // data.isMove = dropEffect === "move";
+
+ switch (event.type) {
+ case "dragenter":
+ // The dragenter event is fired when a dragged element or
+ // text selection enters a valid drop target.
+
+ DRAG_OVER_STAMP = null;
+ if (!node) {
+ // Sometimes we get dragenter for the container element
+ tree.debug(
+ "Ignore non-node " +
+ event.type +
+ ": " +
+ event.target.tagName +
+ "." +
+ event.target.className
+ );
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ }
+
+ $(node.span)
+ .addClass(classDropOver)
+ .removeClass(classDropAccept + " " + classDropReject);
+
+ // Data is only readable in the dragstart and drop event,
+ // but we can check for the type:
+ isSourceFtNode =
+ $.inArray(nodeMimeType, dataTransfer.types) >= 0;
+
+ if (dndOpts.preventNonNodes && !isSourceFtNode) {
+ node.debug("Reject dropping a non-node.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (
+ dndOpts.preventForeignNodes &&
+ (!SOURCE_NODE || SOURCE_NODE.tree !== node.tree)
+ ) {
+ node.debug("Reject dropping a foreign node.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (
+ dndOpts.preventSameParent &&
+ data.otherNode &&
+ data.otherNode.tree === node.tree &&
+ node.parent === data.otherNode.parent
+ ) {
+ node.debug("Reject dropping as sibling (same parent).");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (
+ dndOpts.preventRecursion &&
+ data.otherNode &&
+ data.otherNode.tree === node.tree &&
+ node.isDescendantOf(data.otherNode)
+ ) {
+ node.debug("Reject dropping below own ancestor.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (dndOpts.preventLazyParents && !node.isLoaded()) {
+ node.warn("Drop over unloaded target node prevented.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ }
+ $dropMarker.show();
+
+ // Call dragEnter() to figure out if (and where) dropping is allowed
+ prepareDropEffectCallback(event, data);
+ r = dndOpts.dragEnter(node, data);
+
+ res = normalizeDragEnterResponse(r);
+ // alert("res:" + JSON.stringify(res))
+ DRAG_ENTER_RESPONSE = res;
+
+ allowDrop = res && (res.over || res.before || res.after);
+
+ applyDropEffectCallback(event, data, allowDrop);
+ break;
+
+ case "dragover":
+ if (!node) {
+ tree.debug(
+ "Ignore non-node " +
+ event.type +
+ ": " +
+ event.target.tagName +
+ "." +
+ event.target.className
+ );
+ break;
+ }
+ // The dragover event is fired when an element or text
+ // selection is being dragged over a valid drop target
+ // (every few hundred milliseconds).
+ // tree.debug(
+ // event.type +
+ // ": dropEffect: " +
+ // dataTransfer.dropEffect
+ // );
+ prepareDropEffectCallback(event, data);
+ LAST_HIT_MODE = handleDragOver(event, data);
+
+ // The flag controls the preventDefault() below:
+ allowDrop = !!LAST_HIT_MODE;
+ allowAutoExpand =
+ LAST_HIT_MODE === "over" || LAST_HIT_MODE === false;
+
+ if (
+ allowAutoExpand &&
+ !node.expanded &&
+ node.hasChildren() !== false
+ ) {
+ if (!DRAG_OVER_STAMP) {
+ DRAG_OVER_STAMP = Date.now();
+ } else if (
+ dndOpts.autoExpandMS &&
+ Date.now() - DRAG_OVER_STAMP > dndOpts.autoExpandMS &&
+ !node.isLoading() &&
+ (!dndOpts.dragExpand ||
+ dndOpts.dragExpand(node, data) !== false)
+ ) {
+ node.setExpanded();
+ }
+ } else {
+ DRAG_OVER_STAMP = null;
+ }
+ break;
+
+ case "dragleave":
+ // NOTE: dragleave is fired AFTER the dragenter event of the
+ // FOLLOWING element.
+ if (!node) {
+ tree.debug(
+ "Ignore non-node " +
+ event.type +
+ ": " +
+ event.target.tagName +
+ "." +
+ event.target.className
+ );
+ break;
+ }
+ if (!$(node.span).hasClass(classDropOver)) {
+ node.debug("Ignore dragleave (multi).");
+ break;
+ }
+ $(node.span).removeClass(
+ classDropOver +
+ " " +
+ classDropAccept +
+ " " +
+ classDropReject
+ );
+ node.scheduleAction("cancel");
+ dndOpts.dragLeave(node, data);
+ $dropMarker.hide();
+ break;
+
+ case "drop":
+ // Data is only readable in the (dragstart and) drop event:
+
+ if ($.inArray(nodeMimeType, dataTransfer.types) >= 0) {
+ nodeData = dataTransfer.getData(nodeMimeType);
+ tree.info(
+ event.type +
+ ": getData('application/x-fancytree-node'): '" +
+ nodeData +
+ "'"
+ );
+ }
+ if (!nodeData) {
+ // 1. Source is not a Fancytree node, or
+ // 2. If the FT mime type was set, but returns '', this
+ // is probably IE 11 (which only supports 'text')
+ nodeData = dataTransfer.getData("text");
+ tree.info(
+ event.type + ": getData('text'): '" + nodeData + "'"
+ );
+ }
+ if (nodeData) {
+ try {
+ // 'text' type may contain JSON if IE is involved
+ // and setTextTypeJson option was set
+ json = JSON.parse(nodeData);
+ if (json.title !== undefined) {
+ data.otherNodeData = json;
+ }
+ } catch (ex) {
+ // assume 'text' type contains plain text, so `otherNodeData`
+ // should not be set
+ }
+ }
+ tree.debug(
+ event.type +
+ ": nodeData: '" +
+ nodeData +
+ "', otherNodeData: ",
+ data.otherNodeData
+ );
+
+ $(node.span).removeClass(
+ classDropOver +
+ " " +
+ classDropAccept +
+ " " +
+ classDropReject
+ );
+
+ // Let user implement the actual drop operation
+ data.hitMode = LAST_HIT_MODE;
+ prepareDropEffectCallback(event, data, !LAST_HIT_MODE);
+ data.isCancelled = !LAST_HIT_MODE;
+
+ var orgSourceElem = SOURCE_NODE && SOURCE_NODE.span,
+ orgSourceTree = SOURCE_NODE && SOURCE_NODE.tree;
+
+ dndOpts.dragDrop(node, data);
+ // applyDropEffectCallback(event, data);
+
+ // Prevent browser's default drop handling, i.e. open as link, ...
+ event.preventDefault();
+
+ if (orgSourceElem && !document.body.contains(orgSourceElem)) {
+ // The drop handler removed the original drag source from
+ // the DOM, so the dragend event will probaly not fire.
+ if (orgSourceTree === tree) {
+ tree.debug(
+ "Drop handler removed source element: generating dragEnd."
+ );
+ dndOpts.dragEnd(SOURCE_NODE, data);
+ } else {
+ tree.warn(
+ "Drop handler removed source element: dragend event may be lost."
+ );
+ }
+ }
+
+ _clearGlobals();
+
+ break;
+ }
+ // Dnd API madness: we must PREVENT default handling to enable dropping
+ if (allowDrop) {
+ event.preventDefault();
+ return false;
+ }
+ }
+
+ /** [ext-dnd5] Return a Fancytree instance, from element, index, event, or jQueryObject.
+ *
+ * @returns {FancytreeNode[]} List of nodes (empty if no drag operation)
+ * @example
+ * $.ui.fancytree.getDragNodeList();
+ *
+ * @alias Fancytree_Static#getDragNodeList
+ * @requires jquery.fancytree.dnd5.js
+ * @since 2.31
+ */
+ $.ui.fancytree.getDragNodeList = function () {
+ return SOURCE_NODE_LIST || [];
+ };
+
+ /** [ext-dnd5] Return the FancytreeNode that is currently being dragged.
+ *
+ * If multiple nodes are dragged, only the first is returned.
+ *
+ * @returns {FancytreeNode | null} dragged nodes or null if no drag operation
+ * @example
+ * $.ui.fancytree.getDragNode();
+ *
+ * @alias Fancytree_Static#getDragNode
+ * @requires jquery.fancytree.dnd5.js
+ * @since 2.31
+ */
+ $.ui.fancytree.getDragNode = function () {
+ return SOURCE_NODE;
+ };
+
+ /******************************************************************************
+ *
+ */
+
+ $.ui.fancytree.registerExtension({
+ name: "dnd5",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ autoExpandMS: 1500, // Expand nodes after n milliseconds of hovering
+ dropMarkerInsertOffsetX: -16, // Additional offset for drop-marker with hitMode = "before"/"after"
+ dropMarkerOffsetX: -24, // Absolute position offset for .fancytree-drop-marker relatively to ..fancytree-title (icon/img near a node accepting drop)
+ // #1021 `document.body` is not available yet
+ dropMarkerParent: "body", // Root Container used for drop marker (could be a shadow root)
+ multiSource: false, // true: Drag multiple (i.e. selected) nodes. Also a callback() is allowed
+ effectAllowed: "all", // Restrict the possible cursor shapes and modifier operations (can also be set in the dragStart event)
+ // dropEffect: "auto", // 'copy'|'link'|'move'|'auto'(calculate from `effectAllowed`+modifier keys) or callback(node, data) that returns such string.
+ dropEffectDefault: "move", // Default dropEffect ('copy', 'link', or 'move') when no modifier is pressed (overide in dragDrag, dragOver).
+ preventForeignNodes: false, // Prevent dropping nodes from different Fancytrees
+ preventLazyParents: true, // Prevent dropping items on unloaded lazy Fancytree nodes
+ preventNonNodes: false, // Prevent dropping items other than Fancytree nodes
+ preventRecursion: true, // Prevent dropping nodes on own descendants
+ preventSameParent: false, // Prevent dropping nodes under same direct parent
+ preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
+ scroll: true, // Enable auto-scrolling while dragging
+ scrollSensitivity: 20, // Active top/bottom margin in pixel
+ scrollSpeed: 5, // Pixel per event
+ setTextTypeJson: false, // Allow dragging of nodes to different IE windows
+ sourceCopyHook: null, // Optional callback passed to `toDict` on dragStart @since 2.38
+ // Events (drag support)
+ dragStart: null, // Callback(sourceNode, data), return true, to enable dnd drag
+ dragDrag: $.noop, // Callback(sourceNode, data)
+ dragEnd: $.noop, // Callback(sourceNode, data)
+ // Events (drop support)
+ dragEnter: null, // Callback(targetNode, data), return true, to enable dnd drop
+ dragOver: $.noop, // Callback(targetNode, data)
+ dragExpand: $.noop, // Callback(targetNode, data), return false to prevent autoExpand
+ dragDrop: $.noop, // Callback(targetNode, data)
+ dragLeave: $.noop, // Callback(targetNode, data)
+ },
+
+ treeInit: function (ctx) {
+ var $temp,
+ tree = ctx.tree,
+ opts = ctx.options,
+ glyph = opts.glyph || null,
+ dndOpts = opts.dnd5;
+
+ if ($.inArray("dnd", opts.extensions) >= 0) {
+ $.error("Extensions 'dnd' and 'dnd5' are mutually exclusive.");
+ }
+ if (dndOpts.dragStop) {
+ $.error(
+ "dragStop is not used by ext-dnd5. Use dragEnd instead."
+ );
+ }
+ if (dndOpts.preventRecursiveMoves != null) {
+ $.error(
+ "preventRecursiveMoves was renamed to preventRecursion."
+ );
+ }
+
+ // Implement `opts.createNode` event to add the 'draggable' attribute
+ // #680: this must happen before calling super.treeInit()
+ if (dndOpts.dragStart) {
+ FT.overrideMethod(
+ ctx.options,
+ "createNode",
+ function (event, data) {
+ // Default processing if any
+ this._super.apply(this, arguments);
+ if (data.node.span) {
+ data.node.span.draggable = true;
+ } else {
+ data.node.warn(
+ "Cannot add `draggable`: no span tag"
+ );
+ }
+ }
+ );
+ }
+ this._superApply(arguments);
+
+ this.$container.addClass("fancytree-ext-dnd5");
+
+ // Store the current scroll parent, which may be the tree
+ // container, any enclosing div, or the document.
+ // #761: scrollParent() always needs a container child
+ $temp = $("<span>").appendTo(this.$container);
+ this.$scrollParent = $temp.scrollParent();
+ $temp.remove();
+
+ $dropMarker = $("#fancytree-drop-marker");
+ if (!$dropMarker.length) {
+ $dropMarker = $("<div id='fancytree-drop-marker'></div>")
+ .hide()
+ .css({
+ "z-index": 1000,
+ // Drop marker should not steal dragenter/dragover events:
+ "pointer-events": "none",
+ })
+ .prependTo(dndOpts.dropMarkerParent);
+ if (glyph) {
+ FT.setSpanIcon(
+ $dropMarker[0],
+ glyph.map._addClass,
+ glyph.map.dropMarker
+ );
+ }
+ }
+ $dropMarker.toggleClass("fancytree-rtl", !!opts.rtl);
+
+ // Enable drag support if dragStart() is specified:
+ if (dndOpts.dragStart) {
+ // Bind drag event handlers
+ tree.$container.on(
+ "dragstart drag dragend",
+ onDragEvent.bind(tree)
+ );
+ }
+ // Enable drop support if dragEnter() is specified:
+ if (dndOpts.dragEnter) {
+ // Bind drop event handlers
+ tree.$container.on(
+ "dragenter dragover dragleave drop",
+ onDropEvent.bind(tree)
+ );
+ }
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.edit.js' *//*!
+ * jquery.fancytree.edit.js
+ *
+ * Make node titles editable.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ var isMac = /Mac/.test(navigator.platform),
+ escapeHtml = $.ui.fancytree.escapeHtml,
+ trim = $.ui.fancytree.trim,
+ unescapeHtml = $.ui.fancytree.unescapeHtml;
+
+ /**
+ * [ext-edit] Start inline editing of current node title.
+ *
+ * @alias FancytreeNode#editStart
+ * @requires Fancytree
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.editStart = function () {
+ var $input,
+ node = this,
+ tree = this.tree,
+ local = tree.ext.edit,
+ instOpts = tree.options.edit,
+ $title = $(".fancytree-title", node.span),
+ eventData = {
+ node: node,
+ tree: tree,
+ options: tree.options,
+ isNew: $(node[tree.statusClassPropName]).hasClass(
+ "fancytree-edit-new"
+ ),
+ orgTitle: node.title,
+ input: null,
+ dirty: false,
+ };
+
+ // beforeEdit may want to modify the title before editing
+ if (
+ instOpts.beforeEdit.call(
+ node,
+ { type: "beforeEdit" },
+ eventData
+ ) === false
+ ) {
+ return false;
+ }
+ $.ui.fancytree.assert(!local.currentNode, "recursive edit");
+ local.currentNode = this;
+ local.eventData = eventData;
+
+ // Disable standard Fancytree mouse- and key handling
+ tree.widget._unbind();
+
+ local.lastDraggableAttrValue = node.span.draggable;
+ if (local.lastDraggableAttrValue) {
+ node.span.draggable = false;
+ }
+
+ // #116: ext-dnd prevents the blur event, so we have to catch outer clicks
+ $(document).on("mousedown.fancytree-edit", function (event) {
+ if (!$(event.target).hasClass("fancytree-edit-input")) {
+ node.editEnd(true, event);
+ }
+ });
+
+ // Replace node with <input>
+ $input = $("<input />", {
+ class: "fancytree-edit-input",
+ type: "text",
+ value: tree.options.escapeTitles
+ ? eventData.orgTitle
+ : unescapeHtml(eventData.orgTitle),
+ });
+ local.eventData.input = $input;
+ if (instOpts.adjustWidthOfs != null) {
+ $input.width($title.width() + instOpts.adjustWidthOfs);
+ }
+ if (instOpts.inputCss != null) {
+ $input.css(instOpts.inputCss);
+ }
+
+ $title.html($input);
+
+ // Focus <input> and bind keyboard handler
+ $input
+ .focus()
+ .change(function (event) {
+ $input.addClass("fancytree-edit-dirty");
+ })
+ .on("keydown", function (event) {
+ switch (event.which) {
+ case $.ui.keyCode.ESCAPE:
+ node.editEnd(false, event);
+ break;
+ case $.ui.keyCode.ENTER:
+ node.editEnd(true, event);
+ return false; // so we don't start editmode on Mac
+ }
+ event.stopPropagation();
+ })
+ .blur(function (event) {
+ return node.editEnd(true, event);
+ });
+
+ instOpts.edit.call(node, { type: "edit" }, eventData);
+ };
+
+ /**
+ * [ext-edit] Stop inline editing.
+ * @param {Boolean} [applyChanges=false] false: cancel edit, true: save (if modified)
+ * @alias FancytreeNode#editEnd
+ * @requires jquery.fancytree.edit.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.editEnd = function (
+ applyChanges,
+ _event
+ ) {
+ var newVal,
+ node = this,
+ tree = this.tree,
+ local = tree.ext.edit,
+ eventData = local.eventData,
+ instOpts = tree.options.edit,
+ $title = $(".fancytree-title", node.span),
+ $input = $title.find("input.fancytree-edit-input");
+
+ if (instOpts.trim) {
+ $input.val(trim($input.val()));
+ }
+ newVal = $input.val();
+
+ eventData.dirty = newVal !== node.title;
+ eventData.originalEvent = _event;
+
+ // Find out, if saving is required
+ if (applyChanges === false) {
+ // If true/false was passed, honor this (except in rename mode, if unchanged)
+ eventData.save = false;
+ } else if (eventData.isNew) {
+ // In create mode, we save everything, except for empty text
+ eventData.save = newVal !== "";
+ } else {
+ // In rename mode, we save everyting, except for empty or unchanged text
+ eventData.save = eventData.dirty && newVal !== "";
+ }
+ // Allow to break (keep editor open), modify input, or re-define data.save
+ if (
+ instOpts.beforeClose.call(
+ node,
+ { type: "beforeClose" },
+ eventData
+ ) === false
+ ) {
+ return false;
+ }
+ if (
+ eventData.save &&
+ instOpts.save.call(node, { type: "save" }, eventData) === false
+ ) {
+ return false;
+ }
+ $input.removeClass("fancytree-edit-dirty").off();
+ // Unbind outer-click handler
+ $(document).off(".fancytree-edit");
+
+ if (eventData.save) {
+ // # 171: escape user input (not required if global escaping is on)
+ node.setTitle(
+ tree.options.escapeTitles ? newVal : escapeHtml(newVal)
+ );
+ node.setFocus();
+ } else {
+ if (eventData.isNew) {
+ node.remove();
+ node = eventData.node = null;
+ local.relatedNode.setFocus();
+ } else {
+ node.renderTitle();
+ node.setFocus();
+ }
+ }
+ local.eventData = null;
+ local.currentNode = null;
+ local.relatedNode = null;
+ // Re-enable mouse and keyboard handling
+ tree.widget._bind();
+
+ if (node && local.lastDraggableAttrValue) {
+ node.span.draggable = true;
+ }
+
+ // Set keyboard focus, even if setFocus() claims 'nothing to do'
+ tree.$container.get(0).focus({ preventScroll: true });
+ eventData.input = null;
+ instOpts.close.call(node, { type: "close" }, eventData);
+ return true;
+ };
+
+ /**
+ * [ext-edit] Create a new child or sibling node and start edit mode.
+ *
+ * @param {String} [mode='child'] 'before', 'after', or 'child'
+ * @param {Object} [init] NodeData (or simple title string)
+ * @alias FancytreeNode#editCreateNode
+ * @requires jquery.fancytree.edit.js
+ * @since 2.4
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode = function (
+ mode,
+ init
+ ) {
+ var newNode,
+ tree = this.tree,
+ self = this;
+
+ mode = mode || "child";
+ if (init == null) {
+ init = { title: "" };
+ } else if (typeof init === "string") {
+ init = { title: init };
+ } else {
+ $.ui.fancytree.assert($.isPlainObject(init));
+ }
+ // Make sure node is expanded (and loaded) in 'child' mode
+ if (
+ mode === "child" &&
+ !this.isExpanded() &&
+ this.hasChildren() !== false
+ ) {
+ this.setExpanded().done(function () {
+ self.editCreateNode(mode, init);
+ });
+ return;
+ }
+ newNode = this.addNode(init, mode);
+
+ // #644: Don't filter new nodes.
+ newNode.match = true;
+ $(newNode[tree.statusClassPropName])
+ .removeClass("fancytree-hide")
+ .addClass("fancytree-match");
+
+ newNode.makeVisible(/*{noAnimation: true}*/).done(function () {
+ $(newNode[tree.statusClassPropName]).addClass("fancytree-edit-new");
+ self.tree.ext.edit.relatedNode = self;
+ newNode.editStart();
+ });
+ };
+
+ /**
+ * [ext-edit] Check if any node in this tree in edit mode.
+ *
+ * @returns {FancytreeNode | null}
+ * @alias Fancytree#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.isEditing = function () {
+ return this.ext.edit ? this.ext.edit.currentNode : null;
+ };
+
+ /**
+ * [ext-edit] Check if this node is in edit mode.
+ * @returns {Boolean} true if node is currently beeing edited
+ * @alias FancytreeNode#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.isEditing = function () {
+ return this.tree.ext.edit
+ ? this.tree.ext.edit.currentNode === this
+ : false;
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "edit",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ adjustWidthOfs: 4, // null: don't adjust input size to content
+ allowEmpty: false, // Prevent empty input
+ inputCss: { minWidth: "3em" },
+ // triggerCancel: ["esc", "tab", "click"],
+ triggerStart: ["f2", "mac+enter", "shift+click"],
+ trim: true, // Trim whitespace before save
+ // Events:
+ beforeClose: $.noop, // Return false to prevent cancel/save (data.input is available)
+ beforeEdit: $.noop, // Return false to prevent edit mode
+ close: $.noop, // Editor was removed
+ edit: $.noop, // Editor was opened (available as data.input)
+ // keypress: $.noop, // Not yet implemented
+ save: $.noop, // Save data.input.val() or return false to keep editor open
+ },
+ // Local attributes
+ currentNode: null,
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree;
+
+ this._superApply(arguments);
+
+ this.$container
+ .addClass("fancytree-ext-edit")
+ .on("fancytreebeforeupdateviewport", function (event, data) {
+ var editNode = tree.isEditing();
+ // When scrolling, the TR may be re-used by another node, so the
+ // active cell marker an
+ if (editNode) {
+ editNode.info("Cancel edit due to scroll event.");
+ editNode.editEnd(false, event);
+ }
+ });
+ },
+ nodeClick: function (ctx) {
+ var eventStr = $.ui.fancytree.eventToString(ctx.originalEvent),
+ triggerStart = ctx.options.edit.triggerStart;
+
+ if (
+ eventStr === "shift+click" &&
+ $.inArray("shift+click", triggerStart) >= 0
+ ) {
+ if (ctx.originalEvent.shiftKey) {
+ ctx.node.editStart();
+ return false;
+ }
+ }
+ if (
+ eventStr === "click" &&
+ $.inArray("clickActive", triggerStart) >= 0
+ ) {
+ // Only when click was inside title text (not aynwhere else in the row)
+ if (
+ ctx.node.isActive() &&
+ !ctx.node.isEditing() &&
+ $(ctx.originalEvent.target).hasClass("fancytree-title")
+ ) {
+ ctx.node.editStart();
+ return false;
+ }
+ }
+ return this._superApply(arguments);
+ },
+ nodeDblclick: function (ctx) {
+ if ($.inArray("dblclick", ctx.options.edit.triggerStart) >= 0) {
+ ctx.node.editStart();
+ return false;
+ }
+ return this._superApply(arguments);
+ },
+ nodeKeydown: function (ctx) {
+ switch (ctx.originalEvent.which) {
+ case 113: // [F2]
+ if ($.inArray("f2", ctx.options.edit.triggerStart) >= 0) {
+ ctx.node.editStart();
+ return false;
+ }
+ break;
+ case $.ui.keyCode.ENTER:
+ if (
+ $.inArray("mac+enter", ctx.options.edit.triggerStart) >=
+ 0 &&
+ isMac
+ ) {
+ ctx.node.editStart();
+ return false;
+ }
+ break;
+ }
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.filter.js' *//*!
+ * jquery.fancytree.filter.js
+ *
+ * Remove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ var KeyNoData = "__not_found__",
+ escapeHtml = $.ui.fancytree.escapeHtml,
+ exoticStartChar = "\uFFF7",
+ exoticEndChar = "\uFFF8";
+ function _escapeRegex(str) {
+ return (str + "").replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
+ }
+
+ function extractHtmlText(s) {
+ if (s.indexOf(">") >= 0) {
+ return $("<div/>").html(s).text();
+ }
+ return s;
+ }
+
+ /**
+ * @description Marks the matching charecters of `text` either by `mark` or
+ * by exotic*Chars (if `escapeTitles` is `true`) based on `regexMatchArray`
+ * which is an array of matching groups.
+ * @param {string} text
+ * @param {RegExpMatchArray} regexMatchArray
+ */
+ function _markFuzzyMatchedChars(text, regexMatchArray, escapeTitles) {
+ // It is extremely infuriating that we can not use `let` or `const` or arrow functions.
+ // Damn you IE!!!
+ var matchingIndices = [];
+ // get the indices of matched characters (Iterate through `RegExpMatchArray`)
+ for (
+ var _matchingArrIdx = 1;
+ _matchingArrIdx < regexMatchArray.length;
+ _matchingArrIdx++
+ ) {
+ var _mIdx =
+ // get matching char index by cumulatively adding
+ // the matched group length
+ regexMatchArray[_matchingArrIdx].length +
+ (_matchingArrIdx === 1 ? 0 : 1) +
+ (matchingIndices[matchingIndices.length - 1] || 0);
+ matchingIndices.push(_mIdx);
+ }
+ // Map each `text` char to its position and store in `textPoses`.
+ var textPoses = text.split("");
+ if (escapeTitles) {
+ // If escaping the title, then wrap the matchng char within exotic chars
+ matchingIndices.forEach(function (v) {
+ textPoses[v] = exoticStartChar + textPoses[v] + exoticEndChar;
+ });
+ } else {
+ // Otherwise, Wrap the matching chars within `mark`.
+ matchingIndices.forEach(function (v) {
+ textPoses[v] = "<mark>" + textPoses[v] + "</mark>";
+ });
+ }
+ // Join back the modified `textPoses` to create final highlight markup.
+ return textPoses.join("");
+ }
+ $.ui.fancytree._FancytreeClass.prototype._applyFilterImpl = function (
+ filter,
+ branchMode,
+ _opts
+ ) {
+ var match,
+ statusNode,
+ re,
+ reHighlight,
+ reExoticStartChar,
+ reExoticEndChar,
+ temp,
+ prevEnableUpdate,
+ count = 0,
+ treeOpts = this.options,
+ escapeTitles = treeOpts.escapeTitles,
+ prevAutoCollapse = treeOpts.autoCollapse,
+ opts = $.extend({}, treeOpts.filter, _opts),
+ hideMode = opts.mode === "hide",
+ leavesOnly = !!opts.leavesOnly && !branchMode;
+
+ // Default to 'match title substring (not case sensitive)'
+ if (typeof filter === "string") {
+ if (filter === "") {
+ this.warn(
+ "Fancytree passing an empty string as a filter is handled as clearFilter()."
+ );
+ this.clearFilter();
+ return;
+ }
+ if (opts.fuzzy) {
+ // See https://codereview.stackexchange.com/questions/23899/faster-javascript-fuzzy-string-matching-function/23905#23905
+ // and http://www.quora.com/How-is-the-fuzzy-search-algorithm-in-Sublime-Text-designed
+ // and http://www.dustindiaz.com/autocomplete-fuzzy-matching
+ match = filter
+ .split("")
+ // Escaping the `filter` will not work because,
+ // it gets further split into individual characters. So,
+ // escape each character after splitting
+ .map(_escapeRegex)
+ .reduce(function (a, b) {
+ // create capture groups for parts that comes before
+ // the character
+ return a + "([^" + b + "]*)" + b;
+ }, "");
+ } else {
+ match = _escapeRegex(filter); // make sure a '.' is treated literally
+ }
+ re = new RegExp(match, "i");
+ reHighlight = new RegExp(_escapeRegex(filter), "gi");
+ if (escapeTitles) {
+ reExoticStartChar = new RegExp(
+ _escapeRegex(exoticStartChar),
+ "g"
+ );
+ reExoticEndChar = new RegExp(_escapeRegex(exoticEndChar), "g");
+ }
+ filter = function (node) {
+ if (!node.title) {
+ return false;
+ }
+ var text = escapeTitles
+ ? node.title
+ : extractHtmlText(node.title),
+ // `.match` instead of `.test` to get the capture groups
+ res = text.match(re);
+ if (res && opts.highlight) {
+ if (escapeTitles) {
+ if (opts.fuzzy) {
+ temp = _markFuzzyMatchedChars(
+ text,
+ res,
+ escapeTitles
+ );
+ } else {
+ // #740: we must not apply the marks to escaped entity names, e.g. `&quot;`
+ // Use some exotic characters to mark matches:
+ temp = text.replace(reHighlight, function (s) {
+ return exoticStartChar + s + exoticEndChar;
+ });
+ }
+ // now we can escape the title...
+ node.titleWithHighlight = escapeHtml(temp)
+ // ... and finally insert the desired `<mark>` tags
+ .replace(reExoticStartChar, "<mark>")
+ .replace(reExoticEndChar, "</mark>");
+ } else {
+ if (opts.fuzzy) {
+ node.titleWithHighlight = _markFuzzyMatchedChars(
+ text,
+ res
+ );
+ } else {
+ node.titleWithHighlight = text.replace(
+ reHighlight,
+ function (s) {
+ return "<mark>" + s + "</mark>";
+ }
+ );
+ }
+ }
+ // node.debug("filter", escapeTitles, text, node.titleWithHighlight);
+ }
+ return !!res;
+ };
+ }
+
+ this.enableFilter = true;
+ this.lastFilterArgs = arguments;
+
+ prevEnableUpdate = this.enableUpdate(false);
+
+ this.$div.addClass("fancytree-ext-filter");
+ if (hideMode) {
+ this.$div.addClass("fancytree-ext-filter-hide");
+ } else {
+ this.$div.addClass("fancytree-ext-filter-dimm");
+ }
+ this.$div.toggleClass(
+ "fancytree-ext-filter-hide-expanders",
+ !!opts.hideExpanders
+ );
+ // Reset current filter
+ this.rootNode.subMatchCount = 0;
+ this.visit(function (node) {
+ delete node.match;
+ delete node.titleWithHighlight;
+ node.subMatchCount = 0;
+ });
+ statusNode = this.getRootNode()._findDirectChild(KeyNoData);
+ if (statusNode) {
+ statusNode.remove();
+ }
+
+ // Adjust node.hide, .match, and .subMatchCount properties
+ treeOpts.autoCollapse = false; // #528
+
+ this.visit(function (node) {
+ if (leavesOnly && node.children != null) {
+ return;
+ }
+ var res = filter(node),
+ matchedByBranch = false;
+
+ if (res === "skip") {
+ node.visit(function (c) {
+ c.match = false;
+ }, true);
+ return "skip";
+ }
+ if (!res && (branchMode || res === "branch") && node.parent.match) {
+ res = true;
+ matchedByBranch = true;
+ }
+ if (res) {
+ count++;
+ node.match = true;
+ node.visitParents(function (p) {
+ if (p !== node) {
+ p.subMatchCount += 1;
+ }
+ // Expand match (unless this is no real match, but only a node in a matched branch)
+ if (opts.autoExpand && !matchedByBranch && !p.expanded) {
+ p.setExpanded(true, {
+ noAnimation: true,
+ noEvents: true,
+ scrollIntoView: false,
+ });
+ p._filterAutoExpanded = true;
+ }
+ }, true);
+ }
+ });
+ treeOpts.autoCollapse = prevAutoCollapse;
+
+ if (count === 0 && opts.nodata && hideMode) {
+ statusNode = opts.nodata;
+ if (typeof statusNode === "function") {
+ statusNode = statusNode();
+ }
+ if (statusNode === true) {
+ statusNode = {};
+ } else if (typeof statusNode === "string") {
+ statusNode = { title: statusNode };
+ }
+ statusNode = $.extend(
+ {
+ statusNodeType: "nodata",
+ key: KeyNoData,
+ title: this.options.strings.noData,
+ },
+ statusNode
+ );
+
+ this.getRootNode().addNode(statusNode).match = true;
+ }
+ // Redraw whole tree
+ this._callHook("treeStructureChanged", this, "applyFilter");
+ // this.render();
+ this.enableUpdate(prevEnableUpdate);
+ return count;
+ };
+
+ /**
+ * [ext-filter] Dimm or hide nodes.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false, leavesOnly: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterNodes
+ * @requires jquery.fancytree.filter.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.filterNodes = function (
+ filter,
+ opts
+ ) {
+ if (typeof opts === "boolean") {
+ opts = { leavesOnly: opts };
+ this.warn(
+ "Fancytree.filterNodes() leavesOnly option is deprecated since 2.9.0 / 2015-04-19. Use opts.leavesOnly instead."
+ );
+ }
+ return this._applyFilterImpl(filter, false, opts);
+ };
+
+ /**
+ * [ext-filter] Dimm or hide whole branches.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterBranches
+ * @requires jquery.fancytree.filter.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.filterBranches = function (
+ filter,
+ opts
+ ) {
+ return this._applyFilterImpl(filter, true, opts);
+ };
+
+ /**
+ * [ext-filter] Re-apply current filter.
+ *
+ * @returns {integer} count
+ * @alias Fancytree#updateFilter
+ * @requires jquery.fancytree.filter.js
+ * @since 2.38
+ */
+ $.ui.fancytree._FancytreeClass.prototype.updateFilter = function () {
+ if (
+ this.enableFilter &&
+ this.lastFilterArgs &&
+ this.options.filter.autoApply
+ ) {
+ this._applyFilterImpl.apply(this, this.lastFilterArgs);
+ } else {
+ this.warn("updateFilter(): no filter active.");
+ }
+ };
+
+ /**
+ * [ext-filter] Reset the filter.
+ *
+ * @alias Fancytree#clearFilter
+ * @requires jquery.fancytree.filter.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.clearFilter = function () {
+ var $title,
+ statusNode = this.getRootNode()._findDirectChild(KeyNoData),
+ escapeTitles = this.options.escapeTitles,
+ enhanceTitle = this.options.enhanceTitle,
+ prevEnableUpdate = this.enableUpdate(false);
+
+ if (statusNode) {
+ statusNode.remove();
+ }
+ // we also counted root node's subMatchCount
+ delete this.rootNode.match;
+ delete this.rootNode.subMatchCount;
+
+ this.visit(function (node) {
+ if (node.match && node.span) {
+ // #491, #601
+ $title = $(node.span).find(">span.fancytree-title");
+ if (escapeTitles) {
+ $title.text(node.title);
+ } else {
+ $title.html(node.title);
+ }
+ if (enhanceTitle) {
+ enhanceTitle(
+ { type: "enhanceTitle" },
+ { node: node, $title: $title }
+ );
+ }
+ }
+ delete node.match;
+ delete node.subMatchCount;
+ delete node.titleWithHighlight;
+ if (node.$subMatchBadge) {
+ node.$subMatchBadge.remove();
+ delete node.$subMatchBadge;
+ }
+ if (node._filterAutoExpanded && node.expanded) {
+ node.setExpanded(false, {
+ noAnimation: true,
+ noEvents: true,
+ scrollIntoView: false,
+ });
+ }
+ delete node._filterAutoExpanded;
+ });
+ this.enableFilter = false;
+ this.lastFilterArgs = null;
+ this.$div.removeClass(
+ "fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide"
+ );
+ this._callHook("treeStructureChanged", this, "clearFilter");
+ // this.render();
+ this.enableUpdate(prevEnableUpdate);
+ };
+
+ /**
+ * [ext-filter] Return true if a filter is currently applied.
+ *
+ * @returns {Boolean}
+ * @alias Fancytree#isFilterActive
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+ $.ui.fancytree._FancytreeClass.prototype.isFilterActive = function () {
+ return !!this.enableFilter;
+ };
+
+ /**
+ * [ext-filter] Return true if this node is matched by current filter (or no filter is active).
+ *
+ * @returns {Boolean}
+ * @alias FancytreeNode#isMatched
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.isMatched = function () {
+ return !(this.tree.enableFilter && !this.match);
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "filter",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ autoApply: true, // Re-apply last filter if lazy data is loaded
+ autoExpand: false, // Expand all branches that contain matches while filtered
+ counter: true, // Show a badge with number of matching child nodes near parent icons
+ fuzzy: false, // Match single characters in order, e.g. 'fb' will match 'FooBar'
+ hideExpandedCounter: true, // Hide counter badge if parent is expanded
+ hideExpanders: false, // Hide expanders if all child nodes are hidden by filter
+ highlight: true, // Highlight matches by wrapping inside <mark> tags
+ leavesOnly: false, // Match end nodes only
+ nodata: true, // Display a 'no data' status node if result is empty
+ mode: "dimm", // Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
+ },
+ nodeLoadChildren: function (ctx, source) {
+ var tree = ctx.tree;
+
+ return this._superApply(arguments).done(function () {
+ if (
+ tree.enableFilter &&
+ tree.lastFilterArgs &&
+ ctx.options.filter.autoApply
+ ) {
+ tree._applyFilterImpl.apply(tree, tree.lastFilterArgs);
+ }
+ });
+ },
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var node = ctx.node;
+
+ delete node._filterAutoExpanded;
+ // Make sure counter badge is displayed again, when node is beeing collapsed
+ if (
+ !flag &&
+ ctx.options.filter.hideExpandedCounter &&
+ node.$subMatchBadge
+ ) {
+ node.$subMatchBadge.show();
+ }
+ return this._superApply(arguments);
+ },
+ nodeRenderStatus: function (ctx) {
+ // Set classes for current status
+ var res,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options.filter,
+ $title = $(node.span).find("span.fancytree-title"),
+ $span = $(node[tree.statusClassPropName]),
+ enhanceTitle = ctx.options.enhanceTitle,
+ escapeTitles = ctx.options.escapeTitles;
+
+ res = this._super(ctx);
+ // nothing to do, if node was not yet rendered
+ if (!$span.length || !tree.enableFilter) {
+ return res;
+ }
+ $span
+ .toggleClass("fancytree-match", !!node.match)
+ .toggleClass("fancytree-submatch", !!node.subMatchCount)
+ .toggleClass(
+ "fancytree-hide",
+ !(node.match || node.subMatchCount)
+ );
+ // Add/update counter badge
+ if (
+ opts.counter &&
+ node.subMatchCount &&
+ (!node.isExpanded() || !opts.hideExpandedCounter)
+ ) {
+ if (!node.$subMatchBadge) {
+ node.$subMatchBadge = $(
+ "<span class='fancytree-childcounter'/>"
+ );
+ $(
+ "span.fancytree-icon, span.fancytree-custom-icon",
+ node.span
+ ).append(node.$subMatchBadge);
+ }
+ node.$subMatchBadge.show().text(node.subMatchCount);
+ } else if (node.$subMatchBadge) {
+ node.$subMatchBadge.hide();
+ }
+ // node.debug("nodeRenderStatus", node.titleWithHighlight, node.title)
+ // #601: also check for $title.length, because we don't need to render
+ // if node.span is null (i.e. not rendered)
+ if (node.span && (!node.isEditing || !node.isEditing.call(node))) {
+ if (node.titleWithHighlight) {
+ $title.html(node.titleWithHighlight);
+ } else if (escapeTitles) {
+ $title.text(node.title);
+ } else {
+ $title.html(node.title);
+ }
+ if (enhanceTitle) {
+ enhanceTitle(
+ { type: "enhanceTitle" },
+ { node: node, $title: $title }
+ );
+ }
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.glyph.js' *//*!
+ * jquery.fancytree.glyph.js
+ *
+ * Use glyph-fonts, ligature-fonts, or SVG icons instead of icon sprites.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+
+ var FT = $.ui.fancytree,
+ PRESETS = {
+ awesome3: {
+ // Outdated!
+ _addClass: "",
+ checkbox: "icon-check-empty",
+ checkboxSelected: "icon-check",
+ checkboxUnknown: "icon-check icon-muted",
+ dragHelper: "icon-caret-right",
+ dropMarker: "icon-caret-right",
+ error: "icon-exclamation-sign",
+ expanderClosed: "icon-caret-right",
+ expanderLazy: "icon-angle-right",
+ expanderOpen: "icon-caret-down",
+ loading: "icon-refresh icon-spin",
+ nodata: "icon-meh",
+ noExpander: "",
+ radio: "icon-circle-blank",
+ radioSelected: "icon-circle",
+ // radioUnknown: "icon-circle icon-muted",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "icon-file-alt",
+ docOpen: "icon-file-alt",
+ folder: "icon-folder-close-alt",
+ folderOpen: "icon-folder-open-alt",
+ },
+ awesome4: {
+ _addClass: "fa",
+ checkbox: "fa-square-o",
+ checkboxSelected: "fa-check-square-o",
+ checkboxUnknown: "fa-square fancytree-helper-indeterminate-cb",
+ dragHelper: "fa-arrow-right",
+ dropMarker: "fa-long-arrow-right",
+ error: "fa-warning",
+ expanderClosed: "fa-caret-right",
+ expanderLazy: "fa-angle-right",
+ expanderOpen: "fa-caret-down",
+ // We may prevent wobbling rotations on FF by creating a separate sub element:
+ loading: { html: "<span class='fa fa-spinner fa-pulse' />" },
+ nodata: "fa-meh-o",
+ noExpander: "",
+ radio: "fa-circle-thin", // "fa-circle-o"
+ radioSelected: "fa-circle",
+ // radioUnknown: "fa-dot-circle-o",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "fa-file-o",
+ docOpen: "fa-file-o",
+ folder: "fa-folder-o",
+ folderOpen: "fa-folder-open-o",
+ },
+ awesome5: {
+ // fontawesome 5 have several different base classes
+ // "far, fas, fal and fab" The rendered svg puts that prefix
+ // in a different location so we have to keep them separate here
+ _addClass: "",
+ checkbox: "far fa-square",
+ checkboxSelected: "far fa-check-square",
+ // checkboxUnknown: "far fa-window-close",
+ checkboxUnknown:
+ "fas fa-square fancytree-helper-indeterminate-cb",
+ radio: "far fa-circle",
+ radioSelected: "fas fa-circle",
+ radioUnknown: "far fa-dot-circle",
+ dragHelper: "fas fa-arrow-right",
+ dropMarker: "fas fa-long-arrow-alt-right",
+ error: "fas fa-exclamation-triangle",
+ expanderClosed: "fas fa-caret-right",
+ expanderLazy: "fas fa-angle-right",
+ expanderOpen: "fas fa-caret-down",
+ loading: "fas fa-spinner fa-pulse",
+ nodata: "far fa-meh",
+ noExpander: "",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "far fa-file",
+ docOpen: "far fa-file",
+ folder: "far fa-folder",
+ folderOpen: "far fa-folder-open",
+ },
+ bootstrap3: {
+ _addClass: "glyphicon",
+ checkbox: "glyphicon-unchecked",
+ checkboxSelected: "glyphicon-check",
+ checkboxUnknown:
+ "glyphicon-expand fancytree-helper-indeterminate-cb", // "glyphicon-share",
+ dragHelper: "glyphicon-play",
+ dropMarker: "glyphicon-arrow-right",
+ error: "glyphicon-warning-sign",
+ expanderClosed: "glyphicon-menu-right", // glyphicon-plus-sign
+ expanderLazy: "glyphicon-menu-right", // glyphicon-plus-sign
+ expanderOpen: "glyphicon-menu-down", // glyphicon-minus-sign
+ loading: "glyphicon-refresh fancytree-helper-spin",
+ nodata: "glyphicon-info-sign",
+ noExpander: "",
+ radio: "glyphicon-remove-circle", // "glyphicon-unchecked",
+ radioSelected: "glyphicon-ok-circle", // "glyphicon-check",
+ // radioUnknown: "glyphicon-ban-circle",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "glyphicon-file",
+ docOpen: "glyphicon-file",
+ folder: "glyphicon-folder-close",
+ folderOpen: "glyphicon-folder-open",
+ },
+ material: {
+ _addClass: "material-icons",
+ checkbox: { text: "check_box_outline_blank" },
+ checkboxSelected: { text: "check_box" },
+ checkboxUnknown: { text: "indeterminate_check_box" },
+ dragHelper: { text: "play_arrow" },
+ dropMarker: { text: "arrow-forward" },
+ error: { text: "warning" },
+ expanderClosed: { text: "chevron_right" },
+ expanderLazy: { text: "last_page" },
+ expanderOpen: { text: "expand_more" },
+ loading: {
+ text: "autorenew",
+ addClass: "fancytree-helper-spin",
+ },
+ nodata: { text: "info" },
+ noExpander: { text: "" },
+ radio: { text: "radio_button_unchecked" },
+ radioSelected: { text: "radio_button_checked" },
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: { text: "insert_drive_file" },
+ docOpen: { text: "insert_drive_file" },
+ folder: { text: "folder" },
+ folderOpen: { text: "folder_open" },
+ },
+ };
+
+ function setIcon(node, span, baseClass, opts, type) {
+ var map = opts.map,
+ icon = map[type],
+ $span = $(span),
+ $counter = $span.find(".fancytree-childcounter"),
+ setClass = baseClass + " " + (map._addClass || "");
+
+ // #871 Allow a callback
+ if (typeof icon === "function") {
+ icon = icon.call(this, node, span, type);
+ }
+ // node.debug( "setIcon(" + baseClass + ", " + type + "): " + "oldIcon" + " -> " + icon );
+ // #871: propsed this, but I am not sure how robust this is, e.g.
+ // the prefix (fas, far) class changes are not considered?
+ // if (span.tagName === "svg" && opts.preset === "awesome5") {
+ // // fa5 script converts <i> to <svg> so call a specific handler.
+ // var oldIcon = "fa-" + $span.data("icon");
+ // // node.debug( "setIcon(" + baseClass + ", " + type + "): " + oldIcon + " -> " + icon );
+ // if (typeof oldIcon === "string") {
+ // $span.removeClass(oldIcon);
+ // }
+ // if (typeof icon === "string") {
+ // $span.addClass(icon);
+ // }
+ // return;
+ // }
+ if (typeof icon === "string") {
+ // #883: remove inner html that may be added by prev. mode
+ span.innerHTML = "";
+ $span.attr("class", setClass + " " + icon).append($counter);
+ } else if (icon) {
+ if (icon.text) {
+ span.textContent = "" + icon.text;
+ } else if (icon.html) {
+ span.innerHTML = icon.html;
+ } else {
+ span.innerHTML = "";
+ }
+ $span
+ .attr("class", setClass + " " + (icon.addClass || ""))
+ .append($counter);
+ }
+ }
+
+ $.ui.fancytree.registerExtension({
+ name: "glyph",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ preset: null, // 'awesome3', 'awesome4', 'bootstrap3', 'material'
+ map: {},
+ },
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ opts = ctx.options.glyph;
+
+ if (opts.preset) {
+ FT.assert(
+ !!PRESETS[opts.preset],
+ "Invalid value for `options.glyph.preset`: " + opts.preset
+ );
+ opts.map = $.extend({}, PRESETS[opts.preset], opts.map);
+ } else {
+ tree.warn("ext-glyph: missing `preset` option.");
+ }
+ this._superApply(arguments);
+ tree.$container.addClass("fancytree-ext-glyph");
+ },
+ nodeRenderStatus: function (ctx) {
+ var checkbox,
+ icon,
+ res,
+ span,
+ node = ctx.node,
+ $span = $(node.span),
+ opts = ctx.options.glyph;
+
+ res = this._super(ctx);
+
+ if (node.isRootNode()) {
+ return res;
+ }
+ span = $span.children(".fancytree-expander").get(0);
+ if (span) {
+ // if( node.isLoading() ){
+ // icon = "loading";
+ if (node.expanded && node.hasChildren()) {
+ icon = "expanderOpen";
+ } else if (node.isUndefined()) {
+ icon = "expanderLazy";
+ } else if (node.hasChildren()) {
+ icon = "expanderClosed";
+ } else {
+ icon = "noExpander";
+ }
+ // span.className = "fancytree-expander " + map[icon];
+ setIcon(node, span, "fancytree-expander", opts, icon);
+ }
+
+ if (node.tr) {
+ span = $("td", node.tr).find(".fancytree-checkbox").get(0);
+ } else {
+ span = $span.children(".fancytree-checkbox").get(0);
+ }
+ if (span) {
+ checkbox = FT.evalOption("checkbox", node, node, opts, false);
+ if (
+ (node.parent && node.parent.radiogroup) ||
+ checkbox === "radio"
+ ) {
+ icon = node.selected ? "radioSelected" : "radio";
+ setIcon(
+ node,
+ span,
+ "fancytree-checkbox fancytree-radio",
+ opts,
+ icon
+ );
+ } else {
+ // eslint-disable-next-line no-nested-ternary
+ icon = node.selected
+ ? "checkboxSelected"
+ : node.partsel
+ ? "checkboxUnknown"
+ : "checkbox";
+ // span.className = "fancytree-checkbox " + map[icon];
+ setIcon(node, span, "fancytree-checkbox", opts, icon);
+ }
+ }
+
+ // Standard icon (note that this does not match .fancytree-custom-icon,
+ // that might be set by opts.icon callbacks)
+ span = $span.children(".fancytree-icon").get(0);
+ if (span) {
+ if (node.statusNodeType) {
+ icon = node.statusNodeType; // loading, error
+ } else if (node.folder) {
+ icon =
+ node.expanded && node.hasChildren()
+ ? "folderOpen"
+ : "folder";
+ } else {
+ icon = node.expanded ? "docOpen" : "doc";
+ }
+ setIcon(node, span, "fancytree-icon", opts, icon);
+ }
+ return res;
+ },
+ nodeSetStatus: function (ctx, status, message, details) {
+ var res,
+ span,
+ opts = ctx.options.glyph,
+ node = ctx.node;
+
+ res = this._superApply(arguments);
+
+ if (
+ status === "error" ||
+ status === "loading" ||
+ status === "nodata"
+ ) {
+ if (node.parent) {
+ span = $(".fancytree-expander", node.span).get(0);
+ if (span) {
+ setIcon(node, span, "fancytree-expander", opts, status);
+ }
+ } else {
+ //
+ span = $(
+ ".fancytree-statusnode-" + status,
+ node[this.nodeContainerAttrName]
+ )
+ .find(".fancytree-icon")
+ .get(0);
+ if (span) {
+ setIcon(node, span, "fancytree-icon", opts, status);
+ }
+ }
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.gridnav.js' *//*!
+ * jquery.fancytree.gridnav.js
+ *
+ * Support keyboard navigation for trees with embedded input controls.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([
+ "jquery",
+ "./jquery.fancytree",
+ "./jquery.fancytree.table",
+ ], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree.table"); // core + table
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ // Allow these navigation keys even when input controls are focused
+
+ var KC = $.ui.keyCode,
+ // which keys are *not* handled by embedded control, but passed to tree
+ // navigation handler:
+ NAV_KEYS = {
+ text: [KC.UP, KC.DOWN],
+ checkbox: [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+ link: [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+ radiobutton: [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+ "select-one": [KC.LEFT, KC.RIGHT],
+ "select-multiple": [KC.LEFT, KC.RIGHT],
+ };
+
+ /* Calculate TD column index (considering colspans).*/
+ function getColIdx($tr, $td) {
+ var colspan,
+ td = $td.get(0),
+ idx = 0;
+
+ $tr.children().each(function () {
+ if (this === td) {
+ return false;
+ }
+ colspan = $(this).prop("colspan");
+ idx += colspan ? colspan : 1;
+ });
+ return idx;
+ }
+
+ /* Find TD at given column index (considering colspans).*/
+ function findTdAtColIdx($tr, colIdx) {
+ var colspan,
+ res = null,
+ idx = 0;
+
+ $tr.children().each(function () {
+ if (idx >= colIdx) {
+ res = $(this);
+ return false;
+ }
+ colspan = $(this).prop("colspan");
+ idx += colspan ? colspan : 1;
+ });
+ return res;
+ }
+
+ /* Find adjacent cell for a given direction. Skip empty cells and consider merged cells */
+ function findNeighbourTd($target, keyCode) {
+ var $tr,
+ colIdx,
+ $td = $target.closest("td"),
+ $tdNext = null;
+
+ switch (keyCode) {
+ case KC.LEFT:
+ $tdNext = $td.prev();
+ break;
+ case KC.RIGHT:
+ $tdNext = $td.next();
+ break;
+ case KC.UP:
+ case KC.DOWN:
+ $tr = $td.parent();
+ colIdx = getColIdx($tr, $td);
+ while (true) {
+ $tr = keyCode === KC.UP ? $tr.prev() : $tr.next();
+ if (!$tr.length) {
+ break;
+ }
+ // Skip hidden rows
+ if ($tr.is(":hidden")) {
+ continue;
+ }
+ // Find adjacent cell in the same column
+ $tdNext = findTdAtColIdx($tr, colIdx);
+ // Skip cells that don't conatain a focusable element
+ if ($tdNext && $tdNext.find(":input,a").length) {
+ break;
+ }
+ }
+ break;
+ }
+ return $tdNext;
+ }
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "gridnav",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ autofocusInput: false, // Focus first embedded input if node gets activated
+ handleCursorKeys: true, // Allow UP/DOWN in inputs to move to prev/next node
+ },
+
+ treeInit: function (ctx) {
+ // gridnav requires the table extension to be loaded before itself
+ this._requireExtension("table", true, true);
+ this._superApply(arguments);
+
+ this.$container.addClass("fancytree-ext-gridnav");
+
+ // Activate node if embedded input gets focus (due to a click)
+ this.$container.on("focusin", function (event) {
+ var ctx2,
+ node = $.ui.fancytree.getNode(event.target);
+
+ if (node && !node.isActive()) {
+ // Call node.setActive(), but also pass the event
+ ctx2 = ctx.tree._makeHookContext(node, event);
+ ctx.tree._callHook("nodeSetActive", ctx2, true);
+ }
+ });
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var $outer,
+ opts = ctx.options.gridnav,
+ node = ctx.node,
+ event = ctx.originalEvent || {},
+ triggeredByInput = $(event.target).is(":input");
+
+ flag = flag !== false;
+
+ this._superApply(arguments);
+
+ if (flag) {
+ if (ctx.options.titlesTabbable) {
+ if (!triggeredByInput) {
+ $(node.span).find("span.fancytree-title").focus();
+ node.setFocus();
+ }
+ // If one node is tabbable, the container no longer needs to be
+ ctx.tree.$container.attr("tabindex", "-1");
+ // ctx.tree.$container.removeAttr("tabindex");
+ } else if (opts.autofocusInput && !triggeredByInput) {
+ // Set focus to input sub input (if node was clicked, but not
+ // when TAB was pressed )
+ $outer = $(node.tr || node.span);
+ $outer.find(":input:enabled").first().focus();
+ }
+ }
+ },
+ nodeKeydown: function (ctx) {
+ var inputType,
+ handleKeys,
+ $td,
+ opts = ctx.options.gridnav,
+ event = ctx.originalEvent,
+ $target = $(event.target);
+
+ if ($target.is(":input:enabled")) {
+ inputType = $target.prop("type");
+ } else if ($target.is("a")) {
+ inputType = "link";
+ }
+ // ctx.tree.debug("ext-gridnav nodeKeydown", event, inputType);
+
+ if (inputType && opts.handleCursorKeys) {
+ handleKeys = NAV_KEYS[inputType];
+ if (handleKeys && $.inArray(event.which, handleKeys) >= 0) {
+ $td = findNeighbourTd($target, event.which);
+ if ($td && $td.length) {
+ // ctx.node.debug("ignore keydown in input", event.which, handleKeys);
+ $td.find(":input:enabled,a").focus();
+ // Prevent Fancytree default navigation
+ return false;
+ }
+ }
+ return true;
+ }
+ // ctx.tree.debug("ext-gridnav NOT HANDLED", event, inputType);
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.multi.js' *//*!
+ * jquery.fancytree.multi.js
+ *
+ * Allow multiple selection of nodes by mouse or keyboard.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ // var isMac = /Mac/.test(navigator.platform);
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "multi",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ allowNoSelect: false, //
+ mode: "sameParent", //
+ // Events:
+ // beforeSelect: $.noop // Return false to prevent cancel/save (data.input is available)
+ },
+
+ treeInit: function (ctx) {
+ this._superApply(arguments);
+ this.$container.addClass("fancytree-ext-multi");
+ if (ctx.options.selectMode === 1) {
+ $.error(
+ "Fancytree ext-multi: selectMode: 1 (single) is not compatible."
+ );
+ }
+ },
+ nodeClick: function (ctx) {
+ var //pluginOpts = ctx.options.multi,
+ tree = ctx.tree,
+ node = ctx.node,
+ activeNode = tree.getActiveNode() || tree.getFirstChild(),
+ isCbClick = ctx.targetType === "checkbox",
+ isExpanderClick = ctx.targetType === "expander",
+ eventStr = $.ui.fancytree.eventToString(ctx.originalEvent);
+
+ switch (eventStr) {
+ case "click":
+ if (isExpanderClick) {
+ break;
+ } // Default handler will expand/collapse
+ if (!isCbClick) {
+ tree.selectAll(false);
+ // Select clicked node (radio-button mode)
+ node.setSelected();
+ }
+ // Default handler will toggle checkbox clicks and activate
+ break;
+ case "shift+click":
+ // node.debug("click")
+ tree.visitRows(
+ function (n) {
+ // n.debug("click2", n===node, node)
+ n.setSelected();
+ if (n === node) {
+ return false;
+ }
+ },
+ {
+ start: activeNode,
+ reverse: activeNode.isBelowOf(node),
+ }
+ );
+ break;
+ case "ctrl+click":
+ case "meta+click": // Mac: [Command]
+ node.toggleSelected();
+ return;
+ }
+ return this._superApply(arguments);
+ },
+ nodeKeydown: function (ctx) {
+ var tree = ctx.tree,
+ node = ctx.node,
+ event = ctx.originalEvent,
+ eventStr = $.ui.fancytree.eventToString(event);
+
+ switch (eventStr) {
+ case "up":
+ case "down":
+ tree.selectAll(false);
+ node.navigate(event.which, true);
+ tree.getActiveNode().setSelected();
+ break;
+ case "shift+up":
+ case "shift+down":
+ node.navigate(event.which, true);
+ tree.getActiveNode().setSelected();
+ break;
+ }
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.persist.js' *//*!
+ * jquery.fancytree.persist.js
+ *
+ * Persist tree status in cookiesRemove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @depends: js-cookie or jquery-cookie
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+ /* global Cookies:false */
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+ var cookieStore = null,
+ localStorageStore = null,
+ sessionStorageStore = null,
+ _assert = $.ui.fancytree.assert,
+ ACTIVE = "active",
+ EXPANDED = "expanded",
+ FOCUS = "focus",
+ SELECTED = "selected";
+
+ // Accessing window.xxxStorage may raise security exceptions (see #1022)
+ try {
+ _assert(window.localStorage && window.localStorage.getItem);
+ localStorageStore = {
+ get: function (key) {
+ return window.localStorage.getItem(key);
+ },
+ set: function (key, value) {
+ window.localStorage.setItem(key, value);
+ },
+ remove: function (key) {
+ window.localStorage.removeItem(key);
+ },
+ };
+ } catch (e) {
+ $.ui.fancytree.warn("Could not access window.localStorage", e);
+ }
+
+ try {
+ _assert(window.sessionStorage && window.sessionStorage.getItem);
+ sessionStorageStore = {
+ get: function (key) {
+ return window.sessionStorage.getItem(key);
+ },
+ set: function (key, value) {
+ window.sessionStorage.setItem(key, value);
+ },
+ remove: function (key) {
+ window.sessionStorage.removeItem(key);
+ },
+ };
+ } catch (e) {
+ $.ui.fancytree.warn("Could not access window.sessionStorage", e);
+ }
+
+ if (typeof Cookies === "function") {
+ // Assume https://github.com/js-cookie/js-cookie
+ cookieStore = {
+ get: Cookies.get,
+ set: function (key, value) {
+ Cookies.set(key, value, this.options.persist.cookie);
+ },
+ remove: Cookies.remove,
+ };
+ } else if ($ && typeof $.cookie === "function") {
+ // Fall back to https://github.com/carhartl/jquery-cookie
+ cookieStore = {
+ get: $.cookie,
+ set: function (key, value) {
+ $.cookie(key, value, this.options.persist.cookie);
+ },
+ remove: $.removeCookie,
+ };
+ }
+
+ /* Recursively load lazy nodes
+ * @param {string} mode 'load', 'expand', false
+ */
+ function _loadLazyNodes(tree, local, keyList, mode, dfd) {
+ var i,
+ key,
+ l,
+ node,
+ foundOne = false,
+ expandOpts = tree.options.persist.expandOpts,
+ deferredList = [],
+ missingKeyList = [];
+
+ keyList = keyList || [];
+ dfd = dfd || $.Deferred();
+
+ for (i = 0, l = keyList.length; i < l; i++) {
+ key = keyList[i];
+ node = tree.getNodeByKey(key);
+ if (node) {
+ if (mode && node.isUndefined()) {
+ foundOne = true;
+ tree.debug(
+ "_loadLazyNodes: " + node + " is lazy: loading..."
+ );
+ if (mode === "expand") {
+ deferredList.push(node.setExpanded(true, expandOpts));
+ } else {
+ deferredList.push(node.load());
+ }
+ } else {
+ tree.debug("_loadLazyNodes: " + node + " already loaded.");
+ node.setExpanded(true, expandOpts);
+ }
+ } else {
+ missingKeyList.push(key);
+ tree.debug("_loadLazyNodes: " + node + " was not yet found.");
+ }
+ }
+
+ $.when.apply($, deferredList).always(function () {
+ // All lazy-expands have finished
+ if (foundOne && missingKeyList.length > 0) {
+ // If we read new nodes from server, try to resolve yet-missing keys
+ _loadLazyNodes(tree, local, missingKeyList, mode, dfd);
+ } else {
+ if (missingKeyList.length) {
+ tree.warn(
+ "_loadLazyNodes: could not load those keys: ",
+ missingKeyList
+ );
+ for (i = 0, l = missingKeyList.length; i < l; i++) {
+ key = keyList[i];
+ local._appendKey(EXPANDED, keyList[i], false);
+ }
+ }
+ dfd.resolve();
+ }
+ });
+ return dfd;
+ }
+
+ /**
+ * [ext-persist] Remove persistence data of the given type(s).
+ * Called like
+ * $.ui.fancytree.getTree("#tree").clearCookies("active expanded focus selected");
+ *
+ * @alias Fancytree#clearPersistData
+ * @requires jquery.fancytree.persist.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.clearPersistData = function (
+ types
+ ) {
+ var local = this.ext.persist,
+ prefix = local.cookiePrefix;
+
+ types = types || "active expanded focus selected";
+ if (types.indexOf(ACTIVE) >= 0) {
+ local._data(prefix + ACTIVE, null);
+ }
+ if (types.indexOf(EXPANDED) >= 0) {
+ local._data(prefix + EXPANDED, null);
+ }
+ if (types.indexOf(FOCUS) >= 0) {
+ local._data(prefix + FOCUS, null);
+ }
+ if (types.indexOf(SELECTED) >= 0) {
+ local._data(prefix + SELECTED, null);
+ }
+ };
+
+ $.ui.fancytree._FancytreeClass.prototype.clearCookies = function (types) {
+ this.warn(
+ "'tree.clearCookies()' is deprecated since v2.27.0: use 'clearPersistData()' instead."
+ );
+ return this.clearPersistData(types);
+ };
+
+ /**
+ * [ext-persist] Return persistence information from cookies
+ *
+ * Called like
+ * $.ui.fancytree.getTree("#tree").getPersistData();
+ *
+ * @alias Fancytree#getPersistData
+ * @requires jquery.fancytree.persist.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.getPersistData = function () {
+ var local = this.ext.persist,
+ prefix = local.cookiePrefix,
+ delim = local.cookieDelimiter,
+ res = {};
+
+ res[ACTIVE] = local._data(prefix + ACTIVE);
+ res[EXPANDED] = (local._data(prefix + EXPANDED) || "").split(delim);
+ res[SELECTED] = (local._data(prefix + SELECTED) || "").split(delim);
+ res[FOCUS] = local._data(prefix + FOCUS);
+ return res;
+ };
+
+ /******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "persist",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ cookieDelimiter: "~",
+ cookiePrefix: undefined, // 'fancytree-<treeId>-' by default
+ cookie: {
+ raw: false,
+ expires: "",
+ path: "",
+ domain: "",
+ secure: false,
+ },
+ expandLazy: false, // true: recursively expand and load lazy nodes
+ expandOpts: undefined, // optional `opts` argument passed to setExpanded()
+ fireActivate: true, // false: suppress `activate` event after active node was restored
+ overrideSource: true, // true: cookie takes precedence over `source` data attributes.
+ store: "auto", // 'cookie': force cookie, 'local': force localStore, 'session': force sessionStore
+ types: "active expanded focus selected",
+ },
+
+ /* Generic read/write string data to cookie, sessionStorage or localStorage. */
+ _data: function (key, value) {
+ var store = this._local.store;
+
+ if (value === undefined) {
+ return store.get.call(this, key);
+ } else if (value === null) {
+ store.remove.call(this, key);
+ } else {
+ store.set.call(this, key, value);
+ }
+ },
+
+ /* Append `key` to a cookie. */
+ _appendKey: function (type, key, flag) {
+ key = "" + key; // #90
+ var local = this._local,
+ instOpts = this.options.persist,
+ delim = instOpts.cookieDelimiter,
+ cookieName = local.cookiePrefix + type,
+ data = local._data(cookieName),
+ keyList = data ? data.split(delim) : [],
+ idx = $.inArray(key, keyList);
+ // Remove, even if we add a key, so the key is always the last entry
+ if (idx >= 0) {
+ keyList.splice(idx, 1);
+ }
+ // Append key to cookie
+ if (flag) {
+ keyList.push(key);
+ }
+ local._data(cookieName, keyList.join(delim));
+ },
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ opts = ctx.options,
+ local = this._local,
+ instOpts = this.options.persist;
+
+ // // For 'auto' or 'cookie' mode, the cookie plugin must be available
+ // _assert((instOpts.store !== "auto" && instOpts.store !== "cookie") || cookieStore,
+ // "Missing required plugin for 'persist' extension: js.cookie.js or jquery.cookie.js");
+
+ local.cookiePrefix =
+ instOpts.cookiePrefix || "fancytree-" + tree._id + "-";
+ local.storeActive = instOpts.types.indexOf(ACTIVE) >= 0;
+ local.storeExpanded = instOpts.types.indexOf(EXPANDED) >= 0;
+ local.storeSelected = instOpts.types.indexOf(SELECTED) >= 0;
+ local.storeFocus = instOpts.types.indexOf(FOCUS) >= 0;
+ local.store = null;
+
+ if (instOpts.store === "auto") {
+ instOpts.store = localStorageStore ? "local" : "cookie";
+ }
+ if ($.isPlainObject(instOpts.store)) {
+ local.store = instOpts.store;
+ } else if (instOpts.store === "cookie") {
+ local.store = cookieStore;
+ } else if (instOpts.store === "local") {
+ local.store =
+ instOpts.store === "local"
+ ? localStorageStore
+ : sessionStorageStore;
+ } else if (instOpts.store === "session") {
+ local.store =
+ instOpts.store === "local"
+ ? localStorageStore
+ : sessionStorageStore;
+ }
+ _assert(local.store, "Need a valid store.");
+
+ // Bind init-handler to apply cookie state
+ tree.$div.on("fancytreeinit", function (event) {
+ if (
+ tree._triggerTreeEvent("beforeRestore", null, {}) === false
+ ) {
+ return;
+ }
+
+ var cookie,
+ dfd,
+ i,
+ keyList,
+ node,
+ prevFocus = local._data(local.cookiePrefix + FOCUS), // record this before node.setActive() overrides it;
+ noEvents = instOpts.fireActivate === false;
+
+ // tree.debug("document.cookie:", document.cookie);
+
+ cookie = local._data(local.cookiePrefix + EXPANDED);
+ keyList = cookie && cookie.split(instOpts.cookieDelimiter);
+
+ if (local.storeExpanded) {
+ // Recursively load nested lazy nodes if expandLazy is 'expand' or 'load'
+ // Also remove expand-cookies for unmatched nodes
+ dfd = _loadLazyNodes(
+ tree,
+ local,
+ keyList,
+ instOpts.expandLazy ? "expand" : false,
+ null
+ );
+ } else {
+ // nothing to do
+ dfd = new $.Deferred().resolve();
+ }
+
+ dfd.done(function () {
+ if (local.storeSelected) {
+ cookie = local._data(local.cookiePrefix + SELECTED);
+ if (cookie) {
+ keyList = cookie.split(instOpts.cookieDelimiter);
+ for (i = 0; i < keyList.length; i++) {
+ node = tree.getNodeByKey(keyList[i]);
+ if (node) {
+ if (
+ node.selected === undefined ||
+ (instOpts.overrideSource &&
+ node.selected === false)
+ ) {
+ // node.setSelected();
+ node.selected = true;
+ node.renderStatus();
+ }
+ } else {
+ // node is no longer member of the tree: remove from cookie also
+ local._appendKey(
+ SELECTED,
+ keyList[i],
+ false
+ );
+ }
+ }
+ }
+ // In selectMode 3 we have to fix the child nodes, since we
+ // only stored the selected *top* nodes
+ if (tree.options.selectMode === 3) {
+ tree.visit(function (n) {
+ if (n.selected) {
+ n.fixSelection3AfterClick();
+ return "skip";
+ }
+ });
+ }
+ }
+ if (local.storeActive) {
+ cookie = local._data(local.cookiePrefix + ACTIVE);
+ if (
+ cookie &&
+ (opts.persist.overrideSource || !tree.activeNode)
+ ) {
+ node = tree.getNodeByKey(cookie);
+ if (node) {
+ node.debug("persist: set active", cookie);
+ // We only want to set the focus if the container
+ // had the keyboard focus before
+ node.setActive(true, {
+ noFocus: true,
+ noEvents: noEvents,
+ });
+ }
+ }
+ }
+ if (local.storeFocus && prevFocus) {
+ node = tree.getNodeByKey(prevFocus);
+ if (node) {
+ // node.debug("persist: set focus", cookie);
+ if (tree.options.titlesTabbable) {
+ $(node.span).find(".fancytree-title").focus();
+ } else {
+ $(tree.$container).focus();
+ }
+ // node.setFocus();
+ }
+ }
+ tree._triggerTreeEvent("restore", null, {});
+ });
+ });
+ // Init the tree
+ return this._superApply(arguments);
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var res,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeActive) {
+ local._data(
+ local.cookiePrefix + ACTIVE,
+ this.activeNode ? this.activeNode.key : null
+ );
+ }
+ return res;
+ },
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var res,
+ node = ctx.node,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeExpanded) {
+ local._appendKey(EXPANDED, node.key, flag);
+ }
+ return res;
+ },
+ nodeSetFocus: function (ctx, flag) {
+ var res,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeFocus) {
+ local._data(
+ local.cookiePrefix + FOCUS,
+ this.focusNode ? this.focusNode.key : null
+ );
+ }
+ return res;
+ },
+ nodeSetSelected: function (ctx, flag, callOpts) {
+ var res,
+ selNodes,
+ tree = ctx.tree,
+ node = ctx.node,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeSelected) {
+ if (tree.options.selectMode === 3) {
+ // In selectMode 3 we only store the the selected *top* nodes.
+ // De-selecting a node may also de-select some parents, so we
+ // calculate the current status again
+ selNodes = $.map(tree.getSelectedNodes(true), function (n) {
+ return n.key;
+ });
+ selNodes = selNodes.join(
+ ctx.options.persist.cookieDelimiter
+ );
+ local._data(local.cookiePrefix + SELECTED, selNodes);
+ } else {
+ // beforeSelect can prevent the change - flag doesn't reflect the node.selected state
+ local._appendKey(SELECTED, node.key, node.selected);
+ }
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.table.js' *//*!
+ * jquery.fancytree.table.js
+ *
+ * Render tree as table (aka 'tree grid', 'table tree').
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var _assert = $.ui.fancytree.assert;
+
+ function insertFirstChild(referenceNode, newNode) {
+ referenceNode.insertBefore(newNode, referenceNode.firstChild);
+ }
+
+ function insertSiblingAfter(referenceNode, newNode) {
+ referenceNode.parentNode.insertBefore(
+ newNode,
+ referenceNode.nextSibling
+ );
+ }
+
+ /* Show/hide all rows that are structural descendants of `parent`. */
+ function setChildRowVisibility(parent, flag) {
+ parent.visit(function (node) {
+ var tr = node.tr;
+ // currentFlag = node.hide ? false : flag; // fix for ext-filter
+ if (tr) {
+ tr.style.display = node.hide || !flag ? "none" : "";
+ }
+ if (!node.expanded) {
+ return "skip";
+ }
+ });
+ }
+
+ /* Find node that is rendered in previous row. */
+ function findPrevRowNode(node) {
+ var i,
+ last,
+ prev,
+ parent = node.parent,
+ siblings = parent ? parent.children : null;
+
+ if (siblings && siblings.length > 1 && siblings[0] !== node) {
+ // use the lowest descendant of the preceeding sibling
+ i = $.inArray(node, siblings);
+ prev = siblings[i - 1];
+ _assert(prev.tr);
+ // descend to lowest child (with a <tr> tag)
+ while (prev.children && prev.children.length) {
+ last = prev.children[prev.children.length - 1];
+ if (!last.tr) {
+ break;
+ }
+ prev = last;
+ }
+ } else {
+ // if there is no preceding sibling, use the direct parent
+ prev = parent;
+ }
+ return prev;
+ }
+
+ $.ui.fancytree.registerExtension({
+ name: "table",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx)
+ indentation: 16, // indent every node level by 16px
+ mergeStatusColumns: true, // display 'nodata', 'loading', 'error' centered in a single, merged TR
+ nodeColumnIdx: 0, // render node expander, icon, and title to this column (default: #0)
+ },
+ // Overide virtual methods for this extension.
+ // `this` : is this extension object
+ // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
+ treeInit: function (ctx) {
+ var i,
+ n,
+ $row,
+ $tbody,
+ tree = ctx.tree,
+ opts = ctx.options,
+ tableOpts = opts.table,
+ $table = tree.widget.element;
+
+ if (tableOpts.customStatus != null) {
+ if (opts.renderStatusColumns == null) {
+ tree.warn(
+ "The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' instead."
+ );
+ opts.renderStatusColumns = tableOpts.customStatus;
+ } else {
+ $.error(
+ "The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' only instead."
+ );
+ }
+ }
+ if (opts.renderStatusColumns) {
+ if (opts.renderStatusColumns === true) {
+ opts.renderStatusColumns = opts.renderColumns;
+ // } else if( opts.renderStatusColumns === "wide" ) {
+ // opts.renderStatusColumns = _renderStatusNodeWide;
+ }
+ }
+
+ $table.addClass("fancytree-container fancytree-ext-table");
+ $tbody = $table.find(">tbody");
+ if (!$tbody.length) {
+ // TODO: not sure if we can rely on browsers to insert missing <tbody> before <tr>s:
+ if ($table.find(">tr").length) {
+ $.error(
+ "Expected table > tbody > tr. If you see this please open an issue."
+ );
+ }
+ $tbody = $("<tbody>").appendTo($table);
+ }
+
+ tree.tbody = $tbody[0];
+
+ // Prepare row templates:
+ // Determine column count from table header if any
+ tree.columnCount = $("thead >tr", $table)
+ .last()
+ .find(">th", $table).length;
+ // Read TR templates from tbody if any
+ $row = $tbody.children("tr").first();
+ if ($row.length) {
+ n = $row.children("td").length;
+ if (tree.columnCount && n !== tree.columnCount) {
+ tree.warn(
+ "Column count mismatch between thead (" +
+ tree.columnCount +
+ ") and tbody (" +
+ n +
+ "): using tbody."
+ );
+ tree.columnCount = n;
+ }
+ $row = $row.clone();
+ } else {
+ // Only thead is defined: create default row markup
+ _assert(
+ tree.columnCount >= 1,
+ "Need either <thead> or <tbody> with <td> elements to determine column count."
+ );
+ $row = $("<tr />");
+ for (i = 0; i < tree.columnCount; i++) {
+ $row.append("<td />");
+ }
+ }
+ $row.find(">td")
+ .eq(tableOpts.nodeColumnIdx)
+ .html("<span class='fancytree-node' />");
+ if (opts.aria) {
+ $row.attr("role", "row");
+ $row.find("td").attr("role", "gridcell");
+ }
+ tree.rowFragment = document.createDocumentFragment();
+ tree.rowFragment.appendChild($row.get(0));
+
+ // // If tbody contains a second row, use this as status node template
+ // $row = $tbody.children("tr").eq(1);
+ // if( $row.length === 0 ) {
+ // tree.statusRowFragment = tree.rowFragment;
+ // } else {
+ // $row = $row.clone();
+ // tree.statusRowFragment = document.createDocumentFragment();
+ // tree.statusRowFragment.appendChild($row.get(0));
+ // }
+ //
+ $tbody.empty();
+
+ // Make sure that status classes are set on the node's <tr> elements
+ tree.statusClassPropName = "tr";
+ tree.ariaPropName = "tr";
+ this.nodeContainerAttrName = "tr";
+
+ // #489: make sure $container is set to <table>, even if ext-dnd is listed before ext-table
+ tree.$container = $table;
+
+ this._superApply(arguments);
+
+ // standard Fancytree created a root UL
+ $(tree.rootNode.ul).remove();
+ tree.rootNode.ul = null;
+
+ // Add container to the TAB chain
+ // #577: Allow to set tabindex to "0", "-1" and ""
+ this.$container.attr("tabindex", opts.tabindex);
+ // this.$container.attr("tabindex", opts.tabbable ? "0" : "-1");
+ if (opts.aria) {
+ tree.$container
+ .attr("role", "treegrid")
+ .attr("aria-readonly", true);
+ }
+ },
+ nodeRemoveChildMarkup: function (ctx) {
+ var node = ctx.node;
+ // node.debug("nodeRemoveChildMarkup()");
+ node.visit(function (n) {
+ if (n.tr) {
+ $(n.tr).remove();
+ n.tr = null;
+ }
+ });
+ },
+ nodeRemoveMarkup: function (ctx) {
+ var node = ctx.node;
+ // node.debug("nodeRemoveMarkup()");
+ if (node.tr) {
+ $(node.tr).remove();
+ node.tr = null;
+ }
+ this.nodeRemoveChildMarkup(ctx);
+ },
+ /* Override standard render. */
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ var children,
+ firstTr,
+ i,
+ l,
+ newRow,
+ prevNode,
+ prevTr,
+ subCtx,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = ctx.options,
+ isRootNode = !node.parent;
+
+ if (tree._enableUpdate === false) {
+ // $.ui.fancytree.debug("*** nodeRender _enableUpdate: false");
+ return;
+ }
+ if (!_recursive) {
+ ctx.hasCollapsedParents = node.parent && !node.parent.expanded;
+ }
+ // $.ui.fancytree.debug("*** nodeRender " + node + ", isRoot=" + isRootNode, "tr=" + node.tr, "hcp=" + ctx.hasCollapsedParents, "parent.tr=" + (node.parent && node.parent.tr));
+ if (!isRootNode) {
+ if (node.tr && force) {
+ this.nodeRemoveMarkup(ctx);
+ }
+ if (node.tr) {
+ if (force) {
+ // Set icon, link, and title (normally this is only required on initial render)
+ this.nodeRenderTitle(ctx); // triggers renderColumns()
+ } else {
+ // Update element classes according to node state
+ this.nodeRenderStatus(ctx);
+ }
+ } else {
+ if (ctx.hasCollapsedParents && !deep) {
+ // #166: we assume that the parent will be (recursively) rendered
+ // later anyway.
+ // node.debug("nodeRender ignored due to unrendered parent");
+ return;
+ }
+ // Create new <tr> after previous row
+ // if( node.isStatusNode() ) {
+ // newRow = tree.statusRowFragment.firstChild.cloneNode(true);
+ // } else {
+ newRow = tree.rowFragment.firstChild.cloneNode(true);
+ // }
+ prevNode = findPrevRowNode(node);
+ // $.ui.fancytree.debug("*** nodeRender " + node + ": prev: " + prevNode.key);
+ _assert(prevNode);
+ if (collapsed === true && _recursive) {
+ // hide all child rows, so we can use an animation to show it later
+ newRow.style.display = "none";
+ } else if (deep && ctx.hasCollapsedParents) {
+ // also hide this row if deep === true but any parent is collapsed
+ newRow.style.display = "none";
+ // newRow.style.color = "red";
+ }
+ if (prevNode.tr) {
+ insertSiblingAfter(prevNode.tr, newRow);
+ } else {
+ _assert(
+ !prevNode.parent,
+ "prev. row must have a tr, or be system root"
+ );
+ // tree.tbody.appendChild(newRow);
+ insertFirstChild(tree.tbody, newRow); // #675
+ }
+ node.tr = newRow;
+ if (node.key && opts.generateIds) {
+ node.tr.id = opts.idPrefix + node.key;
+ }
+ node.tr.ftnode = node;
+ // if(opts.aria){
+ // $(node.tr).attr("aria-labelledby", "ftal_" + opts.idPrefix + node.key);
+ // }
+ node.span = $("span.fancytree-node", node.tr).get(0);
+ // Set icon, link, and title (normally this is only required on initial render)
+ this.nodeRenderTitle(ctx);
+ // Allow tweaking, binding, after node was created for the first time
+ // tree._triggerNodeEvent("createNode", ctx);
+ if (opts.createNode) {
+ opts.createNode.call(tree, { type: "createNode" }, ctx);
+ }
+ }
+ }
+ // Allow tweaking after node state was rendered
+ // tree._triggerNodeEvent("renderNode", ctx);
+ if (opts.renderNode) {
+ opts.renderNode.call(tree, { type: "renderNode" }, ctx);
+ }
+ // Visit child nodes
+ // Add child markup
+ children = node.children;
+ if (children && (isRootNode || deep || node.expanded)) {
+ for (i = 0, l = children.length; i < l; i++) {
+ subCtx = $.extend({}, ctx, { node: children[i] });
+ subCtx.hasCollapsedParents =
+ subCtx.hasCollapsedParents || !node.expanded;
+ this.nodeRender(subCtx, force, deep, collapsed, true);
+ }
+ }
+ // Make sure, that <tr> order matches node.children order.
+ if (children && !_recursive) {
+ // we only have to do it once, for the root branch
+ prevTr = node.tr || null;
+ firstTr = tree.tbody.firstChild;
+ // Iterate over all descendants
+ node.visit(function (n) {
+ if (n.tr) {
+ if (
+ !n.parent.expanded &&
+ n.tr.style.display !== "none"
+ ) {
+ // fix after a node was dropped over a collapsed
+ n.tr.style.display = "none";
+ setChildRowVisibility(n, false);
+ }
+ if (n.tr.previousSibling !== prevTr) {
+ node.debug("_fixOrder: mismatch at node: " + n);
+ var nextTr = prevTr ? prevTr.nextSibling : firstTr;
+ tree.tbody.insertBefore(n.tr, nextTr);
+ }
+ prevTr = n.tr;
+ }
+ });
+ }
+ // Update element classes according to node state
+ // if(!isRootNode){
+ // this.nodeRenderStatus(ctx);
+ // }
+ },
+ nodeRenderTitle: function (ctx, title) {
+ var $cb,
+ res,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = ctx.options,
+ isStatusNode = node.isStatusNode();
+
+ res = this._super(ctx, title);
+
+ if (node.isRootNode()) {
+ return res;
+ }
+ // Move checkbox to custom column
+ if (
+ opts.checkbox &&
+ !isStatusNode &&
+ opts.table.checkboxColumnIdx != null
+ ) {
+ $cb = $("span.fancytree-checkbox", node.span); //.detach();
+ $(node.tr)
+ .find("td")
+ .eq(+opts.table.checkboxColumnIdx)
+ .html($cb);
+ }
+ // Update element classes according to node state
+ this.nodeRenderStatus(ctx);
+
+ if (isStatusNode) {
+ if (opts.renderStatusColumns) {
+ // Let user code write column content
+ opts.renderStatusColumns.call(
+ tree,
+ { type: "renderStatusColumns" },
+ ctx
+ );
+ } else if (opts.table.mergeStatusColumns && node.isTopLevel()) {
+ $(node.tr)
+ .find(">td")
+ .eq(0)
+ .prop("colspan", tree.columnCount)
+ .text(node.title)
+ .addClass("fancytree-status-merged")
+ .nextAll()
+ .remove();
+ } // else: default rendering for status node: leave other cells empty
+ } else if (opts.renderColumns) {
+ opts.renderColumns.call(tree, { type: "renderColumns" }, ctx);
+ }
+ return res;
+ },
+ nodeRenderStatus: function (ctx) {
+ var indent,
+ node = ctx.node,
+ opts = ctx.options;
+
+ this._super(ctx);
+
+ $(node.tr).removeClass("fancytree-node");
+ // indent
+ indent = (node.getLevel() - 1) * opts.table.indentation;
+ if (opts.rtl) {
+ $(node.span).css({ paddingRight: indent + "px" });
+ } else {
+ $(node.span).css({ paddingLeft: indent + "px" });
+ }
+ },
+ /* Expand node, return Deferred.promise. */
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ // flag defaults to true
+ flag = flag !== false;
+
+ if ((ctx.node.expanded && flag) || (!ctx.node.expanded && !flag)) {
+ // Expanded state isn't changed - just call base implementation
+ return this._superApply(arguments);
+ }
+
+ var dfd = new $.Deferred(),
+ subOpts = $.extend({}, callOpts, {
+ noEvents: true,
+ noAnimation: true,
+ });
+
+ callOpts = callOpts || {};
+
+ function _afterExpand(ok, args) {
+ // ctx.tree.info("ok:" + ok, args);
+ if (ok) {
+ // #1108 minExpandLevel: 2 together with table extension does not work
+ // don't call when 'ok' is false:
+ setChildRowVisibility(ctx.node, flag);
+ if (
+ flag &&
+ ctx.options.autoScroll &&
+ !callOpts.noAnimation &&
+ ctx.node.hasChildren()
+ ) {
+ // Scroll down to last child, but keep current node visible
+ ctx.node
+ .getLastChild()
+ .scrollIntoView(true, { topNode: ctx.node })
+ .always(function () {
+ if (!callOpts.noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.resolveWith(ctx.node);
+ });
+ } else {
+ if (!callOpts.noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.resolveWith(ctx.node);
+ }
+ } else {
+ if (!callOpts.noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.rejectWith(ctx.node);
+ }
+ }
+ // Call base-expand with disabled events and animation
+ this._super(ctx, flag, subOpts)
+ .done(function () {
+ _afterExpand(true, arguments);
+ })
+ .fail(function () {
+ _afterExpand(false, arguments);
+ });
+ return dfd.promise();
+ },
+ nodeSetStatus: function (ctx, status, message, details) {
+ if (status === "ok") {
+ var node = ctx.node,
+ firstChild = node.children ? node.children[0] : null;
+ if (firstChild && firstChild.isStatusNode()) {
+ $(firstChild.tr).remove();
+ }
+ }
+ return this._superApply(arguments);
+ },
+ treeClear: function (ctx) {
+ this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode));
+ return this._superApply(arguments);
+ },
+ treeDestroy: function (ctx) {
+ this.$container.find("tbody").empty();
+ if (this.$source) {
+ this.$source.removeClass("fancytree-helper-hidden");
+ }
+ return this._superApply(arguments);
+ },
+ /*,
+ treeSetFocus: function(ctx, flag) {
+// alert("treeSetFocus" + ctx.tree.$container);
+ ctx.tree.$container.focus();
+ $.ui.fancytree.focusTree = ctx.tree;
+ }*/
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.themeroller.js' *//*!
+ * jquery.fancytree.themeroller.js
+ *
+ * Enable jQuery UI ThemeRoller styles.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @see http://jqueryui.com/themeroller/
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "themeroller",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ activeClass: "ui-state-active", // Class added to active node
+ // activeClass: "ui-state-highlight",
+ addClass: "ui-corner-all", // Class added to all nodes
+ focusClass: "ui-state-focus", // Class added to focused node
+ hoverClass: "ui-state-hover", // Class added to hovered node
+ selectedClass: "ui-state-highlight", // Class added to selected nodes
+ // selectedClass: "ui-state-active"
+ },
+
+ treeInit: function (ctx) {
+ var $el = ctx.widget.element,
+ opts = ctx.options.themeroller;
+
+ this._superApply(arguments);
+
+ if ($el[0].nodeName === "TABLE") {
+ $el.addClass("ui-widget ui-corner-all");
+ $el.find(">thead tr").addClass("ui-widget-header");
+ $el.find(">tbody").addClass("ui-widget-conent");
+ } else {
+ $el.addClass("ui-widget ui-widget-content ui-corner-all");
+ }
+
+ $el.on(
+ "mouseenter mouseleave",
+ ".fancytree-node",
+ function (event) {
+ var node = $.ui.fancytree.getNode(event.target),
+ flag = event.type === "mouseenter";
+
+ $(node.tr ? node.tr : node.span).toggleClass(
+ opts.hoverClass + " " + opts.addClass,
+ flag
+ );
+ }
+ );
+ },
+ treeDestroy: function (ctx) {
+ this._superApply(arguments);
+ ctx.widget.element.removeClass(
+ "ui-widget ui-widget-content ui-corner-all"
+ );
+ },
+ nodeRenderStatus: function (ctx) {
+ var classes = {},
+ node = ctx.node,
+ $el = $(node.tr ? node.tr : node.span),
+ opts = ctx.options.themeroller;
+
+ this._super(ctx);
+ /*
+ .ui-state-highlight: Class to be applied to highlighted or selected elements. Applies "highlight" container styles to an element and its child text, links, and icons.
+ .ui-state-error: Class to be applied to error messaging container elements. Applies "error" container styles to an element and its child text, links, and icons.
+ .ui-state-error-text: An additional class that applies just the error text color without background. Can be used on form labels for instance. Also applies error icon color to child icons.
+
+ .ui-state-default: Class to be applied to clickable button-like elements. Applies "clickable default" container styles to an element and its child text, links, and icons.
+ .ui-state-hover: Class to be applied on mouseover to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+ .ui-state-focus: Class to be applied on keyboard focus to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+ .ui-state-active: Class to be applied on mousedown to clickable button-like elements. Applies "clickable active" container styles to an element and its child text, links, and icons.
+*/
+ // Set ui-state-* class (handle the case that the same class is assigned
+ // to different states)
+ classes[opts.activeClass] = false;
+ classes[opts.focusClass] = false;
+ classes[opts.selectedClass] = false;
+ if (node.isActive()) {
+ classes[opts.activeClass] = true;
+ }
+ if (node.hasFocus()) {
+ classes[opts.focusClass] = true;
+ }
+ // activeClass takes precedence before selectedClass:
+ if (node.isSelected() && !node.isActive()) {
+ classes[opts.selectedClass] = true;
+ }
+ $el.toggleClass(opts.activeClass, classes[opts.activeClass]);
+ $el.toggleClass(opts.focusClass, classes[opts.focusClass]);
+ $el.toggleClass(opts.selectedClass, classes[opts.selectedClass]);
+ // Additional classes (e.g. 'ui-corner-all')
+ $el.addClass(opts.addClass);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+
+/*! Extension 'jquery.fancytree.wide.js' *//*!
+ * jquery.fancytree.wide.js
+ * Support for 100% wide selection bars.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ var reNumUnit = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/; // split "1.5em" to ["1.5", "em"]
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+ // var _assert = $.ui.fancytree.assert;
+
+ /* Calculate inner width without scrollbar */
+ // function realInnerWidth($el) {
+ // // http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/
+ // // inst.contWidth = parseFloat(this.$container.css("width"), 10);
+ // // 'Client width without scrollbar' - 'padding'
+ // return $el[0].clientWidth - ($el.innerWidth() - parseFloat($el.css("width"), 10));
+ // }
+
+ /* Create a global embedded CSS style for the tree. */
+ function defineHeadStyleElement(id, cssText) {
+ id = "fancytree-style-" + id;
+ var $headStyle = $("#" + id);
+
+ if (!cssText) {
+ $headStyle.remove();
+ return null;
+ }
+ if (!$headStyle.length) {
+ $headStyle = $("<style />")
+ .attr("id", id)
+ .addClass("fancytree-style")
+ .prop("type", "text/css")
+ .appendTo("head");
+ }
+ try {
+ $headStyle.html(cssText);
+ } catch (e) {
+ // fix for IE 6-8
+ $headStyle[0].styleSheet.cssText = cssText;
+ }
+ return $headStyle;
+ }
+
+ /* Calculate the CSS rules that indent title spans. */
+ function renderLevelCss(
+ containerId,
+ depth,
+ levelOfs,
+ lineOfs,
+ labelOfs,
+ measureUnit
+ ) {
+ var i,
+ prefix = "#" + containerId + " span.fancytree-level-",
+ rules = [];
+
+ for (i = 0; i < depth; i++) {
+ rules.push(
+ prefix +
+ (i + 1) +
+ " span.fancytree-title { padding-left: " +
+ (i * levelOfs + lineOfs) +
+ measureUnit +
+ "; }"
+ );
+ }
+ // Some UI animations wrap the UL inside a DIV and set position:relative on both.
+ // This breaks the left:0 and padding-left:nn settings of the title
+ rules.push(
+ "#" +
+ containerId +
+ " div.ui-effects-wrapper ul li span.fancytree-title, " +
+ "#" +
+ containerId +
+ " li.fancytree-animating span.fancytree-title " + // #716
+ "{ padding-left: " +
+ labelOfs +
+ measureUnit +
+ "; position: static; width: auto; }"
+ );
+ return rules.join("\n");
+ }
+
+ // /**
+ // * [ext-wide] Recalculate the width of the selection bar after the tree container
+ // * was resized.<br>
+ // * May be called explicitly on container resize, since there is no resize event
+ // * for DIV tags.
+ // *
+ // * @alias Fancytree#wideUpdate
+ // * @requires jquery.fancytree.wide.js
+ // */
+ // $.ui.fancytree._FancytreeClass.prototype.wideUpdate = function(){
+ // var inst = this.ext.wide,
+ // prevCw = inst.contWidth,
+ // prevLo = inst.lineOfs;
+
+ // inst.contWidth = realInnerWidth(this.$container);
+ // // Each title is precceeded by 2 or 3 icons (16px + 3 margin)
+ // // + 1px title border and 3px title padding
+ // // TODO: use code from treeInit() below
+ // inst.lineOfs = (this.options.checkbox ? 3 : 2) * 19;
+ // if( prevCw !== inst.contWidth || prevLo !== inst.lineOfs ) {
+ // this.debug("wideUpdate: " + inst.contWidth);
+ // this.visit(function(node){
+ // node.tree._callHook("nodeRenderTitle", node);
+ // });
+ // }
+ // };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "wide",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ iconWidth: null, // Adjust this if @fancy-icon-width != "16px"
+ iconSpacing: null, // Adjust this if @fancy-icon-spacing != "3px"
+ labelSpacing: null, // Adjust this if padding between icon and label != "3px"
+ levelOfs: null, // Adjust this if ul padding != "16px"
+ },
+
+ treeCreate: function (ctx) {
+ this._superApply(arguments);
+ this.$container.addClass("fancytree-ext-wide");
+
+ var containerId,
+ cssText,
+ iconSpacingUnit,
+ labelSpacingUnit,
+ iconWidthUnit,
+ levelOfsUnit,
+ instOpts = ctx.options.wide,
+ // css sniffing
+ $dummyLI = $(
+ "<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />"
+ ).appendTo(ctx.tree.$container),
+ $dummyIcon = $dummyLI.find(".fancytree-icon"),
+ $dummyUL = $dummyLI.find("ul"),
+ // $dummyTitle = $dummyLI.find(".fancytree-title"),
+ iconSpacing =
+ instOpts.iconSpacing || $dummyIcon.css("margin-left"),
+ iconWidth = instOpts.iconWidth || $dummyIcon.css("width"),
+ labelSpacing = instOpts.labelSpacing || "3px",
+ levelOfs = instOpts.levelOfs || $dummyUL.css("padding-left");
+
+ $dummyLI.remove();
+
+ iconSpacingUnit = iconSpacing.match(reNumUnit)[2];
+ iconSpacing = parseFloat(iconSpacing, 10);
+ labelSpacingUnit = labelSpacing.match(reNumUnit)[2];
+ labelSpacing = parseFloat(labelSpacing, 10);
+ iconWidthUnit = iconWidth.match(reNumUnit)[2];
+ iconWidth = parseFloat(iconWidth, 10);
+ levelOfsUnit = levelOfs.match(reNumUnit)[2];
+ if (
+ iconSpacingUnit !== iconWidthUnit ||
+ levelOfsUnit !== iconWidthUnit ||
+ labelSpacingUnit !== iconWidthUnit
+ ) {
+ $.error(
+ "iconWidth, iconSpacing, and levelOfs must have the same css measure unit"
+ );
+ }
+ this._local.measureUnit = iconWidthUnit;
+ this._local.levelOfs = parseFloat(levelOfs);
+ this._local.lineOfs =
+ (1 +
+ (ctx.options.checkbox ? 1 : 0) +
+ (ctx.options.icon === false ? 0 : 1)) *
+ (iconWidth + iconSpacing) +
+ iconSpacing;
+ this._local.labelOfs = labelSpacing;
+ this._local.maxDepth = 10;
+
+ // Get/Set a unique Id on the container (if not already exists)
+ containerId = this.$container.uniqueId().attr("id");
+ // Generated css rules for some levels (extended on demand)
+ cssText = renderLevelCss(
+ containerId,
+ this._local.maxDepth,
+ this._local.levelOfs,
+ this._local.lineOfs,
+ this._local.labelOfs,
+ this._local.measureUnit
+ );
+ defineHeadStyleElement(containerId, cssText);
+ },
+ treeDestroy: function (ctx) {
+ // Remove generated css rules
+ defineHeadStyleElement(this.$container.attr("id"), null);
+ return this._superApply(arguments);
+ },
+ nodeRenderStatus: function (ctx) {
+ var containerId,
+ cssText,
+ res,
+ node = ctx.node,
+ level = node.getLevel();
+
+ res = this._super(ctx);
+ // Generate some more level-n rules if required
+ if (level > this._local.maxDepth) {
+ containerId = this.$container.attr("id");
+ this._local.maxDepth *= 2;
+ node.debug(
+ "Define global ext-wide css up to level " +
+ this._local.maxDepth
+ );
+ cssText = renderLevelCss(
+ containerId,
+ this._local.maxDepth,
+ this._local.levelOfs,
+ this._local.lineOfs,
+ this._local.labelSpacing,
+ this._local.measureUnit
+ );
+ defineHeadStyleElement(containerId, cssText);
+ }
+ // Add level-n class to apply indentation padding.
+ // (Setting element style would not work, since it cannot easily be
+ // overriden while animations run)
+ $(node.span).addClass("fancytree-level-" + level);
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+// Value returned by `require('jquery.fancytree')`
+return $.ui.fancytree;
+})); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.min.js b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.min.js
new file mode 100644
index 0000000..c3749d3
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.min.js
@@ -0,0 +1,2 @@
+!function(_){_.ui=_.ui||{};_.ui.version="1.13.2";var r,n=0,s=Array.prototype.hasOwnProperty,a=Array.prototype.slice;_.cleanData=(r=_.cleanData,function(e){for(var t,n,i=0;null!=(n=e[i]);i++)(t=_._data(n,"events"))&&t.remove&&_(n).triggerHandler("remove");r(e)}),_.widget=function(e,n,t){var i,r,o,s={},a=e.split(".")[0],l=a+"-"+(e=e.split(".")[1]);return t||(t=n,n=_.Widget),Array.isArray(t)&&(t=_.extend.apply(null,[{}].concat(t))),_.expr.pseudos[l.toLowerCase()]=function(e){return!!_.data(e,l)},_[a]=_[a]||{},i=_[a][e],r=_[a][e]=function(e,t){if(!this||!this._createWidget)return new r(e,t);arguments.length&&this._createWidget(e,t)},_.extend(r,i,{version:t.version,_proto:_.extend({},t),_childConstructors:[]}),(o=new n).options=_.widget.extend({},o.options),_.each(t,function(t,i){function r(){return n.prototype[t].apply(this,arguments)}function o(e){return n.prototype[t].apply(this,e)}s[t]="function"==typeof i?function(){var e,t=this._super,n=this._superApply;return this._super=r,this._superApply=o,e=i.apply(this,arguments),this._super=t,this._superApply=n,e}:i}),r.prototype=_.widget.extend(o,{widgetEventPrefix:i&&o.widgetEventPrefix||e},s,{constructor:r,namespace:a,widgetName:e,widgetFullName:l}),i?(_.each(i._childConstructors,function(e,t){var n=t.prototype;_.widget(n.namespace+"."+n.widgetName,r,t._proto)}),delete i._childConstructors):n._childConstructors.push(r),_.widget.bridge(e,r),r},_.widget.extend=function(e){for(var t,n,i=a.call(arguments,1),r=0,o=i.length;r<o;r++)for(t in i[r])n=i[r][t],s.call(i[r],t)&&void 0!==n&&(_.isPlainObject(n)?e[t]=_.isPlainObject(e[t])?_.widget.extend({},e[t],n):_.widget.extend({},n):e[t]=n);return e},_.widget.bridge=function(o,t){var s=t.prototype.widgetFullName||o;_.fn[o]=function(n){var e="string"==typeof n,i=a.call(arguments,1),r=this;return e?this.length||"instance"!==n?this.each(function(){var e,t=_.data(this,s);return"instance"===n?(r=t,!1):t?"function"!=typeof t[n]||"_"===n.charAt(0)?_.error("no such method '"+n+"' for "+o+" widget instance"):(e=t[n].apply(t,i))!==t&&void 0!==e?(r=e&&e.jquery?r.pushStack(e.get()):e,!1):void 0:_.error("cannot call methods on "+o+" prior to initialization; attempted to call method '"+n+"'")}):r=void 0:(i.length&&(n=_.widget.extend.apply(null,[n].concat(i))),this.each(function(){var e=_.data(this,s);e?(e.option(n||{}),e._init&&e._init()):_.data(this,s,new t(n,this))})),r}},_.Widget=function(){},_.Widget._childConstructors=[],_.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,t){t=_(t||this.defaultElement||this)[0],this.element=_(t),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=_(),this.hoverable=_(),this.focusable=_(),this.classesElementLookup={},t!==this&&(_.data(t,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===t&&this.destroy()}}),this.document=_(t.style?t.ownerDocument:t.document||t),this.window=_(this.document[0].defaultView||this.document[0].parentWindow)),this.options=_.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:_.noop,_create:_.noop,_init:_.noop,destroy:function(){var n=this;this._destroy(),_.each(this.classesElementLookup,function(e,t){n._removeClass(t,e)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:_.noop,widget:function(){return this.element},option:function(e,t){var n,i,r,o=e;if(0===arguments.length)return _.widget.extend({},this.options);if("string"==typeof e)if(o={},e=(n=e.split(".")).shift(),n.length){for(i=o[e]=_.widget.extend({},this.options[e]),r=0;r<n.length-1;r++)i[n[r]]=i[n[r]]||{},i=i[n[r]];if(e=n.pop(),1===arguments.length)return void 0===i[e]?null:i[e];i[e]=t}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];o[e]=t}return this._setOptions(o),this},_setOptions:function(e){for(var t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return"classes"===e&&this._setOptionClasses(t),this.options[e]=t,"disabled"===e&&this._setOptionDisabled(t),this},_setOptionClasses:function(e){var t,n,i;for(t in e)i=this.classesElementLookup[t],e[t]!==this.options.classes[t]&&i&&i.length&&(n=_(i.get()),this._removeClass(i,t),n.addClass(this._classes({element:n,keys:t,classes:e,add:!0})))},_setOptionDisabled:function(e){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!e),e&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(r){var o=[],s=this;function e(e,t){for(var n,i=0;i<e.length;i++)n=s.classesElementLookup[e[i]]||_(),n=r.add?(function(){var n=[];r.element.each(function(e,t){_.map(s.classesElementLookup,function(e){return e}).some(function(e){return e.is(t)})||n.push(t)}),s._on(_(n),{remove:"_untrackClassesElement"})}(),_(_.uniqueSort(n.get().concat(r.element.get())))):_(n.not(r.element).get()),s.classesElementLookup[e[i]]=n,o.push(e[i]),t&&r.classes[e[i]]&&o.push(r.classes[e[i]])}return(r=_.extend({element:this.element,classes:this.options.classes||{}},r)).keys&&e(r.keys.match(/\S+/g)||[],!0),r.extra&&e(r.extra.match(/\S+/g)||[]),o.join(" ")},_untrackClassesElement:function(n){var i=this;_.each(i.classesElementLookup,function(e,t){-1!==_.inArray(n.target,t)&&(i.classesElementLookup[e]=_(t.not(n.target).get()))}),this._off(_(n.target))},_removeClass:function(e,t,n){return this._toggleClass(e,t,n,!1)},_addClass:function(e,t,n){return this._toggleClass(e,t,n,!0)},_toggleClass:function(e,t,n,i){var r="string"==typeof e||null===e,n={extra:r?t:n,keys:r?e:t,element:r?this.element:e,add:i="boolean"==typeof i?i:n};return n.element.toggleClass(this._classes(n),i),this},_on:function(r,o,e){var s,a=this;"boolean"!=typeof r&&(e=o,o=r,r=!1),e?(o=s=_(o),this.bindings=this.bindings.add(o)):(e=o,o=this.element,s=this.widget()),_.each(e,function(e,t){function n(){if(r||!0!==a.options.disabled&&!_(this).hasClass("ui-state-disabled"))return("string"==typeof t?a[t]:t).apply(a,arguments)}"string"!=typeof t&&(n.guid=t.guid=t.guid||n.guid||_.guid++);var i=e.match(/^([\w:-]*)\s*(.*)$/),e=i[1]+a.eventNamespace,i=i[2];i?s.on(e,i,n):o.on(e,n)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(t),this.bindings=_(this.bindings.not(e).get()),this.focusable=_(this.focusable.not(e).get()),this.hoverable=_(this.hoverable.not(e).get())},_delay:function(e,t){var n=this;return setTimeout(function(){return("string"==typeof e?n[e]:e).apply(n,arguments)},t||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(_(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(_(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(_(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(_(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,t,n){var i,r,o=this.options[e];if(n=n||{},(t=_.Event(t)).type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),t.target=this.element[0],r=t.originalEvent)for(i in r)i in t||(t[i]=r[i]);return this.element.trigger(t,n),!("function"==typeof o&&!1===o.apply(this.element[0],[t].concat(n))||t.isDefaultPrevented())}},_.each({show:"fadeIn",hide:"fadeOut"},function(o,s){_.Widget.prototype["_"+o]=function(t,e,n){var i,r=(e="string"==typeof e?{effect:e}:e)?!0!==e&&"number"!=typeof e&&e.effect||s:o;"number"==typeof(e=e||{})?e={duration:e}:!0===e&&(e={}),i=!_.isEmptyObject(e),e.complete=n,e.delay&&t.delay(e.delay),i&&_.effects&&_.effects.effect[r]?t[o](e):r!==o&&t[r]?t[r](e.duration,e.easing,n):t.queue(function(e){_(this)[o](),n&&n.call(t[0]),e()})}});var i,k,w,o,l,d,c,u,N;_.widget;function S(e,t,n){return[parseFloat(e[0])*(u.test(e[0])?t/100:1),parseFloat(e[1])*(u.test(e[1])?n/100:1)]}function E(e,t){return parseInt(_.css(e,t),10)||0}function T(e){return null!=e&&e===e.window}k=Math.max,w=Math.abs,o=/left|center|right/,l=/top|center|bottom/,d=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,N=_.fn.position,_.position={scrollbarWidth:function(){if(void 0!==i)return i;var e,t=_("<div style='display:block;position:absolute;width:200px;height:200px;overflow:hidden;'><div style='height:300px;width:auto;'></div></div>"),n=t.children()[0];return _("body").append(t),e=n.offsetWidth,t.css("overflow","scroll"),e===(n=n.offsetWidth)&&(n=t[0].clientWidth),t.remove(),i=e-n},getScrollInfo:function(e){var t=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),n=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),t="scroll"===t||"auto"===t&&e.width<e.element[0].scrollWidth;return{width:"scroll"===n||"auto"===n&&e.height<e.element[0].scrollHeight?_.position.scrollbarWidth():0,height:t?_.position.scrollbarWidth():0}},getWithinInfo:function(e){var t=_(e||window),n=T(t[0]),i=!!t[0]&&9===t[0].nodeType;return{element:t,isWindow:n,isDocument:i,offset:!n&&!i?_(e).offset():{left:0,top:0},scrollLeft:t.scrollLeft(),scrollTop:t.scrollTop(),width:t.outerWidth(),height:t.outerHeight()}}},_.fn.position=function(u){if(!u||!u.of)return N.apply(this,arguments);var h,f,p,g,y,e,v="string"==typeof(u=_.extend({},u)).of?_(document).find(u.of):_(u.of),m=_.position.getWithinInfo(u.within),b=_.position.getScrollInfo(m),x=(u.collision||"flip").split(" "),C={},t=9===(e=(t=v)[0]).nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:T(e)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:e.preventDefault?{width:0,height:0,offset:{top:e.pageY,left:e.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()};return v[0].preventDefault&&(u.at="left top"),f=t.width,p=t.height,y=_.extend({},g=t.offset),_.each(["my","at"],function(){var e,t,n=(u[this]||"").split(" ");(n=1===n.length?o.test(n[0])?n.concat(["center"]):l.test(n[0])?["center"].concat(n):["center","center"]:n)[0]=o.test(n[0])?n[0]:"center",n[1]=l.test(n[1])?n[1]:"center",e=d.exec(n[0]),t=d.exec(n[1]),C[this]=[e?e[0]:0,t?t[0]:0],u[this]=[c.exec(n[0])[0],c.exec(n[1])[0]]}),1===x.length&&(x[1]=x[0]),"right"===u.at[0]?y.left+=f:"center"===u.at[0]&&(y.left+=f/2),"bottom"===u.at[1]?y.top+=p:"center"===u.at[1]&&(y.top+=p/2),h=S(C.at,f,p),y.left+=h[0],y.top+=h[1],this.each(function(){var n,e,s=_(this),a=s.outerWidth(),l=s.outerHeight(),t=E(this,"marginLeft"),i=E(this,"marginTop"),r=a+t+E(this,"marginRight")+b.width,o=l+i+E(this,"marginBottom")+b.height,d=_.extend({},y),c=S(C.my,s.outerWidth(),s.outerHeight());"right"===u.my[0]?d.left-=a:"center"===u.my[0]&&(d.left-=a/2),"bottom"===u.my[1]?d.top-=l:"center"===u.my[1]&&(d.top-=l/2),d.left+=c[0],d.top+=c[1],n={marginLeft:t,marginTop:i},_.each(["left","top"],function(e,t){_.ui.position[x[e]]&&_.ui.position[x[e]][t](d,{targetWidth:f,targetHeight:p,elemWidth:a,elemHeight:l,collisionPosition:n,collisionWidth:r,collisionHeight:o,offset:[h[0]+c[0],h[1]+c[1]],my:u.my,at:u.at,within:m,elem:s})}),u.using&&(e=function(e){var t=g.left-d.left,n=t+f-a,i=g.top-d.top,r=i+p-l,o={target:{element:v,left:g.left,top:g.top,width:f,height:p},element:{element:s,left:d.left,top:d.top,width:a,height:l},horizontal:n<0?"left":0<t?"right":"center",vertical:r<0?"top":0<i?"bottom":"middle"};f<a&&w(t+n)<f&&(o.horizontal="center"),p<l&&w(i+r)<p&&(o.vertical="middle"),k(w(t),w(n))>k(w(i),w(r))?o.important="horizontal":o.important="vertical",u.using.call(this,e,o)}),s.offset(_.extend(d,{using:e}))})},_.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,r=n.width,o=e.left-t.collisionPosition.marginLeft,s=i-o,a=o+t.collisionWidth-r-i;t.collisionWidth>r?0<s&&a<=0?(n=e.left+s+t.collisionWidth-r-i,e.left+=s-n):e.left=!(0<a&&s<=0)&&a<s?i+r-t.collisionWidth:i:0<s?e.left+=s:0<a?e.left-=a:e.left=k(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,r=t.within.height,o=e.top-t.collisionPosition.marginTop,s=i-o,a=o+t.collisionHeight-r-i;t.collisionHeight>r?0<s&&a<=0?(n=e.top+s+t.collisionHeight-r-i,e.top+=s-n):e.top=!(0<a&&s<=0)&&a<s?i+r-t.collisionHeight:i:0<s?e.top+=s:0<a?e.top-=a:e.top=k(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,i=n.offset.left+n.scrollLeft,r=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,s=e.left-t.collisionPosition.marginLeft,a=s-o,l=s+t.collisionWidth-r-o,d="left"===t.my[0]?-t.elemWidth:"right"===t.my[0]?t.elemWidth:0,n="left"===t.at[0]?t.targetWidth:"right"===t.at[0]?-t.targetWidth:0,s=-2*t.offset[0];a<0?((i=e.left+d+n+s+t.collisionWidth-r-i)<0||i<w(a))&&(e.left+=d+n+s):0<l&&(0<(o=e.left-t.collisionPosition.marginLeft+d+n+s-o)||w(o)<l)&&(e.left+=d+n+s)},top:function(e,t){var n=t.within,i=n.offset.top+n.scrollTop,r=n.height,o=n.isWindow?n.scrollTop:n.offset.top,s=e.top-t.collisionPosition.marginTop,a=s-o,l=s+t.collisionHeight-r-o,d="top"===t.my[1]?-t.elemHeight:"bottom"===t.my[1]?t.elemHeight:0,n="top"===t.at[1]?t.targetHeight:"bottom"===t.at[1]?-t.targetHeight:0,s=-2*t.offset[1];a<0?((i=e.top+d+n+s+t.collisionHeight-r-i)<0||i<w(a))&&(e.top+=d+n+s):0<l&&(0<(o=e.top-t.collisionPosition.marginTop+d+n+s-o)||w(o)<l)&&(e.top+=d+n+s)}},flipfit:{left:function(){_.ui.position.flip.left.apply(this,arguments),_.ui.position.fit.left.apply(this,arguments)},top:function(){_.ui.position.flip.top.apply(this,arguments),_.ui.position.fit.top.apply(this,arguments)}}};var t,h;_.ui.position;_.expr.pseudos||(_.expr.pseudos=_.expr[":"]),_.uniqueSort||(_.uniqueSort=_.unique),_.escapeSelector||(t=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,h=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},_.escapeSelector=function(e){return(e+"").replace(t,h)}),_.fn.even&&_.fn.odd||_.fn.extend({even:function(){return this.filter(function(e){return e%2==0})},odd:function(){return this.filter(function(e){return e%2==1})}});var e;_.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},_.fn.scrollParent=function(e){var t=this.css("position"),n="absolute"===t,i=e?/(auto|scroll|hidden)/:/(auto|scroll)/,e=this.parents().filter(function(){var e=_(this);return(!n||"static"!==e.css("position"))&&i.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==t&&e.length?e:_(this[0].ownerDocument||document)},_.fn.extend({uniqueId:(e=0,function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&_(this).removeAttr("id")})}})}(jQuery),function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=e(require("jquery")):e(jQuery)}(function(e){var t;return t=function(C){"use strict";if(!C.ui||!C.ui.fancytree){for(var e,h=null,c=new RegExp(/\.|\//),t=/[&<>"'/]/g,n=/[<>"'/]/g,f="$recursive_request",p="$request_target_invalid",i={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;"},r={16:!0,17:!0,18:!0},u={8:"backspace",9:"tab",10:"return",13:"return",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",59:";",61:"=",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},g={16:"shift",17:"ctrl",18:"alt",91:"meta",93:"meta"},o={0:"",1:"left",2:"middle",3:"right"},y="active expanded focus folder lazy radiogroup selected unselectable unselectableIgnore".split(" "),v={},m="columns types".split(" "),b="checkbox expanded extraClasses folder icon iconTooltip key lazy partsel radiogroup refKey selected statusNodeType title tooltip type unselectable unselectableIgnore unselectableStatus".split(" "),s={},x={},a={active:!0,children:!0,data:!0,focus:!0},l=0;l<y.length;l++)v[y[l]]=!0;for(l=0;l<b.length;l++)e=b[l],s[e]=!0,e!==e.toLowerCase()&&(x[e.toLowerCase()]=e);var _=Array.isArray;return k(C.ui,"Fancytree requires jQuery UI (http://jqueryui.com)"),Date.now||(Date.now=function(){return(new Date).getTime()}),j.prototype={_findDirectChild:function(e){var t,n,i=this.children;if(i)if("string"==typeof e){for(t=0,n=i.length;t<n;t++)if(i[t].key===e)return i[t]}else{if("number"==typeof e)return this.children[e];if(e.parent===this)return e}return null},_setChildren:function(e){k(e&&(!this.children||0===this.children.length),"only init supported"),this.children=[];for(var t=0,n=e.length;t<n;t++)this.children.push(new j(this,e[t]));this.tree._callHook("treeStructureChanged",this.tree,"setChildren")},addChildren:function(e,t){var n,i,r,o,s=this.getFirstChild(),a=this.getLastChild(),l=[];for(C.isPlainObject(e)&&(e=[e]),this.children||(this.children=[]),n=0,i=e.length;n<i;n++)l.push(new j(this,e[n]));if(o=l[0],null==t?this.children=this.children.concat(l):(t=this._findDirectChild(t),k(0<=(r=C.inArray(t,this.children)),"insertBefore must be an existing child"),this.children.splice.apply(this.children,[r,0].concat(l))),s&&!t){for(n=0,i=l.length;n<i;n++)l[n].render();s!==this.getFirstChild()&&s.renderStatus(),a!==this.getLastChild()&&a.renderStatus()}else this.parent&&!this.parent.ul&&!this.tr||this.render();return 3===this.tree.options.selectMode&&this.fixSelection3FromEndNodes(),this.triggerModifyChild("add",1===l.length?l[0]:null),o},addClass:function(e){return this.toggleClass(e,!0)},addNode:function(e,t){switch(t=void 0===t||"over"===t?"child":t){case"after":return this.getParent().addChildren(e,this.getNextSibling());case"before":return this.getParent().addChildren(e,this);case"firstChild":var n=this.children?this.children[0]:null;return this.addChildren(e,n);case"child":case"over":return this.addChildren(e)}k(!1,"Invalid mode: "+t)},addPagingNode:function(e,t){var n,i;if(t=t||"child",!1!==e)return e=C.extend({title:this.tree.options.strings.moreData,statusNodeType:"paging",icon:!1},e),this.partload=!0,this.addNode(e,t);for(n=this.children.length-1;0<=n;n--)"paging"===(i=this.children[n]).statusNodeType&&this.removeChild(i);this.partload=!1},appendSibling:function(e){return this.addNode(e,"after")},applyCommand:function(e,t){return this.tree.applyCommand(e,this,t)},applyPatch:function(e){if(null===e)return this.remove(),T(this);var t,n,i={children:!0,expanded:!0,parent:!0};for(t in e)w(e,t)&&(n=e[t],i[t]||N(n)||(s[t]?this[t]=n:this.data[t]=n));return w(e,"children")&&(this.removeChildren(),e.children&&this._setChildren(e.children)),this.isVisible()&&(this.renderTitle(),this.renderStatus()),w(e,"expanded")?this.setExpanded(e.expanded):T(this)},collapseSiblings:function(){return this.tree._callHook("nodeCollapseSiblings",this)},copyTo:function(e,t,n){return e.addNode(this.toDict(!0,n),t)},countChildren:function(e){var t,n,i,r=this.children;if(!r)return 0;if(i=r.length,!1!==e)for(t=0,n=i;t<n;t++)i+=r[t].countChildren();return i},debug:function(e){4<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("log",arguments))},discard:function(){return this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."),this.resetLazy()},discardMarkup:function(e){this.tree._callHook(e?"nodeRemoveMarkup":"nodeRemoveChildMarkup",this)},error:function(e){1<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("error",arguments))},findAll:function(t){t=N(t)?t:L(t);var n=[];return this.visit(function(e){t(e)&&n.push(e)}),n},findFirst:function(t){t=N(t)?t:L(t);var n=null;return this.visit(function(e){if(t(e))return n=e,!1}),n},findRelatedNode:function(e,t){return this.tree.findRelatedNode(this,e,t)},_changeSelectStatusAttrs:function(e){var t=!1,n=this.tree.options,i=h.evalOption("unselectable",this,this,n,!1),n=h.evalOption("unselectableStatus",this,this,n,void 0);switch(e=i&&null!=n?n:e){case!1:t=this.selected||this.partsel,this.selected=!1,this.partsel=!1;break;case!0:t=!this.selected||!this.partsel,this.selected=!0,this.partsel=!0;break;case void 0:t=this.selected||!this.partsel,this.selected=!1,this.partsel=!0;break;default:k(!1,"invalid state: "+e)}return t&&this.renderStatus(),t},fixSelection3AfterClick:function(e){var t=this.isSelected();this.visit(function(e){if(e._changeSelectStatusAttrs(t),e.radiogroup)return"skip"}),this.fixSelection3FromEndNodes(e)},fixSelection3FromEndNodes:function(e){var u=this.tree.options;k(3===u.selectMode,"expected selectMode 3"),function e(t){var n,i,r,o,s,a,l,d,c=t.children;if(c&&c.length){for(l=!(a=!0),n=0,i=c.length;n<i;n++)o=e(r=c[n]),h.evalOption("unselectableIgnore",r,r,u,!1)||(!1!==o&&(l=!0),!0!==o&&(a=!1));s=!!a||!!l&&void 0}else s=null==(d=h.evalOption("unselectableStatus",t,t,u,void 0))?!!t.selected:!!d;return t.partsel&&!t.selected&&t.lazy&&null==t.children&&(s=void 0),t._changeSelectStatusAttrs(s),s}(this),this.visitParents(function(e){for(var t,n,i,r=e.children,o=!0,s=!1,a=0,l=r.length;a<l;a++)t=r[a],h.evalOption("unselectableIgnore",t,t,u,!1)||(((n=null==(i=h.evalOption("unselectableStatus",t,t,u,void 0))?!!t.selected:!!i)||t.partsel)&&(s=!0),n||(o=!1));e._changeSelectStatusAttrs(n=!!o||!!s&&void 0)})},fromDict:function(e){for(var t in e)s[t]?this[t]=e[t]:"data"===t?C.extend(this.data,e.data):N(e[t])||a[t]||(this.data[t]=e[t]);e.children&&(this.removeChildren(),this.addChildren(e.children)),this.renderTitle()},getChildren:function(){if(void 0!==this.hasChildren())return this.children},getFirstChild:function(){return this.children?this.children[0]:null},getIndex:function(){return C.inArray(this,this.parent.children)},getIndexHier:function(e,n){e=e||".";var i,r=[];return C.each(this.getParentList(!1,!0),function(e,t){i=""+(t.getIndex()+1),n&&(i=("0000000"+i).substr(-n)),r.push(i)}),r.join(e)},getKeyPath:function(e){var t=this.tree.options.keyPathSeparator;return t+this.getPath(!e,"key",t)},getLastChild:function(){return this.children?this.children[this.children.length-1]:null},getLevel:function(){for(var e=0,t=this.parent;t;)e++,t=t.parent;return e},getNextSibling:function(){if(this.parent)for(var e=this.parent.children,t=0,n=e.length-1;t<n;t++)if(e[t]===this)return e[t+1];return null},getParent:function(){return this.parent},getParentList:function(e,t){for(var n=[],i=t?this:this.parent;i;)(e||i.parent)&&n.unshift(i),i=i.parent;return n},getPath:function(e,t,n){n=n||"/";var i,r=[],o=N(t=t||"title");return this.visitParents(function(e){e.parent&&(i=o?t(e):e[t],r.unshift(i))},e=!1!==e),r.join(n)},getPrevSibling:function(){if(this.parent)for(var e=this.parent.children,t=1,n=e.length;t<n;t++)if(e[t]===this)return e[t-1];return null},getSelectedNodes:function(t){var n=[];return this.visit(function(e){if(e.selected&&(n.push(e),!0===t))return"skip"}),n},hasChildren:function(){return this.lazy?null==this.children?void 0:0!==this.children.length&&(1!==this.children.length||!this.children[0].isStatusNode()||void 0):!(!this.children||!this.children.length)},hasClass:function(e){return 0<=(" "+(this.extraClasses||"")+" ").indexOf(" "+e+" ")},hasFocus:function(){return this.tree.hasFocus()&&this.tree.focusNode===this},info:function(e){3<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("info",arguments))},isActive:function(){return this.tree.activeNode===this},isBelowOf:function(e){return this.getIndexHier(".",5)>e.getIndexHier(".",5)},isChildOf:function(e){return this.parent&&this.parent===e},isDescendantOf:function(e){if(!e||e.tree!==this.tree)return!1;for(var t=this.parent;t;){if(t===e)return!0;t===t.parent&&C.error("Recursive parent link: "+t),t=t.parent}return!1},isExpanded:function(){return!!this.expanded},isFirstSibling:function(){var e=this.parent;return!e||e.children[0]===this},isFolder:function(){return!!this.folder},isLastSibling:function(){var e=this.parent;return!e||e.children[e.children.length-1]===this},isLazy:function(){return!!this.lazy},isLoaded:function(){return!this.lazy||void 0!==this.hasChildren()},isLoading:function(){return!!this._isLoading},isRoot:function(){return this.isRootNode()},isPartsel:function(){return!this.selected&&!!this.partsel},isPartload:function(){return!!this.partload},isRootNode:function(){return this.tree.rootNode===this},isSelected:function(){return!!this.selected},isStatusNode:function(){return!!this.statusNodeType},isPagingNode:function(){return"paging"===this.statusNodeType},isTopLevel:function(){return this.tree.rootNode===this.parent},isUndefined:function(){return void 0===this.hasChildren()},isVisible:function(){var e,t,n=this.tree.enableFilter,i=this.getParentList(!1,!1);if(n&&!this.match&&!this.subMatchCount)return!1;for(e=0,t=i.length;e<t;e++)if(!i[e].expanded)return!1;return!0},lazyLoad:function(e){C.error("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead.")},load:function(e){var t=this,n=this.isExpanded();return k(this.isLazy(),"load() requires a lazy node"),e||this.isUndefined()?(this.isLoaded()&&this.resetLazy(),!1===(e=this.tree._triggerNodeEvent("lazyLoad",this))?T(this):(k("boolean"!=typeof e,"lazyLoad event must return source in data.result"),e=this.tree._callHook("nodeLoadChildren",this,e),n?(this.expanded=!0,e.always(function(){t.render()})):e.always(function(){t.renderStatus()}),e)):T(this)},makeVisible:function(e){for(var t=this,n=[],i=new C.Deferred,r=this.getParentList(!1,!1),o=r.length,s=!(e&&!0===e.noAnimation),a=!(e&&!1===e.scrollIntoView),l=o-1;0<=l;l--)n.push(r[l].setExpanded(!0,e));return C.when.apply(C,n).done(function(){a?t.scrollIntoView(s).done(function(){i.resolve()}):i.resolve()}),i.promise()},moveTo:function(t,e,n){void 0===e||"over"===e?e="child":"firstChild"===e&&(t.children&&t.children.length?(e="before",t=t.children[0]):e="child");var i,r=this.tree,o=this.parent,s="child"===e?t:t.parent;if(this!==t){if(this.parent?s.isDescendantOf(this)&&C.error("Cannot move a node to its own descendant"):C.error("Cannot move system root"),s!==o&&o.triggerModifyChild("remove",this),1===this.parent.children.length){if(this.parent===s)return;this.parent.children=this.parent.lazy?[]:null,this.parent.expanded=!1}else k(0<=(i=C.inArray(this,this.parent.children)),"invalid source parent"),this.parent.children.splice(i,1);if((this.parent=s).hasChildren())switch(e){case"child":s.children.push(this);break;case"before":k(0<=(i=C.inArray(t,s.children)),"invalid target parent"),s.children.splice(i,0,this);break;case"after":k(0<=(i=C.inArray(t,s.children)),"invalid target parent"),s.children.splice(i+1,0,this);break;default:C.error("Invalid mode "+e)}else s.children=[this];n&&t.visit(n,!0),s===o?s.triggerModifyChild("move",this):s.triggerModifyChild("add",this),r!==t.tree&&(this.warn("Cross-tree moveTo is experimental!"),this.visit(function(e){e.tree=t.tree},!0)),r._callHook("treeStructureChanged",r,"moveTo"),o.isDescendantOf(s)||o.render(),s.isDescendantOf(o)||s===o||s.render()}},navigate:function(e,t){var n=C.ui.keyCode;switch(e){case"left":case n.LEFT:if(this.expanded)return this.setExpanded(!1);break;case"right":case n.RIGHT:if(!this.expanded&&(this.children||this.lazy))return this.setExpanded()}if(n=this.findRelatedNode(e)){try{n.makeVisible({scrollIntoView:!1})}catch(e){}return!1===t?(n.setFocus(),T()):n.setActive()}return this.warn("Could not find related node '"+e+"'."),T()},remove:function(){return this.parent.removeChild(this)},removeChild:function(e){return this.tree._callHook("nodeRemoveChild",this,e)},removeChildren:function(){return this.tree._callHook("nodeRemoveChildren",this)},removeClass:function(e){return this.toggleClass(e,!1)},render:function(e,t){return this.tree._callHook("nodeRender",this,e,t)},renderTitle:function(){return this.tree._callHook("nodeRenderTitle",this)},renderStatus:function(){return this.tree._callHook("nodeRenderStatus",this)},replaceWith:function(e){var n=this.parent,i=C.inArray(this,n.children),r=this;return k(this.isPagingNode(),"replaceWith() currently requires a paging status node"),(e=this.tree._callHook("nodeLoadChildren",this,e)).done(function(e){var t=r.children;for(l=0;l<t.length;l++)t[l].parent=n;n.children.splice.apply(n.children,[i+1,0].concat(t)),r.children=null,r.remove(),n.render()}).fail(function(){r.setExpanded()}),e},resetLazy:function(){this.removeChildren(),this.expanded=!1,this.lazy=!0,this.children=void 0,this.renderStatus()},scheduleAction:function(e,t){this.tree.timer&&(clearTimeout(this.tree.timer),this.tree.debug("clearTimeout(%o)",this.tree.timer)),this.tree.timer=null;var n=this;switch(e){case"cancel":break;case"expand":this.tree.timer=setTimeout(function(){n.tree.debug("setTimeout: trigger expand"),n.setExpanded(!0)},t);break;case"activate":this.tree.timer=setTimeout(function(){n.tree.debug("setTimeout: trigger activate"),n.setActive(!0)},t);break;default:C.error("Invalid mode "+e)}},scrollIntoView:function(e,t){if(void 0!==t&&((p=t).tree&&void 0!==p.statusNodeType))throw Error("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead.");var n=C.extend({effects:!0===e?{duration:200,queue:!1}:e,scrollOfs:this.tree.options.scrollOfs,scrollParent:this.tree.options.scrollParent,topNode:null},t),i=n.scrollParent,r=this.tree.$container,o=r.css("overflow-y");i?i.jquery||(i=C(i)):i=!this.tree.tbody&&("scroll"===o||"auto"===o)?r:r.scrollParent(),i[0]!==document&&i[0]!==document.body||(this.debug("scrollIntoView(): normalizing scrollParent to 'window':",i[0]),i=C(window));var s,a,l=new C.Deferred,d=this,c=C(this.span).height(),u=n.scrollOfs.top||0,h=n.scrollOfs.bottom||0,f=i.height(),p=i.scrollTop(),e=i,t=i[0]===window,o=n.topNode||null,r=null;return this.isRootNode()||!this.isVisible()?(this.info("scrollIntoView(): node is invisible."),T()):(t?(a=C(this.span).offset().top,s=o&&o.span?C(o.span).offset().top:0,e=C("html,body")):(k(i[0]!==document&&i[0]!==document.body,"scrollParent should be a simple element or `window`, not document or body."),t=i.offset().top,a=C(this.span).offset().top-t+p,s=o?C(o.span).offset().top-t+p:0,f-=Math.max(0,i.innerHeight()-i[0].clientHeight)),a<p+u?r=a-u:p+f-h<a+c&&(r=a+c-f+h,o&&(k(o.isRootNode()||o.isVisible(),"topNode must be visible"),s<r&&(r=s-u))),null===r?l.resolveWith(this):n.effects?(n.effects.complete=function(){l.resolveWith(d)},e.stop(!0).animate({scrollTop:r},n.effects)):(e[0].scrollTop=r,l.resolveWith(this)),l.promise())},setActive:function(e,t){return this.tree._callHook("nodeSetActive",this,e,t)},setExpanded:function(e,t){return this.tree._callHook("nodeSetExpanded",this,e,t)},setFocus:function(e){return this.tree._callHook("nodeSetFocus",this,e)},setSelected:function(e,t){return this.tree._callHook("nodeSetSelected",this,e,t)},setStatus:function(e,t,n){return this.tree._callHook("nodeSetStatus",this,e,t,n)},setTitle:function(e){this.title=e,this.renderTitle(),this.triggerModify("rename")},sortChildren:function(e,t){var n,i,r=this.children;if(r){if(r.sort(e=e||function(e,t){e=e.title.toLowerCase(),t=t.title.toLowerCase();return e===t?0:t<e?1:-1}),t)for(n=0,i=r.length;n<i;n++)r[n].children&&r[n].sortChildren(e,"$norender$");"$norender$"!==t&&this.render(),this.triggerModifyChild("sort")}},toDict:function(e,t){var n,i,r,o,s={},a=this;if(C.each(b,function(e,t){!a[t]&&!1!==a[t]||(s[t]=a[t])}),C.isEmptyObject(this.data)||(s.data=C.extend({},this.data),C.isEmptyObject(s.data)&&delete s.data),t){if(!1===(o=t(s,a)))return!1;"skip"===o&&(e=!1)}if(e&&_(this.children))for(s.children=[],n=0,i=this.children.length;n<i;n++)(r=this.children[n]).isStatusNode()||!1!==(o=r.toDict(!0,t))&&s.children.push(o);return s},toggleClass:function(e,t){var n,i,r=e.match(/\S+/g)||[],o=0,s=!1,a=this[this.tree.statusClassPropName],l=" "+(this.extraClasses||"")+" ";for(a&&C(a).toggleClass(e,t);n=r[o++];)if(i=0<=l.indexOf(" "+n+" "),t=void 0===t?!i:!!t)i||(l+=n+" ",s=!0);else for(;-1<l.indexOf(" "+n+" ");)l=l.replace(" "+n+" "," ");return this.extraClasses=S(l),s},toggleExpanded:function(){return this.tree._callHook("nodeToggleExpanded",this)},toggleSelected:function(){return this.tree._callHook("nodeToggleSelected",this)},toString:function(){return"FancytreeNode@"+this.key+"[title='"+this.title+"']"},triggerModifyChild:function(e,t,n){var i=this.tree.options.modifyChild;i&&(t&&t.parent!==this&&C.error("childNode "+t+" is not a child of "+this),t={node:this,tree:this.tree,operation:e,childNode:t||null},n&&C.extend(t,n),i({type:"modifyChild"},t))},triggerModify:function(e,t){this.parent.triggerModifyChild(e,this,t)},visit:function(e,t){var n,i,r=!0,o=this.children;if(!0===t&&(!1===(r=e(this))||"skip"===r))return r;if(o)for(n=0,i=o.length;n<i&&!1!==(r=o[n].visit(e,!0));n++);return r},visitAndLoad:function(n,e,t){var i,r,o,s=this;return!n||!0!==e||!1!==(r=n(s))&&"skip"!==r?s.children||s.lazy?(i=new C.Deferred,o=[],s.load().done(function(){for(var e=0,t=s.children.length;e<t;e++){if(!1===(r=s.children[e].visitAndLoad(n,!0,!0))){i.reject();break}"skip"!==r&&o.push(r)}C.when.apply(this,o).then(function(){i.resolve()})}),i.promise()):T():t?r:T()},visitParents:function(e,t){if(t&&!1===e(this))return!1;for(var n=this.parent;n;){if(!1===e(n))return!1;n=n.parent}return!0},visitSiblings:function(e,t){for(var n,i=this.parent.children,r=0,o=i.length;r<o;r++)if(n=i[r],(t||n!==this)&&!1===e(n))return!1;return!0},warn:function(e){2<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("warn",arguments))}},F.prototype={_makeHookContext:function(e,t,n){var i,r;return void 0!==e.node?(t&&e.originalEvent!==t&&C.error("invalid args"),i=e):e.tree?i={node:e,tree:r=e.tree,widget:r.widget,options:r.widget.options,originalEvent:t,typeInfo:r.types[e.type]||{}}:e.widget?i={node:null,tree:e,widget:e.widget,options:e.widget.options,originalEvent:t}:C.error("invalid args"),n&&C.extend(i,n),i},_callHook:function(e,t,n){var i=this._makeHookContext(t),r=this[e],t=Array.prototype.slice.call(arguments,2);return N(r)||C.error("_callHook('"+e+"') is not a function"),t.unshift(i),r.apply(this,t)},_setExpiringValue:function(e,t,n){this._tempCache[e]={value:t,expire:Date.now()+(+n||50)}},_getExpiringValue:function(e){var t=this._tempCache[e];return t&&t.expire>Date.now()?t.value:(delete this._tempCache[e],null)},_usesExtension:function(e){return 0<=C.inArray(e,this.options.extensions)},_requireExtension:function(e,t,n,i){null!=n&&(n=!!n);var r=this._local.name,o=this.options.extensions,s=C.inArray(e,o)<C.inArray(r,o),o=t&&null==this.ext[e],s=!o&&null!=n&&n!==s;return k(r&&r!==e,"invalid or same name '"+r+"' (require yourself?)"),!o&&!s||(i||(o||t?(i="'"+r+"' extension requires '"+e+"'",s&&(i+=" to be registered "+(n?"before":"after")+" itself")):i="If used together, `"+e+"` must be registered "+(n?"before":"after")+" `"+r+"`"),C.error(i),!1)},activateKey:function(e,t){e=this.getNodeByKey(e);return e?e.setActive(!0,t):this.activeNode&&this.activeNode.setActive(!1,t),e},addPagingNode:function(e,t){return this.rootNode.addPagingNode(e,t)},applyCommand:function(e,t,n){var i;switch(t=t||this.getActiveNode(),e){case"moveUp":(i=t.getPrevSibling())&&(t.moveTo(i,"before"),t.setActive());break;case"moveDown":(i=t.getNextSibling())&&(t.moveTo(i,"after"),t.setActive());break;case"indent":(i=t.getPrevSibling())&&(t.moveTo(i,"child"),i.setExpanded(),t.setActive());break;case"outdent":t.isTopLevel()||(t.moveTo(t.getParent(),"after"),t.setActive());break;case"remove":i=t.getPrevSibling()||t.getParent(),t.remove(),i&&i.setActive();break;case"addChild":t.editCreateNode("child","");break;case"addSibling":t.editCreateNode("after","");break;case"rename":t.editStart();break;case"down":case"first":case"last":case"left":case"parent":case"right":case"up":return t.navigate(e);default:C.error("Unhandled command: '"+e+"'")}},applyPatch:function(e){for(var t,n,i,r,o=e.length,s=[],a=0;a<o;a++)k(2===(t=e[a]).length,"patchList must be an array of length-2-arrays"),n=t[0],i=t[1],(r=null===n?this.rootNode:this.getNodeByKey(n))?(t=new C.Deferred,s.push(t),r.applyPatch(i).always(O(t,r))):this.warn("could not find node with key '"+n+"'");return C.when.apply(C,s).promise()},clear:function(e){this._callHook("treeClear",this)},count:function(){return this.rootNode.countChildren()},debug:function(e){4<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("log",arguments))},destroy:function(){this.widget.destroy()},enable:function(e){!1===e?this.widget.disable():this.widget.enable()},enableUpdate:function(e){return!!this._enableUpdate==!!(e=!1!==e)?e:((this._enableUpdate=e)?(this.debug("enableUpdate(true): redraw "),this._callHook("treeStructureChanged",this,"enableUpdate"),this.render()):this.debug("enableUpdate(false)..."),!e)},error:function(e){1<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("error",arguments))},expandAll:function(t,n){var e=this.enableUpdate(!1);t=!1!==t,this.visit(function(e){!1!==e.hasChildren()&&e.isExpanded()!==t&&e.setExpanded(t,n)}),this.enableUpdate(e)},findAll:function(e){return this.rootNode.findAll(e)},findFirst:function(e){return this.rootNode.findFirst(e)},findNextNode:function(t,n){var i,r=null,e=this.getFirstChild();function o(e){if((r=t(e)?e:r)||e===n)return!1}return t="string"==typeof t?(i=new RegExp("^"+t,"i"),function(e){return i.test(e.title)}):t,this.visitRows(o,{start:n=n||e,includeSelf:!1}),r||n===e||this.visitRows(o,{start:e,includeSelf:!0}),r},findRelatedNode:function(e,t,n){var i=null,r=C.ui.keyCode;switch(t){case"parent":case r.BACKSPACE:e.parent&&e.parent.parent&&(i=e.parent);break;case"first":case r.HOME:this.visit(function(e){if(e.isVisible())return i=e,!1});break;case"last":case r.END:this.visit(function(e){e.isVisible()&&(i=e)});break;case"left":case r.LEFT:e.expanded?e.setExpanded(!1):e.parent&&e.parent.parent&&(i=e.parent);break;case"right":case r.RIGHT:e.expanded||!e.children&&!e.lazy?e.children&&e.children.length&&(i=e.children[0]):(e.setExpanded(),i=e);break;case"up":case r.UP:this.visitRows(function(e){return i=e,!1},{start:e,reverse:!0,includeSelf:!1});break;case"down":case r.DOWN:this.visitRows(function(e){return i=e,!1},{start:e,includeSelf:!1});break;default:this.tree.warn("Unknown relation '"+t+"'.")}return i},generateFormElements:function(e,t,n){n=n||{};var i="string"==typeof e?e:"ft_"+this._id+"[]",r="string"==typeof t?t:"ft_"+this._id+"_active",o="fancytree_result_"+this._id,s=C("#"+o),a=3===this.options.selectMode&&!1!==n.stopOnParents;function l(e){s.append(C("<input>",{type:"checkbox",name:i,value:e.key,checked:!0}))}s.length?s.empty():s=C("<div>",{id:o}).hide().insertAfter(this.$container),!1!==t&&this.activeNode&&s.append(C("<input>",{type:"radio",name:r,value:this.activeNode.key,checked:!0})),n.filter?this.visit(function(e){var t=n.filter(e);if("skip"===t)return t;!1!==t&&l(e)}):!1!==e&&(a=this.getSelectedNodes(a),C.each(a,function(e,t){l(t)}))},getActiveNode:function(){return this.activeNode},getFirstChild:function(){return this.rootNode.getFirstChild()},getFocusNode:function(){return this.focusNode},getOption:function(e){return this.widget.option(e)},getNodeByKey:function(t,e){var n,i;return!e&&(n=document.getElementById(this.options.idPrefix+t))?n.ftnode||null:(e=e||this.rootNode,t=""+t,e.visit(function(e){if(e.key===t)return i=e,!1},!(i=null)),i)},getRootNode:function(){return this.rootNode},getSelectedNodes:function(e){return this.rootNode.getSelectedNodes(e)},hasFocus:function(){return!!this._hasFocus},info:function(e){3<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("info",arguments))},isLoading:function(){var t=!1;return this.rootNode.visit(function(e){if(e._isLoading||e._requestId)return!(t=!0)},!0),t},loadKeyPath:function(e,t){var i,n,r,o=this,s=new C.Deferred,a=this.getRootNode(),l=this.options.keyPathSeparator,d=[],c=C.extend({},t);for("function"==typeof t?i=t:t&&t.callback&&(i=t.callback),c.callback=function(e,t,n){i&&i.call(e,t,n),s.notifyWith(e,[{node:t,status:n}])},null==c.matchKey&&(c.matchKey=function(e,t){return e.key===t}),_(e)||(e=[e]),n=0;n<e.length;n++)(r=e[n]).charAt(0)===l&&(r=r.substr(1)),d.push(r.split(l));return setTimeout(function(){o._loadKeyPathImpl(s,c,a,d).done(function(){s.resolve()})},0),s.promise()},_loadKeyPathImpl:function(e,o,t,n){var i,r,s,a,l,d,c,u,h,f,p=this;for(c={},r=0;r<n.length;r++)for(h=n[r],u=t;h.length;){if(s=h.shift(),!(a=function(e,t){var n,i,r=e.children;if(r)for(n=0,i=r.length;n<i;n++)if(o.matchKey(r[n],t))return r[n];return null}(u,s))){this.warn("loadKeyPath: key not found: "+s+" (parent: "+u+")"),o.callback(this,s,"error");break}if(0===h.length){o.callback(this,a,"ok");break}if(a.lazy&&void 0===a.hasChildren()){o.callback(this,a,"loaded"),c[s=a.key]?c[s].pathSegList.push(h):c[s]={parent:a,pathSegList:[h]};break}o.callback(this,a,"loaded"),u=a}for(l in i=[],c)w(c,l)&&(d=c[l],f=new C.Deferred,i.push(f),function(t,n,e){o.callback(p,n,"loading"),n.load().done(function(){p._loadKeyPathImpl.call(p,t,o,n,e).always(O(t,p))}).fail(function(e){p.warn("loadKeyPath: error loading lazy "+n),o.callback(p,a,"error"),t.rejectWith(p)})}(f,d.parent,d.pathSegList));return C.when.apply(C,i).promise()},reactivate:function(e){var t,n=this.activeNode;return n?(this.activeNode=null,t=n.setActive(!0,{noFocus:!0}),e&&n.setFocus(),t):T()},reload:function(e){return this._callHook("treeClear",this),this._callHook("treeLoad",this,e)},render:function(e,t){return this.rootNode.render(e,t)},selectAll:function(t){this.visit(function(e){e.setSelected(t)})},setFocus:function(e){return this._callHook("treeSetFocus",this,e)},setOption:function(e,t){return this.widget.option(e,t)},debugTime:function(e){4<=this.options.debugLevel&&window.console.time(this+" - "+e)},debugTimeEnd:function(e){4<=this.options.debugLevel&&window.console.timeEnd(this+" - "+e)},toDict:function(e,t){t=this.rootNode.toDict(!0,t);return e?t:t.children},toString:function(){return"Fancytree@"+this._id},_triggerNodeEvent:function(e,t,n,i){i=this._makeHookContext(t,n,i),n=this.widget._trigger(e,n,i);return!1!==n&&void 0!==i.result?i.result:n},_triggerTreeEvent:function(e,t,n){n=this._makeHookContext(this,t,n),t=this.widget._trigger(e,t,n);return!1!==t&&void 0!==n.result?n.result:t},visit:function(e){return this.rootNode.visit(e,!1)},visitRows:function(t,e){if(!this.rootNode.hasChildren())return!1;if(e&&e.reverse)return delete e.reverse,this._visitRowsUp(t,e);for(var n,i,r,o=0,s=!1===(e=e||{}).includeSelf,a=!!e.includeHidden,l=!a&&this.enableFilter,d=e.start||this.rootNode.children[0],c=d.parent;c;){for(k(0<=(i=(r=c.children).indexOf(d)+o),"Could not find "+d+" in parent's children: "+c),n=i;n<r.length;n++)if(d=r[n],!l||d.match||d.subMatchCount){if(!s&&!1===t(d))return!1;if(s=!1,d.children&&d.children.length&&(a||d.expanded)&&!1===d.visit(function(e){return!l||e.match||e.subMatchCount?!1!==t(e)&&(a||!e.children||e.expanded?void 0:"skip"):"skip"},!1))return!1}c=(d=c).parent,o=1}return!0},_visitRowsUp:function(e,t){for(var n,i,r,o=!!t.includeHidden,s=t.start||this.rootNode.children[0];;){if((n=(r=s.parent).children)[0]===s){if(!(s=r).parent)break;n=r.children}else for(i=n.indexOf(s),s=n[i-1];(o||s.expanded)&&s.children&&s.children.length;)s=(n=(r=s).children)[n.length-1];if((o||s.isVisible())&&!1===e(s))return!1}},warn:function(e){2<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("warn",arguments))}},C.extend(F.prototype,{nodeClick:function(e){var t,n,i=e.targetType,r=e.node;if("expander"===i)r.isLoading()?r.debug("Got 2nd click while loading: ignored"):this._callHook("nodeToggleExpanded",e);else if("checkbox"===i)this._callHook("nodeToggleSelected",e),e.options.focusOnSelect&&this._callHook("nodeSetFocus",e,!0);else{if(t=!(n=!1),r.folder)switch(e.options.clickFolderMode){case 2:t=!(n=!0);break;case 3:n=t=!0}t&&(this.nodeSetFocus(e),this._callHook("nodeSetActive",e,!0)),n&&this._callHook("nodeToggleExpanded",e)}},nodeCollapseSiblings:function(e,t){var n,i,r,o=e.node;if(o.parent)for(i=0,r=(n=o.parent.children).length;i<r;i++)n[i]!==o&&n[i].expanded&&this._callHook("nodeSetExpanded",n[i],!1,t)},nodeDblclick:function(e){"title"===e.targetType&&4===e.options.clickFolderMode&&this._callHook("nodeToggleExpanded",e),"title"===e.targetType&&e.originalEvent.preventDefault()},nodeKeydown:function(e){var t=e.originalEvent,n=e.node,i=e.tree,r=e.options,o=t.which,s=t.key||String.fromCharCode(o),a=!!(t.altKey||t.ctrlKey||t.metaKey),l=!g[o]&&!u[o]&&!a,o=C(t.target),d=!0,c=!(t.ctrlKey||!r.autoActivate);if(n||(a=this.getActiveNode()||this.getFirstChild())&&(a.setFocus(),(n=e.node=this.focusNode).debug("Keydown force focus on active node")),r.quicksearch&&l&&!o.is(":input:enabled"))return 500<(o=Date.now())-i.lastQuicksearchTime&&(i.lastQuicksearchTerm=""),i.lastQuicksearchTime=o,i.lastQuicksearchTerm+=s,(s=i.findNextNode(i.lastQuicksearchTerm,i.getActiveNode()))&&s.setActive(),void t.preventDefault();switch(h.eventToString(t)){case"+":case"=":i.nodeSetExpanded(e,!0);break;case"-":i.nodeSetExpanded(e,!1);break;case"space":n.isPagingNode()?i._triggerNodeEvent("clickPaging",e,t):h.evalOption("checkbox",n,n,r,!1)?i.nodeToggleSelected(e):i.nodeSetActive(e,!0);break;case"return":i.nodeSetActive(e,!0);break;case"home":case"end":case"backspace":case"left":case"right":case"up":case"down":n.navigate(t.which,c);break;default:d=!1}d&&t.preventDefault()},nodeLoadChildren:function(o,s){var t,n,a,e=null,i=!0,l=o.tree,d=o.node,c=d.parent,r="nodeLoadChildren",u=Date.now();return N(s)&&k(!N(s=s.call(l,{type:"source"},o)),"source callback must not return another function"),N(s.then)?e=s:s.url?e=(t=C.extend({},o.options.ajax,s)).debugDelay?(n=t.debugDelay,delete t.debugDelay,_(n)&&(n=n[0]+Math.random()*(n[1]-n[0])),d.warn("nodeLoadChildren waiting debugDelay "+Math.round(n)+" ms ..."),C.Deferred(function(e){setTimeout(function(){C.ajax(t).done(function(){e.resolveWith(this,arguments)}).fail(function(){e.rejectWith(this,arguments)})},n)})):C.ajax(t):C.isPlainObject(s)||_(s)?i=!(e={then:function(e,t){e(s,null,null)}}):C.error("Invalid source type: "+s),d._requestId&&(d.warn("Recursive load request #"+u+" while #"+d._requestId+" is pending."),d._requestId=u),i&&(l.debugTime(r),l.nodeSetStatus(o,"loading")),a=new C.Deferred,e.then(function(e,t,n){var i,r;if("json"!==s.dataType&&"jsonp"!==s.dataType||"string"!=typeof e||C.error("Ajax request returned a string (did you get the JSON dataType wrong?)."),d._requestId&&d._requestId>u)a.rejectWith(this,[f]);else if(null!==d.parent||null===c){if(o.options.postProcess){try{(r=l._triggerNodeEvent("postProcess",o,o.originalEvent,{response:e,error:null,dataType:s.dataType})).error&&l.warn("postProcess returned error:",r)}catch(e){r={error:e,message:""+e,details:"postProcess failed"}}if(r.error)return i=C.isPlainObject(r.error)?r.error:{message:r.error},i=l._makeHookContext(d,null,i),void a.rejectWith(this,[i]);(_(r)||C.isPlainObject(r)&&_(r.children))&&(e=r)}else e&&w(e,"d")&&o.options.enableAspx&&(42===o.options.enableAspx&&l.warn("The default for enableAspx will change to `false` in the fututure. Pass `enableAspx: true` or implement postProcess to silence this warning."),e="string"==typeof e.d?C.parseJSON(e.d):e.d);a.resolveWith(this,[e])}else a.rejectWith(this,[p])},function(e,t,n){n=l._makeHookContext(d,null,{error:e,args:Array.prototype.slice.call(arguments),message:n,details:e.status+": "+n});a.rejectWith(this,[n])}),a.done(function(e){var t,n,i;l.nodeSetStatus(o,"ok"),C.isPlainObject(e)?(k(d.isRootNode(),"source may only be an object for root nodes (expecting an array of child objects otherwise)"),k(_(e.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),t=(n=e).children,delete n.children,C.each(m,function(e,t){void 0!==n[t]&&(l[t]=n[t],delete n[t])}),C.extend(l.data,n)):t=e,k(_(t),"expected array of children"),d._setChildren(t),l.options.nodata&&0===t.length&&(N(l.options.nodata)?i=l.options.nodata.call(l,{type:"nodata"},o):!0===l.options.nodata&&d.isRootNode()?i=l.options.strings.noData:"string"==typeof l.options.nodata&&d.isRootNode()&&(i=l.options.nodata),i&&d.setStatus("nodata",i)),l._triggerNodeEvent("loadChildren",d)}).fail(function(e){var t;e!==f?e!==p?(e.node&&e.error&&e.message?t=e:"[object Object]"===(t=l._makeHookContext(d,null,{error:e,args:Array.prototype.slice.call(arguments),message:e?e.message||e.toString():""})).message&&(t.message=""),d.warn("Load children failed ("+t.message+")",t),!1!==l._triggerNodeEvent("loadError",t,null)&&l.nodeSetStatus(o,"error",t.message,t.details)):d.warn("Lazy parent node was removed while loading: discarding response."):d.warn("Ignored response for obsolete load request #"+u+" (expected #"+d._requestId+")")}).always(function(){d._requestId=null,i&&l.debugTimeEnd(r)}),a.promise()},nodeLoadKeyPath:function(e,t){},nodeRemoveChild:function(e,t){var n=e.node,i=C.extend({},e,{node:t}),r=n.children;if(1===r.length)return k(t===r[0],"invalid single child"),this.nodeRemoveChildren(e);this.activeNode&&(t===this.activeNode||this.activeNode.isDescendantOf(t))&&this.activeNode.setActive(!1),this.focusNode&&(t===this.focusNode||this.focusNode.isDescendantOf(t))&&(this.focusNode=null),this.nodeRemoveMarkup(i),this.nodeRemoveChildren(i),k(0<=(i=C.inArray(t,r)),"invalid child"),n.triggerModifyChild("remove",t),t.visit(function(e){e.parent=null},!0),this._callHook("treeRegisterNode",this,!1,t),r.splice(i,1)},nodeRemoveChildMarkup:function(e){e=e.node;e.ul&&(e.isRootNode()?C(e.ul).empty():(C(e.ul).remove(),e.ul=null),e.visit(function(e){e.li=e.ul=null}))},nodeRemoveChildren:function(e){var t=e.tree,n=e.node;n.children&&(this.activeNode&&this.activeNode.isDescendantOf(n)&&this.activeNode.setActive(!1),this.focusNode&&this.focusNode.isDescendantOf(n)&&(this.focusNode=null),this.nodeRemoveChildMarkup(e),n.triggerModifyChild("remove",null),n.visit(function(e){e.parent=null,t._callHook("treeRegisterNode",t,!1,e)}),n.lazy?n.children=[]:n.children=null,n.isRootNode()||(n.expanded=!1),this.nodeRenderStatus(e))},nodeRemoveMarkup:function(e){var t=e.node;t.li&&(C(t.li).remove(),t.li=null),this.nodeRemoveChildMarkup(e)},nodeRender:function(e,t,n,i,r){var o,s,a,l,d,c,u,h=e.node,f=e.tree,p=e.options,g=p.aria,y=!1,v=h.parent,m=!v,b=h.children,x=null;if(!1!==f._enableUpdate&&(m||v.ul)){if(k(m||v.ul,"parent UL must exist"),m||(h.li&&(t||h.li.parentNode!==h.parent.ul)&&(h.li.parentNode===h.parent.ul?x=h.li.nextSibling:this.debug("Unlinking "+h+" (must be child of "+h.parent+")"),this.nodeRemoveMarkup(e)),h.li?this.nodeRenderStatus(e):(y=!0,h.li=document.createElement("li"),(h.li.ftnode=h).key&&p.generateIds&&(h.li.id=p.idPrefix+h.key),h.span=document.createElement("span"),h.span.className="fancytree-node",g&&!h.tr&&C(h.li).attr("role","treeitem"),h.li.appendChild(h.span),this.nodeRenderTitle(e),p.createNode&&p.createNode.call(f,{type:"createNode"},e)),p.renderNode&&p.renderNode.call(f,{type:"renderNode"},e)),b){if(m||h.expanded||!0===n){for(h.ul||(h.ul=document.createElement("ul"),(!0!==i||r)&&h.expanded||(h.ul.style.display="none"),g&&C(h.ul).attr("role","group"),h.li?h.li.appendChild(h.ul):h.tree.$div.append(h.ul)),l=0,d=b.length;l<d;l++)u=C.extend({},e,{node:b[l]}),this.nodeRender(u,t,n,!1,!0);for(o=h.ul.firstChild;o;)o=(a=o.ftnode)&&a.parent!==h?(h.debug("_fixParent: remove missing "+a,o),c=o.nextSibling,o.parentNode.removeChild(o),c):o.nextSibling;for(o=h.ul.firstChild,l=0,d=b.length-1;l<d;l++)(s=b[l])===(a=o.ftnode)?o=o.nextSibling:h.ul.insertBefore(s.li,a.li)}}else h.ul&&(this.warn("remove child markup for "+h),this.nodeRemoveChildMarkup(e));m||y&&v.ul.insertBefore(h.li,x)}},nodeRenderTitle:function(e,t){var n,i,r=e.node,o=e.tree,s=e.options,a=s.aria,l=r.getLevel(),d=[];void 0!==t&&(r.title=t),r.span&&!1!==o._enableUpdate&&(t=a&&!1!==r.hasChildren()?" role='button'":"",l<s.minExpandLevel?(r.lazy||(r.expanded=!0),1<l&&d.push("<span "+t+" class='fancytree-expander fancytree-expander-fixed'></span>")):d.push("<span "+t+" class='fancytree-expander'></span>"),(l=h.evalOption("checkbox",r,r,s,!1))&&!r.isStatusNode()&&(n="fancytree-checkbox",("radio"===l||r.parent&&r.parent.radiogroup)&&(n+=" fancytree-radio"),d.push("<span "+(t=a?" role='checkbox'":"")+" class='"+n+"'></span>")),void 0!==r.data.iconClass&&(r.icon?C.error("'iconClass' node option is deprecated since v2.14.0: use 'icon' only instead"):(r.warn("'iconClass' node option is deprecated since v2.14.0: use 'icon' instead"),r.icon=r.data.iconClass)),!1!==(n=h.evalOption("icon",r,r,s,!0))&&(t=a?" role='presentation'":"",i=(i=h.evalOption("iconTooltip",r,r,s,null))?" title='"+D(i)+"'":"","string"==typeof n?c.test(n)?(n="/"===n.charAt(0)?n:(s.imagePath||"")+n,d.push("<img src='"+n+"' class='fancytree-icon'"+i+" alt='' />")):d.push("<span "+t+" class='fancytree-custom-icon "+n+"'"+i+"></span>"):n.text?d.push("<span "+t+" class='fancytree-custom-icon "+(n.addClass||"")+"'"+i+">"+h.escapeHtml(n.text)+"</span>"):n.html?d.push("<span "+t+" class='fancytree-custom-icon "+(n.addClass||"")+"'"+i+">"+n.html+"</span>"):d.push("<span "+t+" class='fancytree-icon'"+i+"></span>")),t="",t=(t=s.renderTitle?s.renderTitle.call(o,{type:"renderTitle"},e)||"":t)||"<span class='fancytree-title'"+(i=(i=!0===(i=h.evalOption("tooltip",r,r,s,null))?r.title:i)?" title='"+D(i)+"'":"")+(s.titlesTabbable?" tabindex='0'":"")+">"+(s.escapeTitles?h.escapeHtml(r.title):r.title)+"</span>",d.push(t),r.span.innerHTML=d.join(""),this.nodeRenderStatus(e),s.enhanceTitle&&(e.$title=C(">span.fancytree-title",r.span),t=s.enhanceTitle.call(o,{type:"enhanceTitle"},e)||""))},nodeRenderStatus:function(e){var t,n=e.node,i=e.tree,r=e.options,o=n.hasChildren(),s=n.isLastSibling(),a=r.aria,l=r._classNames,d=[],e=n[i.statusClassPropName];e&&!1!==i._enableUpdate&&(a&&(t=C(n.tr||n.li)),d.push(l.node),i.activeNode===n&&d.push(l.active),i.focusNode===n&&d.push(l.focused),n.expanded&&d.push(l.expanded),a&&(!1===o?t.removeAttr("aria-expanded"):t.attr("aria-expanded",Boolean(n.expanded))),n.folder&&d.push(l.folder),!1!==o&&d.push(l.hasChildren),s&&d.push(l.lastsib),n.lazy&&null==n.children&&d.push(l.lazy),n.partload&&d.push(l.partload),n.partsel&&d.push(l.partsel),h.evalOption("unselectable",n,n,r,!1)&&d.push(l.unselectable),n._isLoading&&d.push(l.loading),n._error&&d.push(l.error),n.statusNodeType&&d.push(l.statusNodePrefix+n.statusNodeType),n.selected?(d.push(l.selected),a&&t.attr("aria-selected",!0)):a&&t.attr("aria-selected",!1),n.extraClasses&&d.push(n.extraClasses),!1===o?d.push(l.combinedExpanderPrefix+"n"+(s?"l":"")):d.push(l.combinedExpanderPrefix+(n.expanded?"e":"c")+(n.lazy&&null==n.children?"d":"")+(s?"l":"")),d.push(l.combinedIconPrefix+(n.expanded?"e":"c")+(n.folder?"f":"")),e.className=d.join(" "),n.li&&C(n.li).toggleClass(l.lastsib,s))},nodeSetActive:function(e,t,n){var i=e.node,r=e.tree,o=e.options,s=!0===(n=n||{}).noEvents,a=!0===n.noFocus,n=!1!==n.scrollIntoView;return i===r.activeNode===(t=!1!==t)?T(i):(n&&e.originalEvent&&C(e.originalEvent.target).is("a,:checkbox")&&(i.info("Not scrolling while clicking an embedded link."),n=!1),t&&!s&&!1===this._triggerNodeEvent("beforeActivate",i,e.originalEvent)?A(i,["rejected"]):(t?(r.activeNode&&(k(r.activeNode!==i,"node was active (inconsistency)"),t=C.extend({},e,{node:r.activeNode}),r.nodeSetActive(t,!1),k(null===r.activeNode,"deactivate was out of sync?")),o.activeVisible&&i.makeVisible({scrollIntoView:n}),r.activeNode=i,r.nodeRenderStatus(e),a||r.nodeSetFocus(e),s||r._triggerNodeEvent("activate",i,e.originalEvent)):(k(r.activeNode===i,"node was not active (inconsistency)"),r.activeNode=null,this.nodeRenderStatus(e),s||e.tree._triggerNodeEvent("deactivate",i,e.originalEvent)),T(i)))},nodeSetExpanded:function(i,r,e){var t,n,o,s,a,l,d=i.node,c=i.tree,u=i.options,h=!0===(e=e||{}).noAnimation,f=!0===e.noEvents;if(r=!1!==r,C(d.li).hasClass(u._classNames.animating))return d.warn("setExpanded("+r+") while animating: ignored."),A(d,["recursion"]);if(d.expanded&&r||!d.expanded&&!r)return T(d);if(r&&!d.lazy&&!d.hasChildren())return T(d);if(!r&&d.getLevel()<u.minExpandLevel)return A(d,["locked"]);if(!f&&!1===this._triggerNodeEvent("beforeExpand",d,i.originalEvent))return A(d,["rejected"]);if(h||d.isVisible()||(h=e.noAnimation=!0),n=new C.Deferred,r&&!d.expanded&&u.autoCollapse){a=d.getParentList(!1,!0),l=u.autoCollapse;try{for(u.autoCollapse=!1,o=0,s=a.length;o<s;o++)this._callHook("nodeCollapseSiblings",a[o],e)}finally{u.autoCollapse=l}}return n.done(function(){var e=d.getLastChild();r&&u.autoScroll&&!h&&e&&c._enableUpdate?e.scrollIntoView(!0,{topNode:d}).always(function(){f||i.tree._triggerNodeEvent(r?"expand":"collapse",i)}):f||i.tree._triggerNodeEvent(r?"expand":"collapse",i)}),t=function(e){var t=u._classNames,n=u.toggleEffect;if(d.expanded=r,c._callHook("treeStructureChanged",i,r?"expand":"collapse"),c._callHook("nodeRender",i,!1,!1,!0),d.ul)if("none"!==d.ul.style.display==!!d.expanded)d.warn("nodeSetExpanded: UL.style.display already set");else{if(n&&!h)return C(d.li).addClass(t.animating),void(N(C(d.ul)[n.effect])?C(d.ul)[n.effect]({duration:n.duration,always:function(){C(this).removeClass(t.animating),C(d.li).removeClass(t.animating),e()}}):(C(d.ul).stop(!0,!0),C(d.ul).parent().find(".ui-effects-placeholder").remove(),C(d.ul).toggle(n.effect,n.options,n.duration,function(){C(this).removeClass(t.animating),C(d.li).removeClass(t.animating),e()})));d.ul.style.display=d.expanded||!parent?"":"none"}e()},r&&d.lazy&&void 0===d.hasChildren()?d.load().done(function(){n.notifyWith&&n.notifyWith(d,["loaded"]),t(function(){n.resolveWith(d)})}).fail(function(e){t(function(){n.rejectWith(d,["load failed ("+e+")"])})}):t(function(){n.resolveWith(d)}),n.promise()},nodeSetFocus:function(e,t){var n,i=e.tree,r=e.node,o=i.options,s=!!e.originalEvent&&C(e.originalEvent.target).is(":input");if(t=!1!==t,i.focusNode){if(i.focusNode===r&&t)return;n=C.extend({},e,{node:i.focusNode}),i.focusNode=null,this._triggerNodeEvent("blur",n),this._callHook("nodeRenderStatus",n)}t&&(this.hasFocus()||(r.debug("nodeSetFocus: forcing container focus"),this._callHook("treeSetFocus",e,!0,{calledByNode:!0})),r.makeVisible({scrollIntoView:!1}),i.focusNode=r,o.titlesTabbable&&(s||C(r.span).find(".fancytree-title").focus()),o.aria&&C(i.$container).attr("aria-activedescendant",C(r.tr||r.li).uniqueId().attr("id")),this._triggerNodeEvent("focus",e),document.activeElement===i.$container.get(0)||1<=C(document.activeElement,i.$container).length||C(i.$container).focus(),o.autoScroll&&r.scrollIntoView(),this._callHook("nodeRenderStatus",e))},nodeSetSelected:function(e,t,n){var i=e.node,r=e.tree,o=e.options,s=!0===(n=n||{}).noEvents,a=i.parent;if(t=!1!==t,!h.evalOption("unselectable",i,i,o,!1))return i._lastSelectIntent=t,!!i.selected!==t||3===o.selectMode&&i.partsel&&!t?s||!1!==this._triggerNodeEvent("beforeSelect",i,e.originalEvent)?(t&&1===o.selectMode?(r.lastSelectedNode&&r.lastSelectedNode.setSelected(!1),i.selected=t):3!==o.selectMode||!a||a.radiogroup||i.radiogroup?a&&a.radiogroup?i.visitSiblings(function(e){e._changeSelectStatusAttrs(t&&e===i)},!0):i.selected=t:(i.selected=t,i.fixSelection3AfterClick(n)),this.nodeRenderStatus(e),r.lastSelectedNode=t?i:null,void(s||r._triggerNodeEvent("select",e))):!!i.selected:t},nodeSetStatus:function(i,e,t,n){var r=i.node,o=i.tree;function s(e,t){var n=r.children?r.children[0]:null;return n&&n.isStatusNode()?(C.extend(n,e),n.statusNodeType=t,o._callHook("nodeRenderTitle",n)):(r._setChildren([e]),o._callHook("treeStructureChanged",i,"setStatusNode"),r.children[0].statusNodeType=t,o.render()),r.children[0]}switch(e){case"ok":!function(){var e=r.children?r.children[0]:null;if(e&&e.isStatusNode()){try{r.ul&&(r.ul.removeChild(e.li),e.li=null)}catch(e){}1===r.children.length?r.children=[]:r.children.shift(),o._callHook("treeStructureChanged",i,"clearStatusNode")}}(),r._isLoading=!1,r._error=null,r.renderStatus();break;case"loading":r.parent||s({title:o.options.strings.loading+(t?" ("+t+")":""),checkbox:!1,tooltip:n},e),r._isLoading=!0,r._error=null,r.renderStatus();break;case"error":s({title:o.options.strings.loadError+(t?" ("+t+")":""),checkbox:!1,tooltip:n},e),r._isLoading=!1,r._error={message:t,details:n},r.renderStatus();break;case"nodata":s({title:t||o.options.strings.noData,checkbox:!1,tooltip:n},e),r._isLoading=!1,r._error=null,r.renderStatus();break;default:C.error("invalid node status "+e)}},nodeToggleExpanded:function(e){return this.nodeSetExpanded(e,!e.node.expanded)},nodeToggleSelected:function(e){var t=e.node,n=!t.selected;return t.partsel&&!t.selected&&!0===t._lastSelectIntent&&(t.selected=!(n=!1)),t._lastSelectIntent=n,this.nodeSetSelected(e,n)},treeClear:function(e){var t=e.tree;t.activeNode=null,t.focusNode=null,t.$div.find(">ul.fancytree-container").empty(),t.rootNode.children=null,t._callHook("treeStructureChanged",e,"clear")},treeCreate:function(e){},treeDestroy:function(e){this.$div.find(">ul.fancytree-container").remove(),this.$source&&this.$source.removeClass("fancytree-helper-hidden")},treeInit:function(e){var n=e.tree,i=n.options;n.$container.attr("tabindex",i.tabindex),C.each(m,function(e,t){void 0!==i[t]&&(n.info("Move option "+t+" to tree"),n[t]=i[t],delete i[t])}),i.checkboxAutoHide&&n.$container.addClass("fancytree-checkbox-auto-hide"),i.rtl?n.$container.attr("DIR","RTL").addClass("fancytree-rtl"):n.$container.removeAttr("DIR").removeClass("fancytree-rtl"),i.aria&&(n.$container.attr("role","tree"),1!==i.selectMode&&n.$container.attr("aria-multiselectable",!0)),this.treeLoad(e)},treeLoad:function(e,t){var n,i,r,o=e.tree,s=e.widget.element,a=C.extend({},e,{node:this.rootNode});if(o.rootNode.children&&this.treeClear(e),t=t||this.options.source)"string"==typeof t&&C.error("Not implemented");else switch(i=s.data("type")||"html"){case"html":(r=s.find(">ul").not(".fancytree-container").first()).length?(r.addClass("ui-fancytree-source fancytree-helper-hidden"),t=C.ui.fancytree.parseHtml(r),this.data=C.extend(this.data,P(r))):(h.warn("No `source` option was passed and container does not contain `<ul>`: assuming `source: []`."),t=[]);break;case"json":t=C.parseJSON(s.text()),s.contents().filter(function(){return 3===this.nodeType}).remove(),C.isPlainObject(t)&&(k(_(t.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),t=(n=t).children,delete n.children,C.each(m,function(e,t){void 0!==n[t]&&(o[t]=n[t],delete n[t])}),C.extend(o.data,n));break;default:C.error("Invalid data-type: "+i)}return o._triggerTreeEvent("preInit",null),this.nodeLoadChildren(a,t).done(function(){o._callHook("treeStructureChanged",e,"loadChildren"),o.render(),3===e.options.selectMode&&o.rootNode.fixSelection3FromEndNodes(),o.activeNode&&o.options.activeVisible&&o.activeNode.makeVisible(),o._triggerTreeEvent("init",null,{status:!0})}).fail(function(){o.render(),o._triggerTreeEvent("init",null,{status:!1})})},treeRegisterNode:function(e,t,n){e.tree._callHook("treeStructureChanged",e,t?"addNode":"removeNode")},treeSetFocus:function(e,t,n){var i;(t=!1!==t)!==this.hasFocus()&&(!(this._hasFocus=t)&&this.focusNode?this.focusNode.setFocus(!1):!t||n&&n.calledByNode||C(this.$container).focus(),this.$container.toggleClass("fancytree-treefocus",t),this._triggerTreeEvent(t?"focusTree":"blurTree"),t&&!this.activeNode&&(i=this._lastMousedownNode||this.getFirstChild())&&i.setFocus())},treeSetOption:function(e,t,n){var i=e.tree,r=!0,o=!1,s=!1;switch(t){case"aria":case"checkbox":case"icon":case"minExpandLevel":case"tabindex":s=o=!0;break;case"checkboxAutoHide":i.$container.toggleClass("fancytree-checkbox-auto-hide",!!n);break;case"escapeTitles":case"tooltip":s=!0;break;case"rtl":!1===n?i.$container.removeAttr("DIR").removeClass("fancytree-rtl"):i.$container.attr("DIR","RTL").addClass("fancytree-rtl"),s=!0;break;case"source":r=!1,i._callHook("treeLoad",i,n),s=!0}i.debug("set option "+t+"="+n+" <"+typeof n+">"),r&&(this.widget._super||C.Widget.prototype._setOption).call(this.widget,t,n),o&&i._callHook("treeCreate",i),s&&i.render(!0,!1)},treeStructureChanged:function(e,t){}}),C.widget("ui.fancytree",{options:{activeVisible:!0,ajax:{type:"GET",cache:!1,dataType:"json"},aria:!0,autoActivate:!0,autoCollapse:!1,autoScroll:!1,checkbox:!1,clickFolderMode:4,copyFunctionsToData:!1,debugLevel:null,disabled:!1,enableAspx:42,escapeTitles:!1,extensions:[],focusOnSelect:!1,generateIds:!1,icon:!0,idPrefix:"ft_",keyboard:!0,keyPathSeparator:"/",minExpandLevel:1,nodata:!0,quicksearch:!1,rtl:!1,scrollOfs:{top:0,bottom:0},scrollParent:null,selectMode:2,strings:{loading:"Loading...",loadError:"Load error!",moreData:"More...",noData:"No data."},tabindex:"0",titlesTabbable:!1,toggleEffect:{effect:"slideToggle",duration:200},tooltip:!1,treeId:null,_classNames:{active:"fancytree-active",animating:"fancytree-animating",combinedExpanderPrefix:"fancytree-exp-",combinedIconPrefix:"fancytree-ico-",error:"fancytree-error",expanded:"fancytree-expanded",focused:"fancytree-focused",folder:"fancytree-folder",hasChildren:"fancytree-has-children",lastsib:"fancytree-lastsib",lazy:"fancytree-lazy",loading:"fancytree-loading",node:"fancytree-node",partload:"fancytree-partload",partsel:"fancytree-partsel",radio:"fancytree-radio",selected:"fancytree-selected",statusNodePrefix:"fancytree-statusnode-",unselectable:"fancytree-unselectable"},lazyLoad:null,postProcess:null},_deprecationWarning:function(e){var t=this.tree;t&&3<=t.options.debugLevel&&t.warn("$().fancytree('"+e+"') is deprecated (see https://wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Widget.html")},_create:function(){this.tree=new F(this),this.$source=this.source||"json"===this.element.data("type")?this.element:this.element.find(">ul").first();for(var e,t,n=this.options,i=n.extensions,r=(this.tree,0);r<i.length;r++)t=i[r],(e=C.ui.fancytree._extensions[t])||C.error("Could not apply extension '"+t+"' (it is not registered, did you forget to include it?)"),this.tree.options[t]=function e(t){var n,i,r,o,s=t||{},a=1,l=arguments.length;if("object"==typeof s||N(s)||(s={}),a===l)throw Error("need at least two args");for(;a<l;a++)if(null!=(n=arguments[a]))for(i in n)w(n,i)&&(o=s[i],s!==(r=n[i])&&(r&&C.isPlainObject(r)?(o=o&&C.isPlainObject(o)?o:{},s[i]=e(o,r)):void 0!==r&&(s[i]=r)));return s}({},e.options,this.tree.options[t]),k(void 0===this.tree.ext[t],"Extension name must not exist as Fancytree.ext attribute: '"+t+"'"),this.tree.ext[t]={},function(e,t,n){for(var i in t)"function"==typeof t[i]?"function"==typeof e[i]?e[i]=E(i,e,0,t,n):"_"===i.charAt(0)?e.ext[n][i]=E(i,e,0,t,n):C.error("Could not override tree."+i+". Use prefix '_' to create tree."+n+"._"+i):"options"!==i&&(e.ext[n][i]=t[i])}(this.tree,e,t),0;void 0!==n.icons&&(!0===n.icon?(this.tree.warn("'icons' tree option is deprecated since v2.14.0: use 'icon' instead"),n.icon=n.icons):C.error("'icons' tree option is deprecated since v2.14.0: use 'icon' only instead")),void 0!==n.iconClass&&(n.icon?C.error("'iconClass' tree option is deprecated since v2.14.0: use 'icon' only instead"):(this.tree.warn("'iconClass' tree option is deprecated since v2.14.0: use 'icon' instead"),n.icon=n.iconClass)),void 0!==n.tabbable&&(n.tabindex=n.tabbable?"0":"-1",this.tree.warn("'tabbable' tree option is deprecated since v2.17.0: use 'tabindex='"+n.tabindex+"' instead")),this.tree._callHook("treeCreate",this.tree)},_init:function(){this.tree._callHook("treeInit",this.tree),this._bind()},_setOption:function(e,t){return this.tree._callHook("treeSetOption",this.tree,e,t)},_destroy:function(){this._unbind(),this.tree._callHook("treeDestroy",this.tree)},_unbind:function(){var e=this.tree._ns;this.element.off(e),this.tree.$container.off(e),C(document).off(e)},_bind:function(){var s=this,a=this.options,o=this.tree,e=o._ns;this._unbind(),o.$container.on("focusin"+e+" focusout"+e,function(e){var t=h.getNode(e),n="focusin"===e.type;if(!n&&t&&C(e.target).is("a"))t.debug("Ignored focusout on embedded <a> element.");else{if(n){if(o._getExpiringValue("focusin"))return void o.debug("Ignored double focusin.");o._setExpiringValue("focusin",!0,50),t||(t=o._getExpiringValue("mouseDownNode"))&&o.debug("Reconstruct mouse target for focusin from recent event.")}t?o._callHook("nodeSetFocus",o._makeHookContext(t,e),n):o.tbody&&C(e.target).parents("table.fancytree-container > thead").length?o.debug("Ignore focus event outside table body.",e):o._callHook("treeSetFocus",o,n)}}).on("selectstart"+e,"span.fancytree-title",function(e){e.preventDefault()}).on("keydown"+e,function(e){if(a.disabled||!1===a.keyboard)return!0;var t,n=o.focusNode,i=o._makeHookContext(n||o,e),r=o.phase;try{return o.phase="userEvent","preventNav"===(t=n?o._triggerNodeEvent("keydown",n,e):o._triggerTreeEvent("keydown",e))?t=!0:!1!==t&&(t=o._callHook("nodeKeydown",i)),t}finally{o.phase=r}}).on("mousedown"+e,function(e){e=h.getEventTarget(e);o._lastMousedownNode=e?e.node:null,o._setExpiringValue("mouseDownNode",o._lastMousedownNode)}).on("click"+e+" dblclick"+e,function(e){if(a.disabled)return!0;var t,n=h.getEventTarget(e),i=n.node,r=s.tree,o=r.phase;if(!i)return!0;t=r._makeHookContext(i,e);try{switch(r.phase="userEvent",e.type){case"click":return t.targetType=n.type,i.isPagingNode()?!0===r._triggerNodeEvent("clickPaging",t,e):!1!==r._triggerNodeEvent("click",t,e)&&r._callHook("nodeClick",t);case"dblclick":return t.targetType=n.type,!1!==r._triggerNodeEvent("dblclick",t,e)&&r._callHook("nodeDblclick",t)}}finally{r.phase=o}})},getActiveNode:function(){return this._deprecationWarning("getActiveNode"),this.tree.activeNode},getNodeByKey:function(e){return this._deprecationWarning("getNodeByKey"),this.tree.getNodeByKey(e)},getRootNode:function(){return this._deprecationWarning("getRootNode"),this.tree.rootNode},getTree:function(){return this._deprecationWarning("getTree"),this.tree}}),h=C.ui.fancytree,C.extend(C.ui.fancytree,{version:"2.38.3",buildType: "production",debugLevel: 3,_nextId:1,_nextNodeKey:1,_extensions:{},_FancytreeClass:F,_FancytreeNodeClass:j,jquerySupports:{positionMyOfs:function(e){for(var t,n,i=C.map(S(e).split("."),function(e){return parseInt(e,10)}),r=C.map(Array.prototype.slice.call(arguments,1),function(e){return parseInt(e,10)}),o=0;o<r.length;o++)if((t=i[o]||0)!==(n=r[o]||0))return n<t;return!0}(C.ui.version,1,9)},assert:k,createTree:function(e,t){t=C(e).fancytree(t);return h.getTree(t)},debounce:function(t,n,i,r){var o;return 3===arguments.length&&"boolean"!=typeof i&&(r=i,i=!1),function(){var e=arguments;r=r||this,i&&!o&&n.apply(r,e),clearTimeout(o),o=setTimeout(function(){i||n.apply(r,e),o=null},t)}},debug:function(e){4<=C.ui.fancytree.debugLevel&&d("log",arguments)},error:function(e){1<=C.ui.fancytree.debugLevel&&d("error",arguments)},escapeHtml:function(e){return(""+e).replace(t,function(e){return i[e]})},fixPositionOptions:function(e){var t,n,i,r;return(e.offset||0<=(""+e.my+e.at).indexOf("%"))&&C.error("expected new position syntax (but '%' is not supported)"),C.ui.fancytree.jquerySupports.positionMyOfs||(t=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(e.my),n=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(e.at),i=(t[2]?+t[2]:0)+(n[2]?+n[2]:0),r=(t[4]?+t[4]:0)+(n[4]?+n[4]:0),e=C.extend({},e,{my:t[1]+" "+t[3],at:n[1]+" "+n[3]}),(i||r)&&(e.offset=i+" "+r)),e},getEventTarget:function(e){var t=e&&e.target?e.target.className:"",n={node:this.getNode(e.target),type:void 0};return/\bfancytree-title\b/.test(t)?n.type="title":/\bfancytree-expander\b/.test(t)?n.type=!1===n.node.hasChildren()?"prefix":"expander":/\bfancytree-checkbox\b/.test(t)?n.type="checkbox":/\bfancytree(-custom)?-icon\b/.test(t)?n.type="icon":/\bfancytree-node\b/.test(t)?n.type="title":e&&e.target&&((e=C(e.target)).is("ul[role=group]")?((n.node&&n.node.tree||h).debug("Ignoring click on outer UL."),n.node=null):e.closest(".fancytree-title").length?n.type="title":e.closest(".fancytree-checkbox").length?n.type="checkbox":e.closest(".fancytree-expander").length&&(n.type="expander")),n},getEventTargetType:function(e){return this.getEventTarget(e).type},getNode:function(e){if(e instanceof j)return e;for(e instanceof C?e=e[0]:void 0!==e.originalEvent&&(e=e.target);e;){if(e.ftnode)return e.ftnode;e=e.parentNode}return null},getTree:function(e){var t=e;return e instanceof F?e:("number"==typeof(e=void 0===e?0:e)?e=C(".fancytree-container").eq(e):"string"==typeof e?(e=C("#ft-id-"+t).eq(0)).length||(e=C(t).eq(0)):e instanceof Element||e instanceof HTMLDocument?e=C(e):e instanceof C?e=e.eq(0):void 0!==e.originalEvent&&(e=C(e.target)),(e=(e=e.closest(":ui-fancytree")).data("ui-fancytree")||e.data("fancytree"))?e.tree:null)},evalOption:function(e,t,n,i,r){var o,s=t.tree,i=i[e],n=n[e];return N(i)?(o={node:t,tree:s,widget:s.widget,options:s.widget.options,typeInfo:s.types[t.type]||{}},null==(o=i.call(s,{type:e},o))&&(o=n)):o=null==n?i:n,o=null==o?r:o},setSpanIcon:function(e,t,n){var i=C(e);"string"==typeof n?i.attr("class",t+" "+n):(n.text?i.text(""+n.text):n.html&&(e.innerHTML=n.html),i.attr("class",t+" "+(n.addClass||"")))},eventToString:function(e){var t=e.which,n=e.type,i=[];return e.altKey&&i.push("alt"),e.ctrlKey&&i.push("ctrl"),e.metaKey&&i.push("meta"),e.shiftKey&&i.push("shift"),"click"===n||"dblclick"===n?i.push(o[e.button]+n):"wheel"===n?i.push(n):r[t]||i.push(u[t]||String.fromCharCode(t).toLowerCase()),i.join("+")},info:function(e){3<=C.ui.fancytree.debugLevel&&d("info",arguments)},keyEventToString:function(e){return this.warn("keyEventToString() is deprecated: use eventToString()"),this.eventToString(e)},overrideMethod:function(e,t,n,i){var r,o=e[t]||C.noop;e[t]=function(){var e=i||this;try{return r=e._super,e._super=o,n.apply(e,arguments)}finally{e._super=r}}},parseHtml:function(s){var a,l,d,c,u,h,f,p,e=s.find(">li"),g=[];return e.each(function(){var e,t,n=C(this),i=n.find(">span",this).first(),r=i.length?null:n.find(">a").first(),o={tooltip:null,data:{}};for(i.length?o.title=i.html():r&&r.length?(o.title=r.html(),o.data.href=r.attr("href"),o.data.target=r.attr("target"),o.tooltip=r.attr("title")):(o.title=n.html(),0<=(u=o.title.search(/<ul/i))&&(o.title=o.title.substring(0,u))),o.title=S(o.title),c=0,h=y.length;c<h;c++)o[y[c]]=void 0;for(a=this.className.split(" "),d=[],c=0,h=a.length;c<h;c++)l=a[c],v[l]?o[l]=!0:d.push(l);if(o.extraClasses=d.join(" "),(f=n.attr("title"))&&(o.tooltip=f),(f=n.attr("id"))&&(o.key=f),n.attr("hideCheckbox")&&(o.checkbox=!1),(e=P(n))&&!C.isEmptyObject(e)){for(t in x)w(e,t)&&(e[x[t]]=e[t],delete e[t]);for(c=0,h=b.length;c<h;c++)f=b[c],null!=(p=e[f])&&(delete e[f],o[f]=p);C.extend(o.data,e)}(s=n.find(">ul").first()).length?o.children=C.ui.fancytree.parseHtml(s):o.children=o.lazy?void 0:null,g.push(o)}),g},registerExtension:function(e){k(null!=e.name,"extensions must have a `name` property."),k(null!=e.version,"extensions must have a `version` property."),C.ui.fancytree._extensions[e.name]=e},trim:S,unescapeHtml:function(e){var t=document.createElement("div");return t.innerHTML=e,0===t.childNodes.length?"":t.childNodes[0].nodeValue},warn:function(e){2<=C.ui.fancytree.debugLevel&&d("warn",arguments)}}),C.ui.fancytree}function k(e,t){e||(C.ui.fancytree.error(t="Fancytree assertion failed"+(t=t?": "+t:"")),C.error(t))}function w(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function N(e){return"function"==typeof e}function S(e){return null==e?"":e.trim()}function d(t,n){var i,r,t=window.console?window.console[t]:null;if(t)try{t.apply(window.console,n)}catch(e){for(r="",i=0;i<n.length;i++)r+=n[i];t(r)}}function E(e,i,t,n,r){var o,s,a;function l(){return o.apply(i,arguments)}function d(e){return o.apply(i,e)}return o=i[e],s=n[e],a=i.ext[r],function(){var e=i._local,t=i._super,n=i._superApply;try{return i._local=a,i._super=l,i._superApply=d,s.apply(i,arguments)}finally{i._local=e,i._super=t,i._superApply=n}}}function T(e,t){return(void 0===e?C.Deferred(function(){this.resolve()}):C.Deferred(function(){this.resolveWith(e,t)})).promise()}function A(e,t){return(void 0===e?C.Deferred(function(){this.reject()}):C.Deferred(function(){this.rejectWith(e,t)})).promise()}function O(e,t){return function(){e.resolveWith(t)}}function P(e){var t=C.extend({},e.data()),e=t.json;return delete t.fancytree,delete t.uiFancytree,e&&(delete t.json,t=C.extend(t,e)),t}function D(e){return(""+e).replace(n,function(e){return i[e]})}function L(t){return t=t.toLowerCase(),function(e){return 0<=e.title.toLowerCase().indexOf(t)}}function j(e,t){var n,i,r;for(this.parent=e,this.tree=e.tree,this.ul=null,this.li=null,this.statusNodeType=null,this._isLoading=!1,this._error=null,this.data={},n=0,i=b.length;n<i;n++)this[r=b[n]]=t[r];for(r in null==this.unselectableIgnore&&null==this.unselectableStatus||(this.unselectable=!0),t.hideCheckbox&&C.error("'hideCheckbox' node option was removed in v2.23.0: use 'checkbox: false'"),t.data&&C.extend(this.data,t.data),t)s[r]||!this.tree.options.copyFunctionsToData&&N(t[r])||a[r]||(this.data[r]=t[r]);null==this.key?this.tree.options.defaultKey?(this.key=""+this.tree.options.defaultKey(this),k(this.key,"defaultKey() must return a unique key")):this.key="_"+h._nextNodeKey++:this.key=""+this.key,t.active&&(k(null===this.tree.activeNode,"only one active node allowed"),this.tree.activeNode=this),t.selected&&(this.tree.lastSelectedNode=this),(e=t.children)?e.length?this._setChildren(e):this.children=this.lazy?[]:null:this.children=null,this.tree._callHook("treeRegisterNode",this.tree,!0,this)}function F(e){this.widget=e,this.$div=e.element,this.options=e.options,this.options&&(void 0!==this.options.lazyload&&C.error("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."),void 0!==this.options.loaderror&&C.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."),void 0!==this.options.fx&&C.error("The 'fx' option was replaced by 'toggleEffect' since 2014-11-30."),void 0!==this.options.removeNode&&C.error("The 'removeNode' event was replaced by 'modifyChild' since 2.20 (2016-09-10).")),this.ext={},this.types={},this.columns={},this.data=P(this.$div),this._id=""+(this.options.treeId||C.ui.fancytree._nextId++),this._ns=".fancytree-"+this._id,this.activeNode=null,this.focusNode=null,this._hasFocus=null,this._tempCache={},this._lastMousedownNode=null,this._enableUpdate=!0,this.lastSelectedNode=null,this.systemFocusElement=null,this.lastQuicksearchTerm="",this.lastQuicksearchTime=0,this.viewport=null,this.statusClassPropName="span",this.ariaPropName="li",this.nodeContainerAttrName="li",this.$div.find(">ul.fancytree-container").remove(),this.rootNode=new j({tree:this},{title:"root",key:"root_"+this._id,children:null,expanded:!0}),this.rootNode.parent=null,e=C("<ul>",{id:"ft-id-"+this._id,class:"ui-fancytree fancytree-container fancytree-plain"}).appendTo(this.$div),this.$container=e,this.rootNode.ul=e[0],null==this.options.debugLevel&&(this.options.debugLevel=h.debugLevel)}C.ui.fancytree.warn("Fancytree: ignored duplicate include")},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree.ui-deps"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree.ui-deps"),module.exports=t(require("jquery"))):t(jQuery),t=function(o){"use strict";return o.ui.fancytree._FancytreeClass.prototype.countSelected=function(e){this.options;return this.getSelectedNodes(e).length},o.ui.fancytree._FancytreeNodeClass.prototype.updateCounters=function(){var e=this,t=o("span.fancytree-childcounter",e.span),n=e.tree.options.childcounter,i=e.countChildren(n.deep);!(e.data.childCounter=i)&&n.hideZeros||e.isExpanded()&&n.hideExpanded?t.remove():(t=!t.length?o("<span class='fancytree-childcounter'/>").appendTo(o("span.fancytree-icon,span.fancytree-custom-icon",e.span)):t).text(i),!n.deep||e.isTopLevel()||e.isRootNode()||e.parent.updateCounters()},o.ui.fancytree.prototype.widgetMethod1=function(e){this.tree;return e},o.ui.fancytree.registerExtension({name:"childcounter",version:"2.38.3",options:{deep:!0,hideZeros:!0,hideExpanded:!1},foo:42,_appendCounter:function(e){},treeInit:function(e){e.options,e.options.childcounter;this._superApply(arguments),this.$container.addClass("fancytree-ext-childcounter")},treeDestroy:function(e){this._superApply(arguments)},nodeRenderTitle:function(e,t){var n=e.node,i=e.options.childcounter,r=null==n.data.childCounter?n.countChildren(i.deep):+n.data.childCounter;this._super(e,t),!r&&i.hideZeros||n.isExpanded()&&i.hideExpanded||o("span.fancytree-icon,span.fancytree-custom-icon",n.span).append(o("<span class='fancytree-childcounter'/>").text(r))},nodeSetExpanded:function(e,t,n){var i=e.tree;e.node;return this._superApply(arguments).always(function(){i.nodeRenderTitle(e)})}}),o.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(c){"use strict";var u=c.ui.fancytree.assert;function n(e,t,n){for(var i,r,o=3&e.length,s=e.length-o,a=n,l=3432918353,d=461845907,c=0;c<s;)r=255&e.charCodeAt(c)|(255&e.charCodeAt(++c))<<8|(255&e.charCodeAt(++c))<<16|(255&e.charCodeAt(++c))<<24,++c,a=27492+(65535&(i=5*(65535&(a=(a^=r=(65535&(r=(r=(65535&r)*l+(((r>>>16)*l&65535)<<16)&4294967295)<<15|r>>>17))*d+(((r>>>16)*d&65535)<<16)&4294967295)<<13|a>>>19))+((5*(a>>>16)&65535)<<16)&4294967295))+((58964+(i>>>16)&65535)<<16);switch(r=0,o){case 3:r^=(255&e.charCodeAt(c+2))<<16;case 2:r^=(255&e.charCodeAt(c+1))<<8;case 1:a^=r=(65535&(r=(r=(65535&(r^=255&e.charCodeAt(c)))*l+(((r>>>16)*l&65535)<<16)&4294967295)<<15|r>>>17))*d+(((r>>>16)*d&65535)<<16)&4294967295}return a^=e.length,a=2246822507*(65535&(a^=a>>>16))+((2246822507*(a>>>16)&65535)<<16)&4294967295,a=3266489909*(65535&(a^=a>>>13))+((3266489909*(a>>>16)&65535)<<16)&4294967295,a^=a>>>16,t?("0000000"+(a>>>0).toString(16)).substr(-8):a>>>0}return c.ui.fancytree._FancytreeNodeClass.prototype.getCloneList=function(e){var t,n=this.tree,i=n.refMap[this.refKey]||null,r=n.keyMap;return i&&(t=this.key,e?i=c.map(i,function(e){return r[e]}):(i=c.map(i,function(e){return e===t?null:r[e]})).length<1&&(i=null)),i},c.ui.fancytree._FancytreeNodeClass.prototype.isClone=function(){var e=this.refKey||null,e=e&&this.tree.refMap[e]||null;return!!(e&&1<e.length)},c.ui.fancytree._FancytreeNodeClass.prototype.reRegister=function(t,e){e=null==e?null:""+e;var n=this.tree,i=this.key,r=this.refKey,o=n.keyMap,s=n.refMap,a=s[r]||null,n=!1;return null!=(t=null==t?null:""+t)&&t!==this.key&&(o[t]&&c.error("[ext-clones] reRegister("+t+"): already exists: "+this),delete o[i],o[t]=this,a&&(s[r]=c.map(a,function(e){return e===i?t:e})),this.key=t,n=!0),null!=e&&e!==this.refKey&&(a&&(1===a.length?delete s[r]:s[r]=c.map(a,function(e){return e===i?null:e})),s[e]?s[e].append(t):s[e]=[this.key],this.refKey=e,n=!0),n},c.ui.fancytree._FancytreeNodeClass.prototype.setRefKey=function(e){return this.reRegister(null,e)},c.ui.fancytree._FancytreeClass.prototype.getNodesByRef=function(e,t){var n=this.keyMap,e=this.refMap[e]||null;return e=e&&(e=t?c.map(e,function(e){e=n[e];return e.isDescendantOf(t)?e:null}):c.map(e,function(e){return n[e]})).length<1?null:e},c.ui.fancytree._FancytreeClass.prototype.changeRefKey=function(e,t){var n,i=this.keyMap,r=this.refMap[e]||null;if(r){for(n=0;n<r.length;n++)i[r[n]].refKey=t;delete this.refMap[e],this.refMap[t]=r}},c.ui.fancytree.registerExtension({name:"clones",version:"2.38.3",options:{highlightActiveClones:!0,highlightClones:!1},treeCreate:function(e){this._superApply(arguments),e.tree.refMap={},e.tree.keyMap={}},treeInit:function(e){this.$container.addClass("fancytree-ext-clones"),u(null==e.options.defaultKey),e.options.defaultKey=function(e){return t=e,"id_"+(t=n(e=(e=c.map(e.getParentList(!1,!0),function(e){return e.refKey||e.key})).join("/"),!0))+n(t+e,!0);var t},this._superApply(arguments)},treeClear:function(e){return e.tree.refMap={},e.tree.keyMap={},this._superApply(arguments)},treeRegisterNode:function(e,t,n){var i,r,o=e.tree,s=o.keyMap,a=o.refMap,l=n.key,d=n&&null!=n.refKey?""+n.refKey:null;return n.isStatusNode()||(t?(null!=s[n.key]&&(r=s[n.key],r="clones.treeRegisterNode: duplicate key '"+n.key+"': /"+n.getPath(!0)+" => "+r.getPath(!0),o.error(r),c.error(r)),s[l]=n,d&&((i=a[d])?(i.push(l),2===i.length&&e.options.clones.highlightClones&&s[i[0]].renderStatus()):a[d]=[l])):(null==s[l]&&c.error("clones.treeRegisterNode: node.key not registered: "+n.key),delete s[l],d&&(i=a[d])&&((r=i.length)<=1?(u(1===r),u(i[0]===l),delete a[d]):(function(e,t){for(var n=e.length-1;0<=n;n--)if(e[n]===t)return e.splice(n,1)}(i,l),2===r&&e.options.clones.highlightClones&&s[i[0]].renderStatus())))),this._super(e,t,n)},nodeRenderStatus:function(e){var t,n=e.node,i=this._super(e);return e.options.clones.highlightClones&&(t=c(n[e.tree.statusClassPropName])).length&&n.isClone()&&t.addClass("fancytree-clone"),i},nodeSetActive:function(e,n,t){var i=e.tree.statusClassPropName,r=e.node,o=this._superApply(arguments);return e.options.clones.highlightActiveClones&&r.isClone()&&c.each(r.getCloneList(!0),function(e,t){c(t[i]).toggleClass("fancytree-active-clone",!1!==n)}),o}}),c.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(f){"use strict";var a,l,p=f.ui.fancytree,o=/Mac/.test(navigator.platform),d="fancytree-drag-source",c="fancytree-drag-remove",g="fancytree-drop-accept",y="fancytree-drop-after",v="fancytree-drop-before",m="fancytree-drop-over",b="fancytree-drop-reject",x="fancytree-drop-target",u="application/x-fancytree-node",C=null,h=null,_=null,k=null,w=null,s=null,N=null,S=null,E=null,T=null;function A(){_=h=s=S=N=T=w=null,k&&k.removeClass(d+" "+c),k=null,C&&C.hide(),l&&(l.remove(),l=null)}function O(e){return 0===e?"":0<e?"+"+e:""+e}function P(e,t){var n,i=t.tree,r=t.dataTransfer;"dragstart"===e.type?(t.effectAllowed=i.options.dnd5.effectAllowed,t.dropEffect=i.options.dnd5.dropEffectDefault):(t.effectAllowed=S,t.dropEffect=N),t.dropEffectSuggested=(n=e,i=(e=i).options.dnd5.dropEffectDefault,o?n.metaKey&&n.altKey||n.ctrlKey?i="link":n.metaKey?i="move":n.altKey&&(i="copy"):n.ctrlKey?i="copy":n.shiftKey?i="move":n.altKey&&(i="link"),i!==s&&e.info("evalEffectModifiers: "+n.type+" - evalEffectModifiers(): "+s+" -> "+i),s=i),t.isMove="move"===t.dropEffect,t.files=r.files||[]}function D(e,t,n){var i=t.tree,r=t.dataTransfer;return"dragstart"!==e.type&&S!==t.effectAllowed&&i.warn("effectAllowed should only be changed in dragstart event: "+e.type+": data.effectAllowed changed from "+S+" -> "+t.effectAllowed),!1===n&&(i.info("applyDropEffectCallback: allowDrop === false"),t.effectAllowed="none",t.dropEffect="none"),t.isMove="move"===t.dropEffect,"dragstart"===e.type&&(S=t.effectAllowed,N=t.dropEffect),r.effectAllowed=S,r.dropEffect=N}function L(e,t){if(t.options.dnd5.scroll&&(h=t.tree,s=e,r=h.options.dnd5,o=h.$scrollParent[0],l=r.scrollSensitivity,u=r.scrollSpeed,i=0,o!==document&&"HTML"!==o.tagName?(r=h.$scrollParent.offset(),d=o.scrollTop,r.top+o.offsetHeight-s.pageY<l?0<o.scrollHeight-h.$scrollParent.innerHeight()-d&&(o.scrollTop=i=d+u):0<d&&s.pageY-r.top<l&&(o.scrollTop=i=d-u)):0<(d=f(document).scrollTop())&&s.pageY-d<l?(i=d-u,f(document).scrollTop(i)):f(window).height()-(s.pageY-d)<l&&(i=d+u,f(document).scrollTop(i)),i&&h.debug("autoScroll: "+i+"px")),!t.node)return t.tree.warn("Ignored dragover for non-node"),E;var n,i,r=null,o=t.tree,s=o.options,a=s.dnd5,l=t.node,d=t.otherNode,c="center",u=f(l.span),h=u.find("span.fancytree-title");if(!1===w)return o.debug("Ignored dragover, since dragenter returned false."),!1;if("string"==typeof w&&f.error("assert failed: dragenter returned string"),i=u.offset(),u=(e.pageY-i.top)/u.height(),void 0===e.pageY&&o.warn("event.pageY is undefined: see issue #1013."),w.after&&.75<u||!w.over&&w.after&&.5<u?r="after":w.before&&u<=.25||!w.over&&w.before&&u<=.5?r="before":w.over&&(r="over"),a.preventVoidMoves&&"move"===t.dropEffect&&(l===d?(l.debug("Drop over source node prevented."),r=null):"before"===r&&d&&l===d.getNextSibling()?(l.debug("Drop after source node prevented."),r=null):"after"===r&&d&&l===d.getPrevSibling()?(l.debug("Drop before source node prevented."),r=null):"over"===r&&d&&d.parent===l&&d.isLastSibling()&&(l.debug("Drop last child over own parent prevented."),r=null)),(t.hitMode=r)&&a.dragOver&&(P(e,t),a.dragOver(l,t),D(e,t,!!r),r=t.hitMode),"after"===(E=r)||"before"===r||"over"===r){switch(n=a.dropMarkerOffsetX||0,r){case"before":c="top",n+=a.dropMarkerInsertOffsetX||0;break;case"after":c="bottom",n+=a.dropMarkerInsertOffsetX||0}h={my:"left"+O(n)+" center",at:"left "+c,of:h},s.rtl&&(h.my="right"+O(-n)+" center",h.at="right "+c),C.toggleClass(y,"after"===r).toggleClass(m,"over"===r).toggleClass(v,"before"===r).show().position(p.fixPositionOptions(h))}else C.hide();return f(l.span).toggleClass(x,"after"===r||"before"===r||"over"===r).toggleClass(y,"after"===r).toggleClass(v,"before"===r).toggleClass(g,"over"===r).toggleClass(b,!1===r),r}function j(e){var t,n=this,i=n.options.dnd5,r=null,o=p.getNode(e),s=e.dataTransfer||e.originalEvent.dataTransfer,a={tree:n,node:o,options:n.options,originalEvent:e.originalEvent,widget:n.widget,hitMode:w,dataTransfer:s,otherNode:h||null,otherNodeList:_||null,otherNodeData:null,useDefaultImage:!0,dropEffect:void 0,dropEffectSuggested:void 0,effectAllowed:void 0,files:null,isCancelled:void 0,isMove:void 0};switch(e.type){case"dragenter":if(T=null,!o){n.debug("Ignore non-node "+e.type+": "+e.target.tagName+"."+e.target.className),w=!1;break}if(f(o.span).addClass(m).removeClass(g+" "+b),t=0<=f.inArray(u,s.types),i.preventNonNodes&&!t){o.debug("Reject dropping a non-node."),w=!1;break}if(i.preventForeignNodes&&(!h||h.tree!==o.tree)){o.debug("Reject dropping a foreign node."),w=!1;break}if(i.preventSameParent&&a.otherNode&&a.otherNode.tree===o.tree&&o.parent===a.otherNode.parent){o.debug("Reject dropping as sibling (same parent)."),w=!1;break}if(i.preventRecursion&&a.otherNode&&a.otherNode.tree===o.tree&&o.isDescendantOf(a.otherNode)){o.debug("Reject dropping below own ancestor."),w=!1;break}if(i.preventLazyParents&&!o.isLoaded()){o.warn("Drop over unloaded target node prevented."),w=!1;break}C.show(),P(e,a),t=i.dragEnter(o,a),t=!!(t=t)&&(t=f.isPlainObject(t)?{over:!!t.over,before:!!t.before,after:!!t.after}:Array.isArray(t)?{over:0<=f.inArray("over",t),before:0<=f.inArray("before",t),after:0<=f.inArray("after",t)}:{over:!0===t||"over"===t,before:!0===t||"before"===t,after:!0===t||"after"===t},0!==Object.keys(t).length&&t),D(e,a,r=(w=t)&&(t.over||t.before||t.after));break;case"dragover":if(!o){n.debug("Ignore non-node "+e.type+": "+e.target.tagName+"."+e.target.className);break}P(e,a),r=!!(E=L(e,a)),("over"===E||!1===E)&&!o.expanded&&!1!==o.hasChildren()?T?!(i.autoExpandMS&&Date.now()-T>i.autoExpandMS)||o.isLoading()||i.dragExpand&&!1===i.dragExpand(o,a)||o.setExpanded():T=Date.now():T=null;break;case"dragleave":if(!o){n.debug("Ignore non-node "+e.type+": "+e.target.tagName+"."+e.target.className);break}if(!f(o.span).hasClass(m)){o.debug("Ignore dragleave (multi).");break}f(o.span).removeClass(m+" "+g+" "+b),o.scheduleAction("cancel"),i.dragLeave(o,a),C.hide();break;case"drop":if(0<=f.inArray(u,s.types)&&(d=s.getData(u),n.info(e.type+": getData('application/x-fancytree-node'): '"+d+"'")),d||(d=s.getData("text"),n.info(e.type+": getData('text'): '"+d+"'")),d)try{void 0!==(l=JSON.parse(d)).title&&(a.otherNodeData=l)}catch(e){}n.debug(e.type+": nodeData: '"+d+"', otherNodeData: ",a.otherNodeData),f(o.span).removeClass(m+" "+g+" "+b),a.hitMode=E,P(e,a),a.isCancelled=!E;var l=h&&h.span,d=h&&h.tree;i.dragDrop(o,a),e.preventDefault(),l&&!document.body.contains(l)&&(d===n?(n.debug("Drop handler removed source element: generating dragEnd."),i.dragEnd(h,a)):n.warn("Drop handler removed source element: dragend event may be lost.")),A()}if(r)return e.preventDefault(),!1}return f.ui.fancytree.getDragNodeList=function(){return _||[]},f.ui.fancytree.getDragNode=function(){return h},f.ui.fancytree.registerExtension({name:"dnd5",version:"2.38.3",options:{autoExpandMS:1500,dropMarkerInsertOffsetX:-16,dropMarkerOffsetX:-24,dropMarkerParent:"body",multiSource:!1,effectAllowed:"all",dropEffectDefault:"move",preventForeignNodes:!1,preventLazyParents:!0,preventNonNodes:!1,preventRecursion:!0,preventSameParent:!1,preventVoidMoves:!0,scroll:!0,scrollSensitivity:20,scrollSpeed:5,setTextTypeJson:!1,sourceCopyHook:null,dragStart:null,dragDrag:f.noop,dragEnd:f.noop,dragEnter:null,dragOver:f.noop,dragExpand:f.noop,dragDrop:f.noop,dragLeave:f.noop},treeInit:function(e){var t=e.tree,n=e.options,i=n.glyph||null,r=n.dnd5;0<=f.inArray("dnd",n.extensions)&&f.error("Extensions 'dnd' and 'dnd5' are mutually exclusive."),r.dragStop&&f.error("dragStop is not used by ext-dnd5. Use dragEnd instead."),null!=r.preventRecursiveMoves&&f.error("preventRecursiveMoves was renamed to preventRecursion."),r.dragStart&&p.overrideMethod(e.options,"createNode",function(e,t){this._super.apply(this,arguments),t.node.span?t.node.span.draggable=!0:t.node.warn("Cannot add `draggable`: no span tag")}),this._superApply(arguments),this.$container.addClass("fancytree-ext-dnd5"),e=f("<span>").appendTo(this.$container),this.$scrollParent=e.scrollParent(),e.remove(),(C=f("#fancytree-drop-marker")).length||(C=f("<div id='fancytree-drop-marker'></div>").hide().css({"z-index":1e3,"pointer-events":"none"}).prependTo(r.dropMarkerParent),i&&p.setSpanIcon(C[0],i.map._addClass,i.map.dropMarker)),C.toggleClass("fancytree-rtl",!!n.rtl),r.dragStart&&t.$container.on("dragstart drag dragend",function(e){var t=this,n=t.options.dnd5,i=p.getNode(e),r=e.dataTransfer||e.originalEvent.dataTransfer,o={tree:t,node:i,options:t.options,originalEvent:e.originalEvent,widget:t.widget,dataTransfer:r,useDefaultImage:!0,dropEffect:void 0,dropEffectSuggested:void 0,effectAllowed:void 0,files:void 0,isCancelled:void 0,isMove:void 0};switch(e.type){case"dragstart":if(!i)return t.info("Ignored dragstart on a non-node."),!1;h=i,_=!1===n.multiSource?[i]:!0===n.multiSource?i.isSelected()?t.getSelectedNodes():[i]:n.multiSource(i,o),(k=f(f.map(_,function(e){return e.span}))).addClass(d);var s=i.toDict(!0,n.sourceCopyHook);s.treeId=i.tree._id,s=JSON.stringify(s);try{r.setData(u,s),r.setData("text/html",f(i.span).html()),r.setData("text/plain",i.title)}catch(e){t.warn("Could not set data (IE only accepts 'text') - "+e)}return(n.setTextTypeJson?r.setData("text",s):r.setData("text",i.title),P(e,o),!1===n.dragStart(i,o))?(A(),!1):(D(e,o),l=null,o.useDefaultImage&&(a=f(i.span).find(".fancytree-title"),_&&1<_.length&&(l=f("<span class='fancytree-childcounter'/>").text("+"+(_.length-1)).appendTo(a)),r.setDragImage&&r.setDragImage(a[0],-10,-10)),!0);case"drag":P(e,o),n.dragDrag(i,o),D(e,o),k.toggleClass(c,o.isMove);break;case"dragend":P(e,o),A(),o.isCancelled=!E,n.dragEnd(i,o,!E)}}.bind(t)),r.dragEnter&&t.$container.on("dragenter dragover dragleave drop",j.bind(t))}}),f.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(d){"use strict";var t=/Mac/.test(navigator.platform),c=d.ui.fancytree.escapeHtml,u=d.ui.fancytree.trim,a=d.ui.fancytree.unescapeHtml;return d.ui.fancytree._FancytreeNodeClass.prototype.editStart=function(){var t,n=this,e=this.tree,i=e.ext.edit,r=e.options.edit,o=d(".fancytree-title",n.span),s={node:n,tree:e,options:e.options,isNew:d(n[e.statusClassPropName]).hasClass("fancytree-edit-new"),orgTitle:n.title,input:null,dirty:!1};if(!1===r.beforeEdit.call(n,{type:"beforeEdit"},s))return!1;d.ui.fancytree.assert(!i.currentNode,"recursive edit"),i.currentNode=this,i.eventData=s,e.widget._unbind(),i.lastDraggableAttrValue=n.span.draggable,i.lastDraggableAttrValue&&(n.span.draggable=!1),d(document).on("mousedown.fancytree-edit",function(e){d(e.target).hasClass("fancytree-edit-input")||n.editEnd(!0,e)}),t=d("<input />",{class:"fancytree-edit-input",type:"text",value:e.options.escapeTitles?s.orgTitle:a(s.orgTitle)}),i.eventData.input=t,null!=r.adjustWidthOfs&&t.width(o.width()+r.adjustWidthOfs),null!=r.inputCss&&t.css(r.inputCss),o.html(t),t.focus().change(function(e){t.addClass("fancytree-edit-dirty")}).on("keydown",function(e){switch(e.which){case d.ui.keyCode.ESCAPE:n.editEnd(!1,e);break;case d.ui.keyCode.ENTER:return n.editEnd(!0,e),!1}e.stopPropagation()}).blur(function(e){return n.editEnd(!0,e)}),r.edit.call(n,{type:"edit"},s)},d.ui.fancytree._FancytreeNodeClass.prototype.editEnd=function(e,t){var n,i=this,r=this.tree,o=r.ext.edit,s=o.eventData,a=r.options.edit,l=d(".fancytree-title",i.span).find("input.fancytree-edit-input");return a.trim&&l.val(u(l.val())),n=l.val(),s.dirty=n!==i.title,s.originalEvent=t,!1===e?s.save=!1:s.isNew?s.save=""!==n:s.save=s.dirty&&""!==n,!1!==a.beforeClose.call(i,{type:"beforeClose"},s)&&((!s.save||!1!==a.save.call(i,{type:"save"},s))&&(l.removeClass("fancytree-edit-dirty").off(),d(document).off(".fancytree-edit"),s.save?(i.setTitle(r.options.escapeTitles?n:c(n)),i.setFocus()):s.isNew?(i.remove(),i=s.node=null,o.relatedNode.setFocus()):(i.renderTitle(),i.setFocus()),o.eventData=null,o.currentNode=null,o.relatedNode=null,r.widget._bind(),i&&o.lastDraggableAttrValue&&(i.span.draggable=!0),r.$container.get(0).focus({preventScroll:!0}),s.input=null,a.close.call(i,{type:"close"},s),!0))},d.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode=function(e,t){var n,i=this.tree,r=this;e=e||"child",null==t?t={title:""}:"string"==typeof t?t={title:t}:d.ui.fancytree.assert(d.isPlainObject(t)),"child"!==e||this.isExpanded()||!1===this.hasChildren()?((n=this.addNode(t,e)).match=!0,d(n[i.statusClassPropName]).removeClass("fancytree-hide").addClass("fancytree-match"),n.makeVisible().done(function(){d(n[i.statusClassPropName]).addClass("fancytree-edit-new"),r.tree.ext.edit.relatedNode=r,n.editStart()})):this.setExpanded().done(function(){r.editCreateNode(e,t)})},d.ui.fancytree._FancytreeClass.prototype.isEditing=function(){return this.ext.edit?this.ext.edit.currentNode:null},d.ui.fancytree._FancytreeNodeClass.prototype.isEditing=function(){return!!this.tree.ext.edit&&this.tree.ext.edit.currentNode===this},d.ui.fancytree.registerExtension({name:"edit",version:"2.38.3",options:{adjustWidthOfs:4,allowEmpty:!1,inputCss:{minWidth:"3em"},triggerStart:["f2","mac+enter","shift+click"],trim:!0,beforeClose:d.noop,beforeEdit:d.noop,close:d.noop,edit:d.noop,save:d.noop},currentNode:null,treeInit:function(e){var i=e.tree;this._superApply(arguments),this.$container.addClass("fancytree-ext-edit").on("fancytreebeforeupdateviewport",function(e,t){var n=i.isEditing();n&&(n.info("Cancel edit due to scroll event."),n.editEnd(!1,e))})},nodeClick:function(e){var t=d.ui.fancytree.eventToString(e.originalEvent),n=e.options.edit.triggerStart;return"shift+click"===t&&0<=d.inArray("shift+click",n)&&e.originalEvent.shiftKey||"click"===t&&0<=d.inArray("clickActive",n)&&e.node.isActive()&&!e.node.isEditing()&&d(e.originalEvent.target).hasClass("fancytree-title")?(e.node.editStart(),!1):this._superApply(arguments)},nodeDblclick:function(e){return 0<=d.inArray("dblclick",e.options.edit.triggerStart)?(e.node.editStart(),!1):this._superApply(arguments)},nodeKeydown:function(e){switch(e.originalEvent.which){case 113:if(0<=d.inArray("f2",e.options.edit.triggerStart))return e.node.editStart(),!1;break;case d.ui.keyCode.ENTER:if(0<=d.inArray("mac+enter",e.options.edit.triggerStart)&&t)return e.node.editStart(),!1}return this._superApply(arguments)}}),d.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(y){"use strict";var v="__not_found__",m=y.ui.fancytree.escapeHtml;function b(e){return(e+"").replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function x(e,t,n){for(var i=[],r=1;r<t.length;r++){var o=t[r].length+(1===r?0:1)+(i[i.length-1]||0);i.push(o)}var s=e.split("");return n?i.forEach(function(e){s[e]="\ufff7"+s[e]+"\ufff8"}):i.forEach(function(e){s[e]="<mark>"+s[e]+"</mark>"}),s.join("")}return y.ui.fancytree._FancytreeClass.prototype._applyFilterImpl=function(i,r,e){var t,o,s,a,l,d,c=0,n=this.options,u=n.escapeTitles,h=n.autoCollapse,f=y.extend({},n.filter,e),p="hide"===f.mode,g=!!f.leavesOnly&&!r;if("string"==typeof i){if(""===i)return this.warn("Fancytree passing an empty string as a filter is handled as clearFilter()."),void this.clearFilter();t=f.fuzzy?i.split("").map(b).reduce(function(e,t){return e+"([^"+t+"]*)"+t},""):b(i),o=new RegExp(t,"i"),s=new RegExp(b(i),"gi"),u&&(a=new RegExp(b("\ufff7"),"g"),l=new RegExp(b("\ufff8"),"g")),i=function(e){if(!e.title)return!1;var t,n=u?e.title:0<=(t=e.title).indexOf(">")?y("<div/>").html(t).text():t,t=n.match(o);return t&&f.highlight&&(u?(d=f.fuzzy?x(n,t,u):n.replace(s,function(e){return"\ufff7"+e+"\ufff8"}),e.titleWithHighlight=m(d).replace(a,"<mark>").replace(l,"</mark>")):f.fuzzy?e.titleWithHighlight=x(n,t):e.titleWithHighlight=n.replace(s,function(e){return"<mark>"+e+"</mark>"})),!!t}}return this.enableFilter=!0,this.lastFilterArgs=arguments,e=this.enableUpdate(!1),this.$div.addClass("fancytree-ext-filter"),p?this.$div.addClass("fancytree-ext-filter-hide"):this.$div.addClass("fancytree-ext-filter-dimm"),this.$div.toggleClass("fancytree-ext-filter-hide-expanders",!!f.hideExpanders),this.rootNode.subMatchCount=0,this.visit(function(e){delete e.match,delete e.titleWithHighlight,e.subMatchCount=0}),(t=this.getRootNode()._findDirectChild(v))&&t.remove(),n.autoCollapse=!1,this.visit(function(t){if(!g||null==t.children){var e=i(t),n=!1;if("skip"===e)return t.visit(function(e){e.match=!1},!0),"skip";e||!r&&"branch"!==e||!t.parent.match||(n=e=!0),e&&(c++,t.match=!0,t.visitParents(function(e){e!==t&&(e.subMatchCount+=1),!f.autoExpand||n||e.expanded||(e.setExpanded(!0,{noAnimation:!0,noEvents:!0,scrollIntoView:!1}),e._filterAutoExpanded=!0)},!0))}}),n.autoCollapse=h,0===c&&f.nodata&&p&&(!0===(t="function"==typeof(t=f.nodata)?t():t)?t={}:"string"==typeof t&&(t={title:t}),t=y.extend({statusNodeType:"nodata",key:v,title:this.options.strings.noData},t),this.getRootNode().addNode(t).match=!0),this._callHook("treeStructureChanged",this,"applyFilter"),this.enableUpdate(e),c},y.ui.fancytree._FancytreeClass.prototype.filterNodes=function(e,t){return"boolean"==typeof t&&(t={leavesOnly:t},this.warn("Fancytree.filterNodes() leavesOnly option is deprecated since 2.9.0 / 2015-04-19. Use opts.leavesOnly instead.")),this._applyFilterImpl(e,!1,t)},y.ui.fancytree._FancytreeClass.prototype.filterBranches=function(e,t){return this._applyFilterImpl(e,!0,t)},y.ui.fancytree._FancytreeClass.prototype.updateFilter=function(){this.enableFilter&&this.lastFilterArgs&&this.options.filter.autoApply?this._applyFilterImpl.apply(this,this.lastFilterArgs):this.warn("updateFilter(): no filter active.")},y.ui.fancytree._FancytreeClass.prototype.clearFilter=function(){var t,e=this.getRootNode()._findDirectChild(v),n=this.options.escapeTitles,i=this.options.enhanceTitle,r=this.enableUpdate(!1);e&&e.remove(),delete this.rootNode.match,delete this.rootNode.subMatchCount,this.visit(function(e){e.match&&e.span&&(t=y(e.span).find(">span.fancytree-title"),n?t.text(e.title):t.html(e.title),i&&i({type:"enhanceTitle"},{node:e,$title:t})),delete e.match,delete e.subMatchCount,delete e.titleWithHighlight,e.$subMatchBadge&&(e.$subMatchBadge.remove(),delete e.$subMatchBadge),e._filterAutoExpanded&&e.expanded&&e.setExpanded(!1,{noAnimation:!0,noEvents:!0,scrollIntoView:!1}),delete e._filterAutoExpanded}),this.enableFilter=!1,this.lastFilterArgs=null,this.$div.removeClass("fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide"),this._callHook("treeStructureChanged",this,"clearFilter"),this.enableUpdate(r)},y.ui.fancytree._FancytreeClass.prototype.isFilterActive=function(){return!!this.enableFilter},y.ui.fancytree._FancytreeNodeClass.prototype.isMatched=function(){return!(this.tree.enableFilter&&!this.match)},y.ui.fancytree.registerExtension({name:"filter",version:"2.38.3",options:{autoApply:!0,autoExpand:!1,counter:!0,fuzzy:!1,hideExpandedCounter:!0,hideExpanders:!1,highlight:!0,leavesOnly:!1,nodata:!0,mode:"dimm"},nodeLoadChildren:function(e,t){var n=e.tree;return this._superApply(arguments).done(function(){n.enableFilter&&n.lastFilterArgs&&e.options.filter.autoApply&&n._applyFilterImpl.apply(n,n.lastFilterArgs)})},nodeSetExpanded:function(e,t,n){var i=e.node;return delete i._filterAutoExpanded,!t&&e.options.filter.hideExpandedCounter&&i.$subMatchBadge&&i.$subMatchBadge.show(),this._superApply(arguments)},nodeRenderStatus:function(e){var t=e.node,n=e.tree,i=e.options.filter,r=y(t.span).find("span.fancytree-title"),o=y(t[n.statusClassPropName]),s=e.options.enhanceTitle,a=e.options.escapeTitles,e=this._super(e);return o.length&&n.enableFilter&&(o.toggleClass("fancytree-match",!!t.match).toggleClass("fancytree-submatch",!!t.subMatchCount).toggleClass("fancytree-hide",!(t.match||t.subMatchCount)),!i.counter||!t.subMatchCount||t.isExpanded()&&i.hideExpandedCounter?t.$subMatchBadge&&t.$subMatchBadge.hide():(t.$subMatchBadge||(t.$subMatchBadge=y("<span class='fancytree-childcounter'/>"),y("span.fancytree-icon, span.fancytree-custom-icon",t.span).append(t.$subMatchBadge)),t.$subMatchBadge.show().text(t.subMatchCount)),!t.span||t.isEditing&&t.isEditing.call(t)||(t.titleWithHighlight?r.html(t.titleWithHighlight):a?r.text(t.title):r.html(t.title),s&&s({type:"enhanceTitle"},{node:t,$title:r}))),e}}),y.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(l){"use strict";var a=l.ui.fancytree,n={awesome3:{_addClass:"",checkbox:"icon-check-empty",checkboxSelected:"icon-check",checkboxUnknown:"icon-check icon-muted",dragHelper:"icon-caret-right",dropMarker:"icon-caret-right",error:"icon-exclamation-sign",expanderClosed:"icon-caret-right",expanderLazy:"icon-angle-right",expanderOpen:"icon-caret-down",loading:"icon-refresh icon-spin",nodata:"icon-meh",noExpander:"",radio:"icon-circle-blank",radioSelected:"icon-circle",doc:"icon-file-alt",docOpen:"icon-file-alt",folder:"icon-folder-close-alt",folderOpen:"icon-folder-open-alt"},awesome4:{_addClass:"fa",checkbox:"fa-square-o",checkboxSelected:"fa-check-square-o",checkboxUnknown:"fa-square fancytree-helper-indeterminate-cb",dragHelper:"fa-arrow-right",dropMarker:"fa-long-arrow-right",error:"fa-warning",expanderClosed:"fa-caret-right",expanderLazy:"fa-angle-right",expanderOpen:"fa-caret-down",loading:{html:"<span class='fa fa-spinner fa-pulse' />"},nodata:"fa-meh-o",noExpander:"",radio:"fa-circle-thin",radioSelected:"fa-circle",doc:"fa-file-o",docOpen:"fa-file-o",folder:"fa-folder-o",folderOpen:"fa-folder-open-o"},awesome5:{_addClass:"",checkbox:"far fa-square",checkboxSelected:"far fa-check-square",checkboxUnknown:"fas fa-square fancytree-helper-indeterminate-cb",radio:"far fa-circle",radioSelected:"fas fa-circle",radioUnknown:"far fa-dot-circle",dragHelper:"fas fa-arrow-right",dropMarker:"fas fa-long-arrow-alt-right",error:"fas fa-exclamation-triangle",expanderClosed:"fas fa-caret-right",expanderLazy:"fas fa-angle-right",expanderOpen:"fas fa-caret-down",loading:"fas fa-spinner fa-pulse",nodata:"far fa-meh",noExpander:"",doc:"far fa-file",docOpen:"far fa-file",folder:"far fa-folder",folderOpen:"far fa-folder-open"},bootstrap3:{_addClass:"glyphicon",checkbox:"glyphicon-unchecked",checkboxSelected:"glyphicon-check",checkboxUnknown:"glyphicon-expand fancytree-helper-indeterminate-cb",dragHelper:"glyphicon-play",dropMarker:"glyphicon-arrow-right",error:"glyphicon-warning-sign",expanderClosed:"glyphicon-menu-right",expanderLazy:"glyphicon-menu-right",expanderOpen:"glyphicon-menu-down",loading:"glyphicon-refresh fancytree-helper-spin",nodata:"glyphicon-info-sign",noExpander:"",radio:"glyphicon-remove-circle",radioSelected:"glyphicon-ok-circle",doc:"glyphicon-file",docOpen:"glyphicon-file",folder:"glyphicon-folder-close",folderOpen:"glyphicon-folder-open"},material:{_addClass:"material-icons",checkbox:{text:"check_box_outline_blank"},checkboxSelected:{text:"check_box"},checkboxUnknown:{text:"indeterminate_check_box"},dragHelper:{text:"play_arrow"},dropMarker:{text:"arrow-forward"},error:{text:"warning"},expanderClosed:{text:"chevron_right"},expanderLazy:{text:"last_page"},expanderOpen:{text:"expand_more"},loading:{text:"autorenew",addClass:"fancytree-helper-spin"},nodata:{text:"info"},noExpander:{text:""},radio:{text:"radio_button_unchecked"},radioSelected:{text:"radio_button_checked"},doc:{text:"insert_drive_file"},docOpen:{text:"insert_drive_file"},folder:{text:"folder"},folderOpen:{text:"folder_open"}}};function d(e,t,n,i,r){var o=i.map,s=o[r],a=l(t),i=a.find(".fancytree-childcounter"),o=n+" "+(o._addClass||"");"string"==typeof(s="function"==typeof s?s.call(this,e,t,r):s)?(t.innerHTML="",a.attr("class",o+" "+s).append(i)):s&&(s.text?t.textContent=""+s.text:s.html?t.innerHTML=s.html:t.innerHTML="",a.attr("class",o+" "+(s.addClass||"")).append(i))}return l.ui.fancytree.registerExtension({name:"glyph",version:"2.38.3",options:{preset:null,map:{}},treeInit:function(e){var t=e.tree,e=e.options.glyph;e.preset?(a.assert(!!n[e.preset],"Invalid value for `options.glyph.preset`: "+e.preset),e.map=l.extend({},n[e.preset],e.map)):t.warn("ext-glyph: missing `preset` option."),this._superApply(arguments),t.$container.addClass("fancytree-ext-glyph")},nodeRenderStatus:function(e){var t,n,i=e.node,r=l(i.span),o=e.options.glyph,s=this._super(e);return i.isRootNode()||((n=r.children(".fancytree-expander").get(0))&&(t=i.expanded&&i.hasChildren()?"expanderOpen":i.isUndefined()?"expanderLazy":i.hasChildren()?"expanderClosed":"noExpander",d(i,n,"fancytree-expander",o,t)),(n=(i.tr?l("td",i.tr).find(".fancytree-checkbox"):r.children(".fancytree-checkbox")).get(0))&&(e=a.evalOption("checkbox",i,i,o,!1),i.parent&&i.parent.radiogroup||"radio"===e?d(i,n,"fancytree-checkbox fancytree-radio",o,t=i.selected?"radioSelected":"radio"):d(i,n,"fancytree-checkbox",o,t=i.selected?"checkboxSelected":i.partsel?"checkboxUnknown":"checkbox")),(n=r.children(".fancytree-icon").get(0))&&(t=i.statusNodeType||(i.folder?i.expanded&&i.hasChildren()?"folderOpen":"folder":i.expanded?"docOpen":"doc"),d(i,n,"fancytree-icon",o,t))),s},nodeSetStatus:function(e,t,n,i){var r,o=e.options.glyph,s=e.node,e=this._superApply(arguments);return"error"!==t&&"loading"!==t&&"nodata"!==t||(s.parent?(r=l(".fancytree-expander",s.span).get(0))&&d(s,r,"fancytree-expander",o,t):(r=l(".fancytree-statusnode-"+t,s[this.nodeContainerAttrName]).find(".fancytree-icon").get(0))&&d(s,r,"fancytree-icon",o,t)),e}}),l.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(c){"use strict";var u=c.ui.keyCode,o={text:[u.UP,u.DOWN],checkbox:[u.UP,u.DOWN,u.LEFT,u.RIGHT],link:[u.UP,u.DOWN,u.LEFT,u.RIGHT],radiobutton:[u.UP,u.DOWN,u.LEFT,u.RIGHT],"select-one":[u.LEFT,u.RIGHT],"select-multiple":[u.LEFT,u.RIGHT]};function s(e,t){var n,i,r,o,s,a,l=e.closest("td"),d=null;switch(t){case u.LEFT:d=l.prev();break;case u.RIGHT:d=l.next();break;case u.UP:case u.DOWN:for(n=l.parent(),r=n,s=l.get(0),a=0,r.children().each(function(){return this!==s&&(o=c(this).prop("colspan"),void(a+=o||1))}),i=a;(n=t===u.UP?n.prev():n.next()).length&&(n.is(":hidden")||!(d=function(e,t){var n,i=null,r=0;return e.children().each(function(){return t<=r?(i=c(this),!1):(n=c(this).prop("colspan"),void(r+=n||1))}),i}(n,i))||!d.find(":input,a").length););}return d}return c.ui.fancytree.registerExtension({name:"gridnav",version:"2.38.3",options:{autofocusInput:!1,handleCursorKeys:!0},treeInit:function(n){this._requireExtension("table",!0,!0),this._superApply(arguments),this.$container.addClass("fancytree-ext-gridnav"),this.$container.on("focusin",function(e){var t=c.ui.fancytree.getNode(e.target);t&&!t.isActive()&&(e=n.tree._makeHookContext(t,e),n.tree._callHook("nodeSetActive",e,!0))})},nodeSetActive:function(e,t,n){var i=e.options.gridnav,r=e.node,o=e.originalEvent||{},o=c(o.target).is(":input");t=!1!==t,this._superApply(arguments),t&&(e.options.titlesTabbable?(o||(c(r.span).find("span.fancytree-title").focus(),r.setFocus()),e.tree.$container.attr("tabindex","-1")):i.autofocusInput&&!o&&c(r.tr||r.span).find(":input:enabled").first().focus())},nodeKeydown:function(e){var t,n,i=e.options.gridnav,r=e.originalEvent,e=c(r.target);return e.is(":input:enabled")?t=e.prop("type"):e.is("a")&&(t="link"),t&&i.handleCursorKeys?!((t=o[t])&&0<=c.inArray(r.which,t)&&(n=s(e,r.which))&&n.length)||(n.find(":input:enabled,a").focus(),!1):this._superApply(arguments)}}),c.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree","./jquery.fancytree.table"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree.table"),module.exports=t(require("jquery"))):t(jQuery),t=function(s){"use strict";return s.ui.fancytree.registerExtension({name:"multi",version:"2.38.3",options:{allowNoSelect:!1,mode:"sameParent"},treeInit:function(e){this._superApply(arguments),this.$container.addClass("fancytree-ext-multi"),1===e.options.selectMode&&s.error("Fancytree ext-multi: selectMode: 1 (single) is not compatible.")},nodeClick:function(e){var t=e.tree,n=e.node,i=t.getActiveNode()||t.getFirstChild(),r="checkbox"===e.targetType,o="expander"===e.targetType;switch(s.ui.fancytree.eventToString(e.originalEvent)){case"click":if(o)break;r||(t.selectAll(!1),n.setSelected());break;case"shift+click":t.visitRows(function(e){if(e.setSelected(),e===n)return!1},{start:i,reverse:i.isBelowOf(n)});break;case"ctrl+click":case"meta+click":return void n.toggleSelected()}return this._superApply(arguments)},nodeKeydown:function(e){var t=e.tree,n=e.node,i=e.originalEvent;switch(s.ui.fancytree.eventToString(i)){case"up":case"down":t.selectAll(!1),n.navigate(i.which,!0),t.getActiveNode().setSelected();break;case"shift+up":case"shift+down":n.navigate(i.which,!0),t.getActiveNode().setSelected()}return this._superApply(arguments)}}),s.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(p){"use strict";var t=null,n=null,i=null,r=p.ui.fancytree.assert,u="active",g="expanded",h="focus",f="selected";try{r(window.localStorage&&window.localStorage.getItem),n={get:function(e){return window.localStorage.getItem(e)},set:function(e,t){window.localStorage.setItem(e,t)},remove:function(e){window.localStorage.removeItem(e)}}}catch(e){p.ui.fancytree.warn("Could not access window.localStorage",e)}try{r(window.sessionStorage&&window.sessionStorage.getItem),i={get:function(e){return window.sessionStorage.getItem(e)},set:function(e,t){window.sessionStorage.setItem(e,t)},remove:function(e){window.sessionStorage.removeItem(e)}}}catch(e){p.ui.fancytree.warn("Could not access window.sessionStorage",e)}return"function"==typeof Cookies?t={get:Cookies.get,set:function(e,t){Cookies.set(e,t,this.options.persist.cookie)},remove:Cookies.remove}:p&&"function"==typeof p.cookie&&(t={get:p.cookie,set:function(e,t){p.cookie(e,t,this.options.persist.cookie)},remove:p.removeCookie}),p.ui.fancytree._FancytreeClass.prototype.clearPersistData=function(e){var t=this.ext.persist,n=t.cookiePrefix;0<=(e=e||"active expanded focus selected").indexOf(u)&&t._data(n+u,null),0<=e.indexOf(g)&&t._data(n+g,null),0<=e.indexOf(h)&&t._data(n+h,null),0<=e.indexOf(f)&&t._data(n+f,null)},p.ui.fancytree._FancytreeClass.prototype.clearCookies=function(e){return this.warn("'tree.clearCookies()' is deprecated since v2.27.0: use 'clearPersistData()' instead."),this.clearPersistData(e)},p.ui.fancytree._FancytreeClass.prototype.getPersistData=function(){var e=this.ext.persist,t=e.cookiePrefix,n=e.cookieDelimiter,i={};return i[u]=e._data(t+u),i[g]=(e._data(t+g)||"").split(n),i[f]=(e._data(t+f)||"").split(n),i[h]=e._data(t+h),i},p.ui.fancytree.registerExtension({name:"persist",version:"2.38.3",options:{cookieDelimiter:"~",cookiePrefix:void 0,cookie:{raw:!1,expires:"",path:"",domain:"",secure:!1},expandLazy:!1,expandOpts:void 0,fireActivate:!0,overrideSource:!0,store:"auto",types:"active expanded focus selected"},_data:function(e,t){var n=this._local.store;if(void 0===t)return n.get.call(this,e);null===t?n.remove.call(this,e):n.set.call(this,e,t)},_appendKey:function(e,t,n){t=""+t;var i=this._local,r=this.options.persist.cookieDelimiter,o=i.cookiePrefix+e,s=i._data(o),e=s?s.split(r):[],s=p.inArray(t,e);0<=s&&e.splice(s,1),n&&e.push(t),i._data(o,e.join(r))},treeInit:function(e){var a=e.tree,l=e.options,d=this._local,c=this.options.persist;return d.cookiePrefix=c.cookiePrefix||"fancytree-"+a._id+"-",d.storeActive=0<=c.types.indexOf(u),d.storeExpanded=0<=c.types.indexOf(g),d.storeSelected=0<=c.types.indexOf(f),d.storeFocus=0<=c.types.indexOf(h),d.store=null,"auto"===c.store&&(c.store=n?"local":"cookie"),p.isPlainObject(c.store)?d.store=c.store:"cookie"===c.store?d.store=t:"local"!==c.store&&"session"!==c.store||(d.store="local"===c.store?n:i),r(d.store,"Need a valid store."),a.$div.on("fancytreeinit",function(e){var t,n,i,r,o,s;!1!==a._triggerTreeEvent("beforeRestore",null,{})&&(i=d._data(d.cookiePrefix+h),r=!1===c.fireActivate,o=d._data(d.cookiePrefix+g),s=o&&o.split(c.cookieDelimiter),(d.storeExpanded?function e(t,n,i,r,o){var s,a,l,d,c=!1,u=t.options.persist.expandOpts,h=[],f=[];for(i=i||[],o=o||p.Deferred(),s=0,l=i.length;s<l;s++)a=i[s],(d=t.getNodeByKey(a))?r&&d.isUndefined()?(c=!0,t.debug("_loadLazyNodes: "+d+" is lazy: loading..."),"expand"===r?h.push(d.setExpanded(!0,u)):h.push(d.load())):(t.debug("_loadLazyNodes: "+d+" already loaded."),d.setExpanded(!0,u)):(f.push(a),t.debug("_loadLazyNodes: "+d+" was not yet found."));return p.when.apply(p,h).always(function(){if(c&&0<f.length)e(t,n,f,r,o);else{if(f.length)for(t.warn("_loadLazyNodes: could not load those keys: ",f),s=0,l=f.length;s<l;s++)a=i[s],n._appendKey(g,i[s],!1);o.resolve()}}),o}(a,d,s,!!c.expandLazy&&"expand",null):(new p.Deferred).resolve()).done(function(){if(d.storeSelected){if(o=d._data(d.cookiePrefix+f))for(s=o.split(c.cookieDelimiter),t=0;t<s.length;t++)(n=a.getNodeByKey(s[t]))?(void 0===n.selected||c.overrideSource&&!1===n.selected)&&(n.selected=!0,n.renderStatus()):d._appendKey(f,s[t],!1);3===a.options.selectMode&&a.visit(function(e){if(e.selected)return e.fixSelection3AfterClick(),"skip"})}d.storeActive&&(!(o=d._data(d.cookiePrefix+u))||!l.persist.overrideSource&&a.activeNode||(n=a.getNodeByKey(o))&&(n.debug("persist: set active",o),n.setActive(!0,{noFocus:!0,noEvents:r}))),d.storeFocus&&i&&(n=a.getNodeByKey(i))&&(a.options.titlesTabbable?p(n.span).find(".fancytree-title"):p(a.$container)).focus(),a._triggerTreeEvent("restore",null,{})}))}),this._superApply(arguments)},nodeSetActive:function(e,t,n){var i=this._local;return t=!1!==t,t=this._superApply(arguments),i.storeActive&&i._data(i.cookiePrefix+u,this.activeNode?this.activeNode.key:null),t},nodeSetExpanded:function(e,t,n){var i=e.node,r=this._local;return t=!1!==t,e=this._superApply(arguments),r.storeExpanded&&r._appendKey(g,i.key,t),e},nodeSetFocus:function(e,t){var n=this._local;return t=!1!==t,t=this._superApply(arguments),n.storeFocus&&n._data(n.cookiePrefix+h,this.focusNode?this.focusNode.key:null),t},nodeSetSelected:function(e,t,n){var i=e.tree,r=e.node,o=this._local;return t=!1!==t,t=this._superApply(arguments),o.storeSelected&&(3===i.options.selectMode?(i=(i=p.map(i.getSelectedNodes(!0),function(e){return e.key})).join(e.options.persist.cookieDelimiter),o._data(o.cookiePrefix+f,i)):o._appendKey(f,r.key,r.selected)),t}}),p.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(m){"use strict";var b=m.ui.fancytree.assert;function x(e,n){e.visit(function(e){var t=e.tr;if(t&&(t.style.display=e.hide||!n?"none":""),!e.expanded)return"skip"})}return m.ui.fancytree.registerExtension({name:"table",version:"2.38.3",options:{checkboxColumnIdx:null,indentation:16,mergeStatusColumns:!0,nodeColumnIdx:0},treeInit:function(e){var t,n,i,r=e.tree,o=e.options,s=o.table,a=r.widget.element;if(null!=s.customStatus&&(null==o.renderStatusColumns?(r.warn("The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' instead."),o.renderStatusColumns=s.customStatus):m.error("The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' only instead.")),o.renderStatusColumns&&!0===o.renderStatusColumns&&(o.renderStatusColumns=o.renderColumns),a.addClass("fancytree-container fancytree-ext-table"),(i=a.find(">tbody")).length||(a.find(">tr").length&&m.error("Expected table > tbody > tr. If you see this please open an issue."),i=m("<tbody>").appendTo(a)),r.tbody=i[0],r.columnCount=m("thead >tr",a).last().find(">th",a).length,(n=i.children("tr").first()).length)e=n.children("td").length,r.columnCount&&e!==r.columnCount&&(r.warn("Column count mismatch between thead ("+r.columnCount+") and tbody ("+e+"): using tbody."),r.columnCount=e),n=n.clone();else for(b(1<=r.columnCount,"Need either <thead> or <tbody> with <td> elements to determine column count."),n=m("<tr />"),t=0;t<r.columnCount;t++)n.append("<td />");n.find(">td").eq(s.nodeColumnIdx).html("<span class='fancytree-node' />"),o.aria&&(n.attr("role","row"),n.find("td").attr("role","gridcell")),r.rowFragment=document.createDocumentFragment(),r.rowFragment.appendChild(n.get(0)),i.empty(),r.statusClassPropName="tr",r.ariaPropName="tr",this.nodeContainerAttrName="tr",r.$container=a,this._superApply(arguments),m(r.rootNode.ul).remove(),r.rootNode.ul=null,this.$container.attr("tabindex",o.tabindex),o.aria&&r.$container.attr("role","treegrid").attr("aria-readonly",!0)},nodeRemoveChildMarkup:function(e){e.node.visit(function(e){e.tr&&(m(e.tr).remove(),e.tr=null)})},nodeRemoveMarkup:function(e){var t=e.node;t.tr&&(m(t.tr).remove(),t.tr=null),this.nodeRemoveChildMarkup(e)},nodeRender:function(e,t,n,i,r){var o,s,a,l,d,c,u,h,f,p=e.tree,g=e.node,y=e.options,v=!g.parent;if(!1!==p._enableUpdate){if(r||(e.hasCollapsedParents=g.parent&&!g.parent.expanded),!v)if(g.tr&&t&&this.nodeRemoveMarkup(e),g.tr)t?this.nodeRenderTitle(e):this.nodeRenderStatus(e);else{if(e.hasCollapsedParents&&!n)return;d=p.rowFragment.firstChild.cloneNode(!0),h=function(e){var t,n,i=e.parent,r=i?i.children:null;if(r&&1<r.length&&r[0]!==e)for(n=r[m.inArray(e,r)-1],b(n.tr);n.children&&n.children.length&&(t=n.children[n.children.length-1]).tr;)n=t;else n=i;return n}(g),b(h),(!0===i&&r||n&&e.hasCollapsedParents)&&(d.style.display="none"),h.tr?(f=h.tr).parentNode.insertBefore(d,f.nextSibling):(b(!h.parent,"prev. row must have a tr, or be system root"),(h=p.tbody).insertBefore(d,h.firstChild)),g.tr=d,g.key&&y.generateIds&&(g.tr.id=y.idPrefix+g.key),(g.tr.ftnode=g).span=m("span.fancytree-node",g.tr).get(0),this.nodeRenderTitle(e),y.createNode&&y.createNode.call(p,{type:"createNode"},e)}if(y.renderNode&&y.renderNode.call(p,{type:"renderNode"},e),(o=g.children)&&(v||n||g.expanded))for(a=0,l=o.length;a<l;a++)(u=m.extend({},e,{node:o[a]})).hasCollapsedParents=u.hasCollapsedParents||!g.expanded,this.nodeRender(u,t,n,i,!0);o&&!r&&(c=g.tr||null,s=p.tbody.firstChild,g.visit(function(e){var t;e.tr&&(e.parent.expanded||"none"===e.tr.style.display||(e.tr.style.display="none",x(e,!1)),e.tr.previousSibling!==c&&(g.debug("_fixOrder: mismatch at node: "+e),t=c?c.nextSibling:s,p.tbody.insertBefore(e.tr,t)),c=e.tr)}))}},nodeRenderTitle:function(e,t){var n=e.tree,i=e.node,r=e.options,o=i.isStatusNode(),s=this._super(e,t);return i.isRootNode()||(r.checkbox&&!o&&null!=r.table.checkboxColumnIdx&&(t=m("span.fancytree-checkbox",i.span),m(i.tr).find("td").eq(+r.table.checkboxColumnIdx).html(t)),this.nodeRenderStatus(e),o?r.renderStatusColumns?r.renderStatusColumns.call(n,{type:"renderStatusColumns"},e):r.table.mergeStatusColumns&&i.isTopLevel()&&m(i.tr).find(">td").eq(0).prop("colspan",n.columnCount).text(i.title).addClass("fancytree-status-merged").nextAll().remove():r.renderColumns&&r.renderColumns.call(n,{type:"renderColumns"},e)),s},nodeRenderStatus:function(e){var t=e.node,n=e.options;this._super(e),m(t.tr).removeClass("fancytree-node"),e=(t.getLevel()-1)*n.table.indentation,n.rtl?m(t.span).css({paddingRight:e+"px"}):m(t.span).css({paddingLeft:e+"px"})},nodeSetExpanded:function(t,n,i){if(n=!1!==n,t.node.expanded&&n||!t.node.expanded&&!n)return this._superApply(arguments);var r=new m.Deferred,e=m.extend({},i,{noEvents:!0,noAnimation:!0});function o(e){e?(x(t.node,n),n&&t.options.autoScroll&&!i.noAnimation&&t.node.hasChildren()?t.node.getLastChild().scrollIntoView(!0,{topNode:t.node}).always(function(){i.noEvents||t.tree._triggerNodeEvent(n?"expand":"collapse",t),r.resolveWith(t.node)}):(i.noEvents||t.tree._triggerNodeEvent(n?"expand":"collapse",t),r.resolveWith(t.node))):(i.noEvents||t.tree._triggerNodeEvent(n?"expand":"collapse",t),r.rejectWith(t.node))}return i=i||{},this._super(t,n,e).done(function(){o(!0)}).fail(function(){o(!1)}),r.promise()},nodeSetStatus:function(e,t,n,i){return"ok"!==t||(e=(e=e.node).children?e.children[0]:null)&&e.isStatusNode()&&m(e.tr).remove(),this._superApply(arguments)},treeClear:function(e){return this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode)),this._superApply(arguments)},treeDestroy:function(e){return this.$container.find("tbody").empty(),this.$source&&this.$source.removeClass("fancytree-helper-hidden"),this._superApply(arguments)}}),m.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(o){"use strict";return o.ui.fancytree.registerExtension({name:"themeroller",version:"2.38.3",options:{activeClass:"ui-state-active",addClass:"ui-corner-all",focusClass:"ui-state-focus",hoverClass:"ui-state-hover",selectedClass:"ui-state-highlight"},treeInit:function(e){var t=e.widget.element,n=e.options.themeroller;this._superApply(arguments),"TABLE"===t[0].nodeName?(t.addClass("ui-widget ui-corner-all"),t.find(">thead tr").addClass("ui-widget-header"),t.find(">tbody").addClass("ui-widget-conent")):t.addClass("ui-widget ui-widget-content ui-corner-all"),t.on("mouseenter mouseleave",".fancytree-node",function(e){var t=o.ui.fancytree.getNode(e.target),e="mouseenter"===e.type;o(t.tr||t.span).toggleClass(n.hoverClass+" "+n.addClass,e)})},treeDestroy:function(e){this._superApply(arguments),e.widget.element.removeClass("ui-widget ui-widget-content ui-corner-all")},nodeRenderStatus:function(e){var t={},n=e.node,i=o(n.tr||n.span),r=e.options.themeroller;this._super(e),t[r.activeClass]=!1,t[r.focusClass]=!1,t[r.selectedClass]=!1,n.isActive()&&(t[r.activeClass]=!0),n.hasFocus()&&(t[r.focusClass]=!0),n.isSelected()&&!n.isActive()&&(t[r.selectedClass]=!0),i.toggleClass(r.activeClass,t[r.activeClass]),i.toggleClass(r.focusClass,t[r.focusClass]),i.toggleClass(r.selectedClass,t[r.selectedClass]),i.addClass(r.addClass)}}),o.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),t=function(d){"use strict";var c=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function u(e,t){var n=d("#"+(e="fancytree-style-"+e));if(t){n.length||(n=d("<style />").attr("id",e).addClass("fancytree-style").prop("type","text/css").appendTo("head"));try{n.html(t)}catch(e){n[0].styleSheet.cssText=t}return n}n.remove()}function h(e,t,n,i,r,o){for(var s="#"+e+" span.fancytree-level-",a=[],l=0;l<t;l++)a.push(s+(l+1)+" span.fancytree-title { padding-left: "+(l*n+i)+o+"; }");return a.push("#"+e+" div.ui-effects-wrapper ul li span.fancytree-title, #"+e+" li.fancytree-animating span.fancytree-title { padding-left: "+r+o+"; position: static; width: auto; }"),a.join("\n")}return d.ui.fancytree.registerExtension({name:"wide",version:"2.38.3",options:{iconWidth:null,iconSpacing:null,labelSpacing:null,levelOfs:null},treeCreate:function(e){this._superApply(arguments),this.$container.addClass("fancytree-ext-wide");var t=e.options.wide,n=d("<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />").appendTo(e.tree.$container),i=n.find(".fancytree-icon"),r=n.find("ul"),o=t.iconSpacing||i.css("margin-left"),s=t.iconWidth||i.css("width"),a=t.labelSpacing||"3px",l=t.levelOfs||r.css("padding-left");n.remove(),i=o.match(c)[2],o=parseFloat(o,10),t=a.match(c)[2],a=parseFloat(a,10),r=s.match(c)[2],s=parseFloat(s,10),n=l.match(c)[2],i===r&&n===r&&t===r||d.error("iconWidth, iconSpacing, and levelOfs must have the same css measure unit"),this._local.measureUnit=r,this._local.levelOfs=parseFloat(l),this._local.lineOfs=(1+(e.options.checkbox?1:0)+(!1===e.options.icon?0:1))*(s+o)+o,this._local.labelOfs=a,this._local.maxDepth=10,u(a=this.$container.uniqueId().attr("id"),h(a,this._local.maxDepth,this._local.levelOfs,this._local.lineOfs,this._local.labelOfs,this._local.measureUnit))},treeDestroy:function(e){return u(this.$container.attr("id"),null),this._superApply(arguments)},nodeRenderStatus:function(e){var t=e.node,n=t.getLevel(),i=this._super(e);return n>this._local.maxDepth&&(e=this.$container.attr("id"),this._local.maxDepth*=2,t.debug("Define global ext-wide css up to level "+this._local.maxDepth),u(e,h(e,this._local.maxDepth,this._local.levelOfs,this._local.lineOfs,this._local.labelSpacing,this._local.measureUnit))),d(t.span).addClass("fancytree-level-"+n),i}}),d.ui.fancytree},"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],t):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=t(require("jquery"))):t(jQuery),e.ui.fancytree});
+//# sourceMappingURL=jquery.fancytree-all-deps.min.js.map \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.min.js.map b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.min.js.map
new file mode 100644
index 0000000..9cadd5b
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all-deps.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"jquery.fancytree-all-deps.min.js","sources":["jquery.fancytree-all-deps.js"],"names":["$","ui","version","orig","widgetUuid","widgetHasOwnProperty","Array","prototype","hasOwnProperty","widgetSlice","slice","cleanData","elems","events","elem","i","_data","remove","triggerHandler","widget","name","base","existingConstructor","constructor","basePrototype","proxiedPrototype","namespace","split","fullName","Widget","isArray","extend","apply","concat","expr","pseudos","toLowerCase","data","options","element","this","_createWidget","arguments","length","_proto","_childConstructors","each","prop","value","_super","_superApply","args","returnValue","__super","__superApply","widgetEventPrefix","widgetName","widgetFullName","child","childPrototype","push","bridge","target","key","input","call","inputIndex","inputLength","undefined","isPlainObject","object","fn","isMethodCall","methodValue","instance","charAt","error","jquery","pushStack","get","option","_init","defaultElement","classes","disabled","create","uuid","eventNamespace","bindings","hoverable","focusable","classesElementLookup","_on","event","destroy","document","style","ownerDocument","window","defaultView","parentWindow","_getCreateOptions","_create","_setOptionDisabled","_trigger","_getCreateEventData","noop","that","_destroy","_removeClass","off","removeData","removeAttr","parts","curOption","shift","pop","_setOptions","_setOption","_setOptionClasses","classKey","elements","currentElements","addClass","_classes","keys","add","_toggleClass","enable","disable","full","processClassString","checkOption","current","nodesToBind","_","map","some","is","bindRemoveEvent","uniqueSort","not","match","extra","join","_untrackClassesElement","inArray","_off","_addClass","toggleClass","suppressDisabledCheck","handlers","delegateElement","handler","handlerProxy","hasClass","guid","eventName","selector","on","_delay","delay","setTimeout","_hoverable","mouseenter","currentTarget","mouseleave","_focusable","focusin","focusout","type","callback","Event","originalEvent","trigger","isDefaultPrevented","show","hide","method","defaultEffect","hasOptions","effectName","effect","duration","isEmptyObject","complete","effects","easing","queue","next","cachedScrollbarWidth","max","abs","rhorizontal","rvertical","roffset","rposition","rpercent","_position","getOffsets","offsets","width","height","parseFloat","test","parseCss","property","parseInt","css","isWindow","obj","Math","position","scrollbarWidth","w1","div","innerDiv","children","append","offsetWidth","w2","clientWidth","getScrollInfo","within","overflowX","isDocument","overflowY","hasOverflowX","scrollWidth","scrollHeight","getWithinInfo","withinElement","isElemWindow","nodeType","offset","left","top","scrollLeft","scrollTop","outerWidth","outerHeight","of","atOffset","targetWidth","targetHeight","targetOffset","basePosition","raw","find","scrollInfo","collision","dimensions","preventDefault","pageY","pageX","at","horizontalOffset","verticalOffset","pos","exec","collisionPosition","using","elemWidth","elemHeight","marginLeft","marginTop","collisionWidth","collisionHeight","myOffset","my","dir","props","right","bottom","feedback","horizontal","vertical","important","fit","withinOffset","collisionPosLeft","overLeft","overRight","newOverRight","collisionPosTop","overTop","overBottom","newOverBottom","flip","offsetLeft","newOverLeft","offsetTop","newOverTop","flipfit","rcssescape","fcssescape","unique","escapeSelector","ch","asCodePoint","charCodeAt","toString","sel","replace","even","odd","filter","keyCode","BACKSPACE","COMMA","DELETE","DOWN","END","ENTER","ESCAPE","HOME","LEFT","PAGE_DOWN","PAGE_UP","PERIOD","RIGHT","SPACE","TAB","UP","scrollParent","includeHidden","excludeStaticParent","overflowRegex","parents","parent","eq","uniqueId","id","removeUniqueId","jQuery","factory","define","amd","module","exports","require","fancytree","attr","FT","TEST_IMG","RegExp","REX_HTML","REX_TOOLTIP","RECURSIVE_REQUEST_ERROR","INVALID_REQUEST_TARGET_ERROR","ENTITY_MAP","&","<",">","\"","'","/","IGNORE_KEYCODES","16","17","18","SPECIAL_KEYCODES","8","9","10","13","19","20","27","32","33","34","35","36","37","38","39","40","45","46","59","61","96","97","98","99","100","101","102","103","104","105","106","107","109","110","111","112","113","114","115","116","117","118","119","120","121","122","123","144","145","173","186","187","188","189","190","191","192","219","220","221","222","MODIFIERS","91","93","MOUSE_BUTTONS","0","1","2","3","CLASS_ATTRS","CLASS_ATTR_MAP","TREE_ATTRS","NODE_ATTRS","NODE_ATTR_MAP","NODE_ATTR_LOWERCASE_MAP","NONE_NODE_DATA_MAP","active","focus","_isArray","_assert","Date","now","getTime","FancytreeNode","_findDirectChild","ptr","l","cl","_setChildren","tree","_callHook","addChildren","insertBefore","firstNode","origFirstChild","getFirstChild","origLastChild","getLastChild","nodeList","splice","render","renderStatus","ul","tr","selectMode","fixSelection3FromEndNodes","triggerModifyChild","className","addNode","node","mode","getParent","getNextSibling","addPagingNode","n","title","strings","moreData","statusNodeType","icon","partload","removeChild","appendSibling","applyCommand","cmd","opts","applyPatch","patch","_getResolvedPromise","v","IGNORE_MAP","expanded","_hasProp","_isFunction","removeChildren","isVisible","renderTitle","setExpanded","collapseSiblings","copyTo","toDict","countChildren","deep","debug","msg","debugLevel","unshift","consoleApply","discard","warn","resetLazy","discardMarkup","includeSelf","findAll","_makeNodeTitleMatcher","res","visit","findFirst","findRelatedNode","where","_changeSelectStatusAttrs","state","changed","unselectable","evalOption","unselectableStatus","selected","partsel","fixSelection3AfterClick","callOpts","flag","isSelected","radiogroup","_walk","s","allSelected","someSelected","unselState","lazy","visitParents","fromDict","dict","getChildren","hasChildren","getIndex","getIndexHier","separator","digits","getParentList","o","substr","getKeyPath","excludeSelf","sep","keyPathSeparator","getPath","getLevel","level","dtn","ac","includeRoot","part","val","path","isFunc","getPrevSibling","getSelectedNodes","stopOnParents","isStatusNode","extraClasses","indexOf","hasFocus","focusNode","info","isActive","activeNode","isBelowOf","otherNode","isChildOf","isDescendantOf","p","isExpanded","isFirstSibling","isFolder","folder","isLastSibling","isLazy","isLoaded","isLoading","_isLoading","isRoot","isRootNode","isPartsel","isPartload","rootNode","isPagingNode","isTopLevel","isUndefined","hasFilter","enableFilter","subMatchCount","lazyLoad","load","forceReload","self","wasExpanded","source","_triggerNodeEvent","always","makeVisible","deferreds","dfd","Deferred","len","noAnimation","scroll","scrollIntoView","when","done","resolve","promise","moveTo","targetNode","prevParent","targetParent","navigate","activate","KC","e","setFocus","setActive","childNode","removeClass","force","replaceWith","fail","scheduleAction","ms","timer","clearTimeout","x","Error","scrollOfs","topNode","$scrollParent","$container","tbody","body","topNodeY","nodeY","nodeHeight","span","topOfs","bottomOfs","containerHeight","$animateTarget","isParentWindow","newScrollTop","containerOffsetTop","innerHeight","clientHeight","resolveWith","stop","animate","setSelected","setStatus","status","message","details","setTitle","triggerModify","sortChildren","cmp","sort","a","b","y","recursive","classNames","wasAdded","statusElem","statusClassPropName","curClasses","_trim","toggleExpanded","toggleSelected","operation","modifyChild","visitAndLoad","_recursion","loaders","reject","then","visitSiblings","Fancytree","_makeHookContext","ctx","typeInfo","types","funcName","contextObject","_extraArgs","_setExpiringValue","_tempCache","expire","_getExpiringValue","entry","_usesExtension","extensions","_requireExtension","required","before","thisName","_local","extList","isBefore","isMissing","ext","badOrder","activateKey","getNodeByKey","opts_","refNode","getActiveNode","editCreateNode","editStart","patchList","p2","patchCount","deferredList","_makeResolveFunc","clear","count","enableUpdate","_enableUpdate","expandAll","prev","findNextNode","startNode","reMatch","_checkNode","visitRows","start","reverse","generateFormElements","selectedName","_id","activeName","$result","_appender","checked","empty","insertAfter","idx","getFocusNode","getOption","optionName","searchRoot","el","getElementById","idPrefix","ftnode","getRootNode","_hasFocus","_requestId","loadKeyPath","keyPathList","optsOrCallback","pathSegList","notifyWith","matchKey","_loadKeyPathImpl","nodeKey","remain","remainMap","tmpParent","segList","subDfd","__findChild","errMsg","rejectWith","__lazyload","reactivate","noFocus","reload","selectAll","setOption","debugTime","label","console","time","debugTimeEnd","timeEnd","result","_triggerTreeEvent","_visitRowsUp","nextIdx","siblings","siblingOfs","skipFirstNode","checkFilter","nodeClick","expand","targetType","focusOnSelect","clickFolderMode","nodeSetFocus","nodeCollapseSiblings","nodeDblclick","nodeKeydown","which","String","fromCharCode","specialModifiers","altKey","ctrlKey","metaKey","isAlnum","$target","handled","autoActivate","quicksearch","stamp","lastQuicksearchTime","lastQuicksearchTerm","matchNode","eventToString","nodeSetExpanded","nodeToggleSelected","nodeSetActive","nodeLoadChildren","ajax","resultDfd","ajaxDfd","isAsync","nodePrevParent","tag","requestId","url","debugDelay","random","round","nodeSetStatus","textStatus","jqXHR","errorObj","dataType","postProcess","response","enableAspx","d","parseJSON","errorThrown","metaData","noDataRes","nodata","noData","ctxErr","nodeLoadKeyPath","nodeRemoveChild","subCtx","nodeRemoveChildren","nodeRemoveMarkup","nodeRemoveChildMarkup","li","nodeRenderStatus","nodeRender","collapsed","_recursive","childLI","childNode1","childNode2","aria","firstTime","successorLi","parentNode","nextSibling","createElement","generateIds","appendChild","nodeRenderTitle","createNode","renderNode","display","$div","firstChild","iconTooltip","ares","role","minExpandLevel","checkbox","iconClass","_escapeTooltip","imagePath","text","escapeHtml","html","nodeTitle","tooltip","titlesTabbable","escapeTitles","innerHTML","enhanceTitle","$title","$ariaElem","isLastSib","cn","_classNames","cnList","focused","Boolean","lastsib","loading","_error","statusNodePrefix","combinedExpanderPrefix","combinedIconPrefix","noEvents","_getRejectedPromise","activeVisible","_afterLoad","prevAC","animating","autoCollapse","lastChild","autoScroll","toggleEffect","toggle","ctx2","isInput","calledByNode","activeElement","nodeSetSelected","_lastSelectIntent","lastSelectedNode","_setStatusNode","_clearStatusNode","loadError","nodeToggleExpanded","treeClear","treeCreate","treeDestroy","$source","treeInit","tabindex","checkboxAutoHide","rtl","treeLoad","$ul","rootCtx","first","parseHtml","_getElementDataAsDict","contents","treeRegisterNode","treeSetFocus","_lastMousedownNode","treeSetOption","callDefault","callCreate","callRender","treeStructureChanged","cache","copyFunctionsToData","keyboard","treeId","radio","_deprecationWarning","extension","extName","_extensions","_simpleDeepMerge","copy","clone","src","attrName","_makeVirtualFunction","_subclassObject","icons","tabbable","_bind","_unbind","ns","_ns","getNode","prevPhase","phase","et","getEventTarget","getTree","buildType","_nextId","_nextNodeKey","_FancytreeClass","_FancytreeNodeClass","jquerySupports","positionMyOfs","dottedVersion","t","verParts","testParts","isVersionAtLeast","assert","createTree","$tree","debounce","timeout","invokeAsap","fixPositionOptions","myParts","atParts","dx","dy","tcn","closest","getEventTargetType","orgEl","Element","HTMLDocument","nodeObject","treeOptions","defaultValue","treeOpt","nodeOpt","setSpanIcon","baseClass","$span","shiftKey","button","keyEventToString","overrideMethod","methodName","context","prevSuper","iPos","tmp","tmp2","$children","allData","lowerCaseAttr","$li","$liSpan","$liA","href","search","substring","registerExtension","definition","trim","unescapeHtml","childNodes","nodeValue","cond","Object","prevFunc","baseFunc","prevLocal","prevSuperApply","argArray","deferred","$el","json","uiFancytree","unselectableIgnore","hideCheckbox","defaultKey","lazyload","loaderror","fx","removeNode","columns","systemFocusElement","viewport","ariaPropName","nodeContainerAttrName","class","appendTo","countSelected","topOnly","updateCounters","$badge","extOpts","childcounter","childCounter","hideZeros","hideExpanded","widgetMethod1","arg1","foo","_appendCounter","bar","hashMurmur3","asString","seed","h1b","k1","remainder","bytes","h1","c1","c2","getCloneList","refList","refMap","refKey","keyMap","isClone","reRegister","prevKey","prevRefKey","modified","setRefKey","getNodesByRef","changeRefKey","oldRefKey","newRefKey","highlightActiveClones","highlightClones","other","clones","arr","_removeArrayMember","scpn","$dragImage","$extraHelper","isMac","navigator","platform","classDragSource","classDragRemove","classDropAccept","classDropAfter","classDropBefore","classDropOver","classDropReject","classDropTarget","nodeMimeType","$dropMarker","SOURCE_NODE","SOURCE_NODE_LIST","$sourceList","DRAG_ENTER_RESPONSE","SUGGESTED_DROP_EFFECT","REQUESTED_DROP_EFFECT","REQUESTED_EFFECT_ALLOWED","LAST_HIT_MODE","DRAG_OVER_STAMP","_clearGlobals","offsetString","prepareDropEffectCallback","dataTransfer","effectAllowed","dnd5","dropEffect","dropEffectDefault","dropEffectSuggested","effectDefault","isMove","files","applyDropEffectCallback","allowDrop","handleDragOver","dndOpts","sp","sensitivity","scrollSensitivity","speed","scrollSpeed","scrolled","tagName","spOfs","offsetHeight","markerOffsetX","nodeOfs","hitMode","sourceNode","markerAt","$targetTitle","relPosY","after","over","preventVoidMoves","dragOver","dropMarkerOffsetX","dropMarkerInsertOffsetX","onDropEvent","r","otherNodeList","otherNodeData","useDefaultImage","isCancelled","isSourceFtNode","preventNonNodes","preventForeignNodes","preventSameParent","preventRecursion","preventLazyParents","dragEnter","autoExpandMS","dragExpand","dragLeave","nodeData","getData","JSON","parse","ex","orgSourceElem","orgSourceTree","dragDrop","contains","dragEnd","getDragNodeList","getDragNode","dropMarkerParent","multiSource","setTextTypeJson","sourceCopyHook","dragStart","dragDrag","glyph","dragStop","preventRecursiveMoves","draggable","$temp","z-index","pointer-events","prependTo","dropMarker","stringify","setData","setDragImage","bind","$input","local","edit","instOpts","eventData","isNew","orgTitle","dirty","beforeEdit","currentNode","lastDraggableAttrValue","editEnd","adjustWidthOfs","inputCss","change","stopPropagation","blur","applyChanges","_event","newVal","save","beforeClose","relatedNode","preventScroll","close","init","newNode","isEditing","allowEmpty","minWidth","triggerStart","editNode","eventStr","KeyNoData","_escapeRegex","str","_markFuzzyMatchedChars","regexMatchArray","matchingIndices","_matchingArrIdx","_mIdx","textPoses","forEach","_applyFilterImpl","branchMode","_opts","statusNode","re","reHighlight","reExoticStartChar","reExoticEndChar","temp","treeOpts","prevAutoCollapse","hideMode","leavesOnly","clearFilter","fuzzy","reduce","highlight","titleWithHighlight","lastFilterArgs","prevEnableUpdate","hideExpanders","matchedByBranch","c","autoExpand","_filterAutoExpanded","filterNodes","filterBranches","updateFilter","autoApply","$subMatchBadge","isFilterActive","isMatched","counter","hideExpandedCounter","PRESETS","awesome3","checkboxSelected","checkboxUnknown","dragHelper","expanderClosed","expanderLazy","expanderOpen","noExpander","radioSelected","doc","docOpen","folderOpen","awesome4","awesome5","radioUnknown","bootstrap3","material","setIcon","$counter","setClass","textContent","preset","NAV_KEYS","link","radiobutton","select-one","select-multiple","findNeighbourTd","$tr","colIdx","colspan","td","$td","$tdNext","findTdAtColIdx","autofocusInput","handleCursorKeys","gridnav","triggeredByInput","handleKeys","inputType","allowNoSelect","isCbClick","isExpanderClick","cookieStore","localStorageStore","sessionStorageStore","ACTIVE","EXPANDED","FOCUS","SELECTED","localStorage","getItem","set","setItem","removeItem","sessionStorage","Cookies","persist","cookie","removeCookie","clearPersistData","prefix","cookiePrefix","clearCookies","getPersistData","delim","cookieDelimiter","expires","domain","secure","expandLazy","expandOpts","fireActivate","overrideSource","store","_appendKey","cookieName","keyList","storeActive","storeExpanded","storeSelected","storeFocus","prevFocus","_loadLazyNodes","foundOne","missingKeyList","selNodes","setChildRowVisibility","checkboxColumnIdx","indentation","mergeStatusColumns","nodeColumnIdx","$row","$tbody","tableOpts","table","$table","customStatus","renderStatusColumns","renderColumns","columnCount","last","rowFragment","createDocumentFragment","firstTr","newRow","prevTr","referenceNode","hasCollapsedParents","cloneNode","prevNode","findPrevRowNode","nextTr","previousSibling","$cb","nextAll","indent","paddingRight","paddingLeft","subOpts","_afterExpand","ok","activeClass","focusClass","hoverClass","selectedClass","themeroller","nodeName","reNumUnit","defineHeadStyleElement","cssText","$headStyle","styleSheet","renderLevelCss","containerId","depth","levelOfs","lineOfs","labelOfs","measureUnit","rules","iconWidth","iconSpacing","labelSpacing","wide","$dummyLI","$dummyIcon","$dummyUL","iconSpacingUnit","labelSpacingUnit","iconWidthUnit","levelOfsUnit","maxDepth"],"mappings":"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"} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all.js b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all.js
new file mode 100644
index 0000000..44e0267
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all.js
@@ -0,0 +1,13178 @@
+/*!
+ * jquery.fancytree.js
+ * Tree view control with support for lazy loading and much more.
+ * https://github.com/mar10/fancytree/
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+/** Core Fancytree module.
+ */
+
+// UMD wrapper for the Fancytree core module
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree.ui-deps"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree.ui-deps");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ // prevent duplicate loading
+ if ($.ui && $.ui.fancytree) {
+ $.ui.fancytree.warn("Fancytree: ignored duplicate include");
+ return;
+ }
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+
+ var i,
+ attr,
+ FT = null, // initialized below
+ TEST_IMG = new RegExp(/\.|\//), // strings are considered image urls if they contain '.' or '/'
+ REX_HTML = /[&<>"'/]/g, // Escape those characters
+ REX_TOOLTIP = /[<>"'/]/g, // Don't escape `&` in tooltips
+ RECURSIVE_REQUEST_ERROR = "$recursive_request",
+ INVALID_REQUEST_TARGET_ERROR = "$request_target_invalid",
+ ENTITY_MAP = {
+ "&": "&amp;",
+ "<": "&lt;",
+ ">": "&gt;",
+ '"': "&quot;",
+ "'": "&#39;",
+ "/": "&#x2F;",
+ },
+ IGNORE_KEYCODES = { 16: true, 17: true, 18: true },
+ SPECIAL_KEYCODES = {
+ 8: "backspace",
+ 9: "tab",
+ 10: "return",
+ 13: "return",
+ // 16: null, 17: null, 18: null, // ignore shift, ctrl, alt
+ 19: "pause",
+ 20: "capslock",
+ 27: "esc",
+ 32: "space",
+ 33: "pageup",
+ 34: "pagedown",
+ 35: "end",
+ 36: "home",
+ 37: "left",
+ 38: "up",
+ 39: "right",
+ 40: "down",
+ 45: "insert",
+ 46: "del",
+ 59: ";",
+ 61: "=",
+ // 91: null, 93: null, // ignore left and right meta
+ 96: "0",
+ 97: "1",
+ 98: "2",
+ 99: "3",
+ 100: "4",
+ 101: "5",
+ 102: "6",
+ 103: "7",
+ 104: "8",
+ 105: "9",
+ 106: "*",
+ 107: "+",
+ 109: "-",
+ 110: ".",
+ 111: "/",
+ 112: "f1",
+ 113: "f2",
+ 114: "f3",
+ 115: "f4",
+ 116: "f5",
+ 117: "f6",
+ 118: "f7",
+ 119: "f8",
+ 120: "f9",
+ 121: "f10",
+ 122: "f11",
+ 123: "f12",
+ 144: "numlock",
+ 145: "scroll",
+ 173: "-",
+ 186: ";",
+ 187: "=",
+ 188: ",",
+ 189: "-",
+ 190: ".",
+ 191: "/",
+ 192: "`",
+ 219: "[",
+ 220: "\\",
+ 221: "]",
+ 222: "'",
+ },
+ MODIFIERS = {
+ 16: "shift",
+ 17: "ctrl",
+ 18: "alt",
+ 91: "meta",
+ 93: "meta",
+ },
+ MOUSE_BUTTONS = { 0: "", 1: "left", 2: "middle", 3: "right" },
+ // Boolean attributes that can be set with equivalent class names in the LI tags
+ // Note: v2.23: checkbox and hideCheckbox are *not* in this list
+ CLASS_ATTRS =
+ "active expanded focus folder lazy radiogroup selected unselectable unselectableIgnore".split(
+ " "
+ ),
+ CLASS_ATTR_MAP = {},
+ // Top-level Fancytree attributes, that can be set by dict
+ TREE_ATTRS = "columns types".split(" "),
+ // TREE_ATTR_MAP = {},
+ // Top-level FancytreeNode attributes, that can be set by dict
+ NODE_ATTRS =
+ "checkbox expanded extraClasses folder icon iconTooltip key lazy partsel radiogroup refKey selected statusNodeType title tooltip type unselectable unselectableIgnore unselectableStatus".split(
+ " "
+ ),
+ NODE_ATTR_MAP = {},
+ // Mapping of lowercase -> real name (because HTML5 data-... attribute only supports lowercase)
+ NODE_ATTR_LOWERCASE_MAP = {},
+ // Attribute names that should NOT be added to node.data
+ NONE_NODE_DATA_MAP = {
+ active: true,
+ children: true,
+ data: true,
+ focus: true,
+ };
+
+ for (i = 0; i < CLASS_ATTRS.length; i++) {
+ CLASS_ATTR_MAP[CLASS_ATTRS[i]] = true;
+ }
+ for (i = 0; i < NODE_ATTRS.length; i++) {
+ attr = NODE_ATTRS[i];
+ NODE_ATTR_MAP[attr] = true;
+ if (attr !== attr.toLowerCase()) {
+ NODE_ATTR_LOWERCASE_MAP[attr.toLowerCase()] = attr;
+ }
+ }
+ // for(i=0; i<TREE_ATTRS.length; i++) {
+ // TREE_ATTR_MAP[TREE_ATTRS[i]] = true;
+ // }
+
+ function _assert(cond, msg) {
+ // TODO: see qunit.js extractStacktrace()
+ if (!cond) {
+ msg = msg ? ": " + msg : "";
+ msg = "Fancytree assertion failed" + msg;
+
+ // consoleApply("assert", [!!cond, msg]);
+
+ // #1041: Raised exceptions may not be visible in the browser
+ // console if inside promise chains, so we also print directly:
+ $.ui.fancytree.error(msg);
+
+ // Throw exception:
+ $.error(msg);
+ }
+ }
+
+ function _hasProp(object, property) {
+ return Object.prototype.hasOwnProperty.call(object, property);
+ }
+
+ /* Replacement for the deprecated `jQuery.isFunction()`. */
+ function _isFunction(obj) {
+ return typeof obj === "function";
+ }
+
+ /* Replacement for the deprecated `jQuery.trim()`. */
+ function _trim(text) {
+ return text == null ? "" : text.trim();
+ }
+
+ /* Replacement for the deprecated `jQuery.isArray()`. */
+ var _isArray = Array.isArray;
+
+ _assert($.ui, "Fancytree requires jQuery UI (http://jqueryui.com)");
+
+ function consoleApply(method, args) {
+ var i,
+ s,
+ fn = window.console ? window.console[method] : null;
+
+ if (fn) {
+ try {
+ fn.apply(window.console, args);
+ } catch (e) {
+ // IE 8?
+ s = "";
+ for (i = 0; i < args.length; i++) {
+ s += args[i];
+ }
+ fn(s);
+ }
+ }
+ }
+
+ /* support: IE8 Polyfil for Date.now() */
+ if (!Date.now) {
+ Date.now = function now() {
+ return new Date().getTime();
+ };
+ }
+
+ /*Return true if x is a FancytreeNode.*/
+ function _isNode(x) {
+ return !!(x.tree && x.statusNodeType !== undefined);
+ }
+
+ /** Return true if dotted version string is equal or higher than requested version.
+ *
+ * See http://jsfiddle.net/mar10/FjSAN/
+ */
+ function isVersionAtLeast(dottedVersion, major, minor, patch) {
+ var i,
+ v,
+ t,
+ verParts = $.map(_trim(dottedVersion).split("."), function (e) {
+ return parseInt(e, 10);
+ }),
+ testParts = $.map(
+ Array.prototype.slice.call(arguments, 1),
+ function (e) {
+ return parseInt(e, 10);
+ }
+ );
+
+ for (i = 0; i < testParts.length; i++) {
+ v = verParts[i] || 0;
+ t = testParts[i] || 0;
+ if (v !== t) {
+ return v > t;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Deep-merge a list of objects (but replace array-type options).
+ *
+ * jQuery's $.extend(true, ...) method does a deep merge, that also merges Arrays.
+ * This variant is used to merge extension defaults with user options, and should
+ * merge objects, but override arrays (for example the `triggerStart: [...]` option
+ * of ext-edit). Also `null` values are copied over and not skipped.
+ *
+ * See issue #876
+ *
+ * Example:
+ * _simpleDeepMerge({}, o1, o2);
+ */
+ function _simpleDeepMerge() {
+ var options,
+ name,
+ src,
+ copy,
+ clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length;
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if (typeof target !== "object" && !_isFunction(target)) {
+ target = {};
+ }
+ if (i === length) {
+ throw Error("need at least two args");
+ }
+ for (; i < length; i++) {
+ // Only deal with non-null/undefined values
+ if ((options = arguments[i]) != null) {
+ // Extend the base object
+ for (name in options) {
+ if (_hasProp(options, name)) {
+ src = target[name];
+ copy = options[name];
+ // Prevent never-ending loop
+ if (target === copy) {
+ continue;
+ }
+ // Recurse if we're merging plain objects
+ // (NOTE: unlike $.extend, we don't merge arrays, but replace them)
+ if (copy && $.isPlainObject(copy)) {
+ clone = src && $.isPlainObject(src) ? src : {};
+ // Never move original objects, clone them
+ target[name] = _simpleDeepMerge(clone, copy);
+ // Don't bring in undefined values
+ } else if (copy !== undefined) {
+ target[name] = copy;
+ }
+ }
+ }
+ }
+ }
+ // Return the modified object
+ return target;
+ }
+
+ /** Return a wrapper that calls sub.methodName() and exposes
+ * this : tree
+ * this._local : tree.ext.EXTNAME
+ * this._super : base.methodName.call()
+ * this._superApply : base.methodName.apply()
+ */
+ function _makeVirtualFunction(methodName, tree, base, extension, extName) {
+ // $.ui.fancytree.debug("_makeVirtualFunction", methodName, tree, base, extension, extName);
+ // if(rexTestSuper && !rexTestSuper.test(func)){
+ // // extension.methodName() doesn't call _super(), so no wrapper required
+ // return func;
+ // }
+ // Use an immediate function as closure
+ var proxy = (function () {
+ var prevFunc = tree[methodName], // org. tree method or prev. proxy
+ baseFunc = extension[methodName], //
+ _local = tree.ext[extName],
+ _super = function () {
+ return prevFunc.apply(tree, arguments);
+ },
+ _superApply = function (args) {
+ return prevFunc.apply(tree, args);
+ };
+
+ // Return the wrapper function
+ return function () {
+ var prevLocal = tree._local,
+ prevSuper = tree._super,
+ prevSuperApply = tree._superApply;
+
+ try {
+ tree._local = _local;
+ tree._super = _super;
+ tree._superApply = _superApply;
+ return baseFunc.apply(tree, arguments);
+ } finally {
+ tree._local = prevLocal;
+ tree._super = prevSuper;
+ tree._superApply = prevSuperApply;
+ }
+ };
+ })(); // end of Immediate Function
+ return proxy;
+ }
+
+ /**
+ * Subclass `base` by creating proxy functions
+ */
+ function _subclassObject(tree, base, extension, extName) {
+ // $.ui.fancytree.debug("_subclassObject", tree, base, extension, extName);
+ for (var attrName in extension) {
+ if (typeof extension[attrName] === "function") {
+ if (typeof tree[attrName] === "function") {
+ // override existing method
+ tree[attrName] = _makeVirtualFunction(
+ attrName,
+ tree,
+ base,
+ extension,
+ extName
+ );
+ } else if (attrName.charAt(0) === "_") {
+ // Create private methods in tree.ext.EXTENSION namespace
+ tree.ext[extName][attrName] = _makeVirtualFunction(
+ attrName,
+ tree,
+ base,
+ extension,
+ extName
+ );
+ } else {
+ $.error(
+ "Could not override tree." +
+ attrName +
+ ". Use prefix '_' to create tree." +
+ extName +
+ "._" +
+ attrName
+ );
+ }
+ } else {
+ // Create member variables in tree.ext.EXTENSION namespace
+ if (attrName !== "options") {
+ tree.ext[extName][attrName] = extension[attrName];
+ }
+ }
+ }
+ }
+
+ function _getResolvedPromise(context, argArray) {
+ if (context === undefined) {
+ return $.Deferred(function () {
+ this.resolve();
+ }).promise();
+ }
+ return $.Deferred(function () {
+ this.resolveWith(context, argArray);
+ }).promise();
+ }
+
+ function _getRejectedPromise(context, argArray) {
+ if (context === undefined) {
+ return $.Deferred(function () {
+ this.reject();
+ }).promise();
+ }
+ return $.Deferred(function () {
+ this.rejectWith(context, argArray);
+ }).promise();
+ }
+
+ function _makeResolveFunc(deferred, context) {
+ return function () {
+ deferred.resolveWith(context);
+ };
+ }
+
+ function _getElementDataAsDict($el) {
+ // Evaluate 'data-NAME' attributes with special treatment for 'data-json'.
+ var d = $.extend({}, $el.data()),
+ json = d.json;
+
+ delete d.fancytree; // added to container by widget factory (old jQuery UI)
+ delete d.uiFancytree; // added to container by widget factory
+
+ if (json) {
+ delete d.json;
+ // <li data-json='...'> is already returned as object (http://api.jquery.com/data/#data-html5)
+ d = $.extend(d, json);
+ }
+ return d;
+ }
+
+ function _escapeTooltip(s) {
+ return ("" + s).replace(REX_TOOLTIP, function (s) {
+ return ENTITY_MAP[s];
+ });
+ }
+
+ // TODO: use currying
+ function _makeNodeTitleMatcher(s) {
+ s = s.toLowerCase();
+ return function (node) {
+ return node.title.toLowerCase().indexOf(s) >= 0;
+ };
+ }
+
+ function _makeNodeTitleStartMatcher(s) {
+ var reMatch = new RegExp("^" + s, "i");
+ return function (node) {
+ return reMatch.test(node.title);
+ };
+ }
+
+ /******************************************************************************
+ * FancytreeNode
+ */
+
+ /**
+ * Creates a new FancytreeNode
+ *
+ * @class FancytreeNode
+ * @classdesc A FancytreeNode represents the hierarchical data model and operations.
+ *
+ * @param {FancytreeNode} parent
+ * @param {NodeData} obj
+ *
+ * @property {Fancytree} tree The tree instance
+ * @property {FancytreeNode} parent The parent node
+ * @property {string} key Node id (must be unique inside the tree)
+ * @property {string} title Display name (may contain HTML)
+ * @property {object} data Contains all extra data that was passed on node creation
+ * @property {FancytreeNode[] | null | undefined} children Array of child nodes.<br>
+ * For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array
+ * to define a node that has no children.
+ * @property {boolean} expanded Use isExpanded(), setExpanded() to access this property.
+ * @property {string} extraClasses Additional CSS classes, added to the node's `<span>`.<br>
+ * Note: use `node.add/remove/toggleClass()` to modify.
+ * @property {boolean} folder Folder nodes have different default icons and click behavior.<br>
+ * Note: Also non-folders may have children.
+ * @property {string} statusNodeType null for standard nodes. Otherwise type of special system node: 'error', 'loading', 'nodata', or 'paging'.
+ * @property {boolean} lazy True if this node is loaded on demand, i.e. on first expansion.
+ * @property {boolean} selected Use isSelected(), setSelected() to access this property.
+ * @property {string} tooltip Alternative description used as hover popup
+ * @property {string} iconTooltip Description used as hover popup for icon. @since 2.27
+ * @property {string} type Node type, used with tree.types map. @since 2.27
+ */
+ function FancytreeNode(parent, obj) {
+ var i, l, name, cl;
+
+ this.parent = parent;
+ this.tree = parent.tree;
+ this.ul = null;
+ this.li = null; // <li id='key' ftnode=this> tag
+ this.statusNodeType = null; // if this is a temp. node to display the status of its parent
+ this._isLoading = false; // if this node itself is loading
+ this._error = null; // {message: '...'} if a load error occurred
+ this.data = {};
+
+ // TODO: merge this code with node.toDict()
+ // copy attributes from obj object
+ for (i = 0, l = NODE_ATTRS.length; i < l; i++) {
+ name = NODE_ATTRS[i];
+ this[name] = obj[name];
+ }
+ // unselectableIgnore and unselectableStatus imply unselectable
+ if (
+ this.unselectableIgnore != null ||
+ this.unselectableStatus != null
+ ) {
+ this.unselectable = true;
+ }
+ if (obj.hideCheckbox) {
+ $.error(
+ "'hideCheckbox' node option was removed in v2.23.0: use 'checkbox: false'"
+ );
+ }
+ // node.data += obj.data
+ if (obj.data) {
+ $.extend(this.data, obj.data);
+ }
+ // Copy all other attributes to this.data.NAME
+ for (name in obj) {
+ if (
+ !NODE_ATTR_MAP[name] &&
+ (this.tree.options.copyFunctionsToData ||
+ !_isFunction(obj[name])) &&
+ !NONE_NODE_DATA_MAP[name]
+ ) {
+ // node.data.NAME = obj.NAME
+ this.data[name] = obj[name];
+ }
+ }
+
+ // Fix missing key
+ if (this.key == null) {
+ // test for null OR undefined
+ if (this.tree.options.defaultKey) {
+ this.key = "" + this.tree.options.defaultKey(this);
+ _assert(this.key, "defaultKey() must return a unique key");
+ } else {
+ this.key = "_" + FT._nextNodeKey++;
+ }
+ } else {
+ this.key = "" + this.key; // Convert to string (#217)
+ }
+
+ // Fix tree.activeNode
+ // TODO: not elegant: we use obj.active as marker to set tree.activeNode
+ // when loading from a dictionary.
+ if (obj.active) {
+ _assert(
+ this.tree.activeNode === null,
+ "only one active node allowed"
+ );
+ this.tree.activeNode = this;
+ }
+ if (obj.selected) {
+ // #186
+ this.tree.lastSelectedNode = this;
+ }
+ // TODO: handle obj.focus = true
+
+ // Create child nodes
+ cl = obj.children;
+ if (cl) {
+ if (cl.length) {
+ this._setChildren(cl);
+ } else {
+ // if an empty array was passed for a lazy node, keep it, in order to mark it 'loaded'
+ this.children = this.lazy ? [] : null;
+ }
+ } else {
+ this.children = null;
+ }
+ // Add to key/ref map (except for root node)
+ // if( parent ) {
+ this.tree._callHook("treeRegisterNode", this.tree, true, this);
+ // }
+ }
+
+ FancytreeNode.prototype = /** @lends FancytreeNode# */ {
+ /* Return the direct child FancytreeNode with a given key, index. */
+ _findDirectChild: function (ptr) {
+ var i,
+ l,
+ cl = this.children;
+
+ if (cl) {
+ if (typeof ptr === "string") {
+ for (i = 0, l = cl.length; i < l; i++) {
+ if (cl[i].key === ptr) {
+ return cl[i];
+ }
+ }
+ } else if (typeof ptr === "number") {
+ return this.children[ptr];
+ } else if (ptr.parent === this) {
+ return ptr;
+ }
+ }
+ return null;
+ },
+ // TODO: activate()
+ // TODO: activateSilently()
+ /* Internal helper called in recursive addChildren sequence.*/
+ _setChildren: function (children) {
+ _assert(
+ children && (!this.children || this.children.length === 0),
+ "only init supported"
+ );
+ this.children = [];
+ for (var i = 0, l = children.length; i < l; i++) {
+ this.children.push(new FancytreeNode(this, children[i]));
+ }
+ this.tree._callHook(
+ "treeStructureChanged",
+ this.tree,
+ "setChildren"
+ );
+ },
+ /**
+ * Append (or insert) a list of child nodes.
+ *
+ * @param {NodeData[]} children array of child node definitions (also single child accepted)
+ * @param {FancytreeNode | string | Integer} [insertBefore] child node (or key or index of such).
+ * If omitted, the new children are appended.
+ * @returns {FancytreeNode} first child added
+ *
+ * @see FancytreeNode#applyPatch
+ */
+ addChildren: function (children, insertBefore) {
+ var i,
+ l,
+ pos,
+ origFirstChild = this.getFirstChild(),
+ origLastChild = this.getLastChild(),
+ firstNode = null,
+ nodeList = [];
+
+ if ($.isPlainObject(children)) {
+ children = [children];
+ }
+ if (!this.children) {
+ this.children = [];
+ }
+ for (i = 0, l = children.length; i < l; i++) {
+ nodeList.push(new FancytreeNode(this, children[i]));
+ }
+ firstNode = nodeList[0];
+ if (insertBefore == null) {
+ this.children = this.children.concat(nodeList);
+ } else {
+ // Returns null if insertBefore is not a direct child:
+ insertBefore = this._findDirectChild(insertBefore);
+ pos = $.inArray(insertBefore, this.children);
+ _assert(pos >= 0, "insertBefore must be an existing child");
+ // insert nodeList after children[pos]
+ this.children.splice.apply(
+ this.children,
+ [pos, 0].concat(nodeList)
+ );
+ }
+ if (origFirstChild && !insertBefore) {
+ // #708: Fast path -- don't render every child of root, just the new ones!
+ // #723, #729: but only if it's appended to an existing child list
+ for (i = 0, l = nodeList.length; i < l; i++) {
+ nodeList[i].render(); // New nodes were never rendered before
+ }
+ // Adjust classes where status may have changed
+ // Has a first child
+ if (origFirstChild !== this.getFirstChild()) {
+ // Different first child -- recompute classes
+ origFirstChild.renderStatus();
+ }
+ if (origLastChild !== this.getLastChild()) {
+ // Different last child -- recompute classes
+ origLastChild.renderStatus();
+ }
+ } else if (!this.parent || this.parent.ul || this.tr) {
+ // render if the parent was rendered (or this is a root node)
+ this.render();
+ }
+ if (this.tree.options.selectMode === 3) {
+ this.fixSelection3FromEndNodes();
+ }
+ this.triggerModifyChild(
+ "add",
+ nodeList.length === 1 ? nodeList[0] : null
+ );
+ return firstNode;
+ },
+ /**
+ * Add class to node's span tag and to .extraClasses.
+ *
+ * @param {string} className class name
+ *
+ * @since 2.17
+ */
+ addClass: function (className) {
+ return this.toggleClass(className, true);
+ },
+ /**
+ * Append or prepend a node, or append a child node.
+ *
+ * This a convenience function that calls addChildren()
+ *
+ * @param {NodeData} node node definition
+ * @param {string} [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')
+ * @returns {FancytreeNode} new node
+ */
+ addNode: function (node, mode) {
+ if (mode === undefined || mode === "over") {
+ mode = "child";
+ }
+ switch (mode) {
+ case "after":
+ return this.getParent().addChildren(
+ node,
+ this.getNextSibling()
+ );
+ case "before":
+ return this.getParent().addChildren(node, this);
+ case "firstChild":
+ // Insert before the first child if any
+ var insertBefore = this.children ? this.children[0] : null;
+ return this.addChildren(node, insertBefore);
+ case "child":
+ case "over":
+ return this.addChildren(node);
+ }
+ _assert(false, "Invalid mode: " + mode);
+ },
+ /**Add child status nodes that indicate 'More...', etc.
+ *
+ * This also maintains the node's `partload` property.
+ * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.
+ * @param {string} [mode='child'] 'child'|firstChild'
+ * @since 2.15
+ */
+ addPagingNode: function (node, mode) {
+ var i, n;
+
+ mode = mode || "child";
+ if (node === false) {
+ for (i = this.children.length - 1; i >= 0; i--) {
+ n = this.children[i];
+ if (n.statusNodeType === "paging") {
+ this.removeChild(n);
+ }
+ }
+ this.partload = false;
+ return;
+ }
+ node = $.extend(
+ {
+ title: this.tree.options.strings.moreData,
+ statusNodeType: "paging",
+ icon: false,
+ },
+ node
+ );
+ this.partload = true;
+ return this.addNode(node, mode);
+ },
+ /**
+ * Append new node after this.
+ *
+ * This a convenience function that calls addNode(node, 'after')
+ *
+ * @param {NodeData} node node definition
+ * @returns {FancytreeNode} new node
+ */
+ appendSibling: function (node) {
+ return this.addNode(node, "after");
+ },
+ /**
+ * (experimental) Apply a modification (or navigation) operation.
+ *
+ * @param {string} cmd
+ * @param {object} [opts]
+ * @see Fancytree#applyCommand
+ * @since 2.32
+ */
+ applyCommand: function (cmd, opts) {
+ return this.tree.applyCommand(cmd, this, opts);
+ },
+ /**
+ * Modify existing child nodes.
+ *
+ * @param {NodePatch} patch
+ * @returns {$.Promise}
+ * @see FancytreeNode#addChildren
+ */
+ applyPatch: function (patch) {
+ // patch [key, null] means 'remove'
+ if (patch === null) {
+ this.remove();
+ return _getResolvedPromise(this);
+ }
+ // TODO: make sure that root node is not collapsed or modified
+ // copy (most) attributes to node.ATTR or node.data.ATTR
+ var name,
+ promise,
+ v,
+ IGNORE_MAP = { children: true, expanded: true, parent: true }; // TODO: should be global
+
+ for (name in patch) {
+ if (_hasProp(patch, name)) {
+ v = patch[name];
+ if (!IGNORE_MAP[name] && !_isFunction(v)) {
+ if (NODE_ATTR_MAP[name]) {
+ this[name] = v;
+ } else {
+ this.data[name] = v;
+ }
+ }
+ }
+ }
+ // Remove and/or create children
+ if (_hasProp(patch, "children")) {
+ this.removeChildren();
+ if (patch.children) {
+ // only if not null and not empty list
+ // TODO: addChildren instead?
+ this._setChildren(patch.children);
+ }
+ // TODO: how can we APPEND or INSERT child nodes?
+ }
+ if (this.isVisible()) {
+ this.renderTitle();
+ this.renderStatus();
+ }
+ // Expand collapse (final step, since this may be async)
+ if (_hasProp(patch, "expanded")) {
+ promise = this.setExpanded(patch.expanded);
+ } else {
+ promise = _getResolvedPromise(this);
+ }
+ return promise;
+ },
+ /** Collapse all sibling nodes.
+ * @returns {$.Promise}
+ */
+ collapseSiblings: function () {
+ return this.tree._callHook("nodeCollapseSiblings", this);
+ },
+ /** Copy this node as sibling or child of `node`.
+ *
+ * @param {FancytreeNode} node source node
+ * @param {string} [mode=child] 'before' | 'after' | 'child'
+ * @param {Function} [map] callback function(NodeData, FancytreeNode) that could modify the new node
+ * @returns {FancytreeNode} new
+ */
+ copyTo: function (node, mode, map) {
+ return node.addNode(this.toDict(true, map), mode);
+ },
+ /** Count direct and indirect children.
+ *
+ * @param {boolean} [deep=true] pass 'false' to only count direct children
+ * @returns {int} number of child nodes
+ */
+ countChildren: function (deep) {
+ var cl = this.children,
+ i,
+ l,
+ n;
+ if (!cl) {
+ return 0;
+ }
+ n = cl.length;
+ if (deep !== false) {
+ for (i = 0, l = n; i < l; i++) {
+ n += cl[i].countChildren();
+ }
+ }
+ return n;
+ },
+ // TODO: deactivate()
+ /** Write to browser console if debugLevel >= 4 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ debug: function (msg) {
+ if (this.tree.options.debugLevel >= 4) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("log", arguments);
+ }
+ },
+ /** Deprecated.
+ * @deprecated since 2014-02-16. Use resetLazy() instead.
+ */
+ discard: function () {
+ this.warn(
+ "FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."
+ );
+ return this.resetLazy();
+ },
+ /** Remove DOM elements for all descendents. May be called on .collapse event
+ * to keep the DOM small.
+ * @param {boolean} [includeSelf=false]
+ */
+ discardMarkup: function (includeSelf) {
+ var fn = includeSelf ? "nodeRemoveMarkup" : "nodeRemoveChildMarkup";
+ this.tree._callHook(fn, this);
+ },
+ /** Write error to browser console if debugLevel >= 1 (prepending tree info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ error: function (msg) {
+ if (this.tree.options.debugLevel >= 1) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("error", arguments);
+ }
+ },
+ /**Find all nodes that match condition (excluding self).
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode[]} array of nodes (may be empty)
+ */
+ findAll: function (match) {
+ match = _isFunction(match) ? match : _makeNodeTitleMatcher(match);
+ var res = [];
+ this.visit(function (n) {
+ if (match(n)) {
+ res.push(n);
+ }
+ });
+ return res;
+ },
+ /**Find first node that matches condition (excluding self).
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode} matching node or null
+ * @see FancytreeNode#findAll
+ */
+ findFirst: function (match) {
+ match = _isFunction(match) ? match : _makeNodeTitleMatcher(match);
+ var res = null;
+ this.visit(function (n) {
+ if (match(n)) {
+ res = n;
+ return false;
+ }
+ });
+ return res;
+ },
+ /** Find a node relative to self.
+ *
+ * @param {number|string} where The keyCode that would normally trigger this move,
+ * or a keyword ('down', 'first', 'last', 'left', 'parent', 'right', 'up').
+ * @returns {FancytreeNode}
+ * @since v2.31
+ */
+ findRelatedNode: function (where, includeHidden) {
+ return this.tree.findRelatedNode(this, where, includeHidden);
+ },
+ /* Apply selection state (internal use only) */
+ _changeSelectStatusAttrs: function (state) {
+ var changed = false,
+ opts = this.tree.options,
+ unselectable = FT.evalOption(
+ "unselectable",
+ this,
+ this,
+ opts,
+ false
+ ),
+ unselectableStatus = FT.evalOption(
+ "unselectableStatus",
+ this,
+ this,
+ opts,
+ undefined
+ );
+
+ if (unselectable && unselectableStatus != null) {
+ state = unselectableStatus;
+ }
+ switch (state) {
+ case false:
+ changed = this.selected || this.partsel;
+ this.selected = false;
+ this.partsel = false;
+ break;
+ case true:
+ changed = !this.selected || !this.partsel;
+ this.selected = true;
+ this.partsel = true;
+ break;
+ case undefined:
+ changed = this.selected || !this.partsel;
+ this.selected = false;
+ this.partsel = true;
+ break;
+ default:
+ _assert(false, "invalid state: " + state);
+ }
+ // this.debug("fixSelection3AfterLoad() _changeSelectStatusAttrs()", state, changed);
+ if (changed) {
+ this.renderStatus();
+ }
+ return changed;
+ },
+ /**
+ * Fix selection status, after this node was (de)selected in multi-hier mode.
+ * This includes (de)selecting all children.
+ */
+ fixSelection3AfterClick: function (callOpts) {
+ var flag = this.isSelected();
+
+ // this.debug("fixSelection3AfterClick()");
+
+ this.visit(function (node) {
+ node._changeSelectStatusAttrs(flag);
+ if (node.radiogroup) {
+ // #931: don't (de)select this branch
+ return "skip";
+ }
+ });
+ this.fixSelection3FromEndNodes(callOpts);
+ },
+ /**
+ * Fix selection status for multi-hier mode.
+ * Only end-nodes are considered to update the descendants branch and parents.
+ * Should be called after this node has loaded new children or after
+ * children have been modified using the API.
+ */
+ fixSelection3FromEndNodes: function (callOpts) {
+ var opts = this.tree.options;
+
+ // this.debug("fixSelection3FromEndNodes()");
+ _assert(opts.selectMode === 3, "expected selectMode 3");
+
+ // Visit all end nodes and adjust their parent's `selected` and `partsel`
+ // attributes. Return selection state true, false, or undefined.
+ function _walk(node) {
+ var i,
+ l,
+ child,
+ s,
+ state,
+ allSelected,
+ someSelected,
+ unselIgnore,
+ unselState,
+ children = node.children;
+
+ if (children && children.length) {
+ // check all children recursively
+ allSelected = true;
+ someSelected = false;
+
+ for (i = 0, l = children.length; i < l; i++) {
+ child = children[i];
+ // the selection state of a node is not relevant; we need the end-nodes
+ s = _walk(child);
+ // if( !child.unselectableIgnore ) {
+ unselIgnore = FT.evalOption(
+ "unselectableIgnore",
+ child,
+ child,
+ opts,
+ false
+ );
+ if (!unselIgnore) {
+ if (s !== false) {
+ someSelected = true;
+ }
+ if (s !== true) {
+ allSelected = false;
+ }
+ }
+ }
+ // eslint-disable-next-line no-nested-ternary
+ state = allSelected
+ ? true
+ : someSelected
+ ? undefined
+ : false;
+ } else {
+ // This is an end-node: simply report the status
+ unselState = FT.evalOption(
+ "unselectableStatus",
+ node,
+ node,
+ opts,
+ undefined
+ );
+ state = unselState == null ? !!node.selected : !!unselState;
+ }
+ // #939: Keep a `partsel` flag that was explicitly set on a lazy node
+ if (
+ node.partsel &&
+ !node.selected &&
+ node.lazy &&
+ node.children == null
+ ) {
+ state = undefined;
+ }
+ node._changeSelectStatusAttrs(state);
+ return state;
+ }
+ _walk(this);
+
+ // Update parent's state
+ this.visitParents(function (node) {
+ var i,
+ l,
+ child,
+ state,
+ unselIgnore,
+ unselState,
+ children = node.children,
+ allSelected = true,
+ someSelected = false;
+
+ for (i = 0, l = children.length; i < l; i++) {
+ child = children[i];
+ unselIgnore = FT.evalOption(
+ "unselectableIgnore",
+ child,
+ child,
+ opts,
+ false
+ );
+ if (!unselIgnore) {
+ unselState = FT.evalOption(
+ "unselectableStatus",
+ child,
+ child,
+ opts,
+ undefined
+ );
+ state =
+ unselState == null
+ ? !!child.selected
+ : !!unselState;
+ // When fixing the parents, we trust the sibling status (i.e.
+ // we don't recurse)
+ if (state || child.partsel) {
+ someSelected = true;
+ }
+ if (!state) {
+ allSelected = false;
+ }
+ }
+ }
+ // eslint-disable-next-line no-nested-ternary
+ state = allSelected ? true : someSelected ? undefined : false;
+ node._changeSelectStatusAttrs(state);
+ });
+ },
+ // TODO: focus()
+ /**
+ * Update node data. If dict contains 'children', then also replace
+ * the hole sub tree.
+ * @param {NodeData} dict
+ *
+ * @see FancytreeNode#addChildren
+ * @see FancytreeNode#applyPatch
+ */
+ fromDict: function (dict) {
+ // copy all other attributes to this.data.xxx
+ for (var name in dict) {
+ if (NODE_ATTR_MAP[name]) {
+ // node.NAME = dict.NAME
+ this[name] = dict[name];
+ } else if (name === "data") {
+ // node.data += dict.data
+ $.extend(this.data, dict.data);
+ } else if (
+ !_isFunction(dict[name]) &&
+ !NONE_NODE_DATA_MAP[name]
+ ) {
+ // node.data.NAME = dict.NAME
+ this.data[name] = dict[name];
+ }
+ }
+ if (dict.children) {
+ // recursively set children and render
+ this.removeChildren();
+ this.addChildren(dict.children);
+ }
+ this.renderTitle();
+ /*
+ var children = dict.children;
+ if(children === undefined){
+ this.data = $.extend(this.data, dict);
+ this.render();
+ return;
+ }
+ dict = $.extend({}, dict);
+ dict.children = undefined;
+ this.data = $.extend(this.data, dict);
+ this.removeChildren();
+ this.addChild(children);
+ */
+ },
+ /** Return the list of child nodes (undefined for unexpanded lazy nodes).
+ * @returns {FancytreeNode[] | undefined}
+ */
+ getChildren: function () {
+ if (this.hasChildren() === undefined) {
+ // TODO: only required for lazy nodes?
+ return undefined; // Lazy node: unloaded, currently loading, or load error
+ }
+ return this.children;
+ },
+ /** Return the first child node or null.
+ * @returns {FancytreeNode | null}
+ */
+ getFirstChild: function () {
+ return this.children ? this.children[0] : null;
+ },
+ /** Return the 0-based child index.
+ * @returns {int}
+ */
+ getIndex: function () {
+ // return this.parent.children.indexOf(this);
+ return $.inArray(this, this.parent.children); // indexOf doesn't work in IE7
+ },
+ /** Return the hierarchical child index (1-based, e.g. '3.2.4').
+ * @param {string} [separator="."]
+ * @param {int} [digits=1]
+ * @returns {string}
+ */
+ getIndexHier: function (separator, digits) {
+ separator = separator || ".";
+ var s,
+ res = [];
+ $.each(this.getParentList(false, true), function (i, o) {
+ s = "" + (o.getIndex() + 1);
+ if (digits) {
+ // prepend leading zeroes
+ s = ("0000000" + s).substr(-digits);
+ }
+ res.push(s);
+ });
+ return res.join(separator);
+ },
+ /** Return the parent keys separated by options.keyPathSeparator, e.g. "/id_1/id_17/id_32".
+ *
+ * (Unlike `node.getPath()`, this method prepends a "/" and inverts the first argument.)
+ *
+ * @see FancytreeNode#getPath
+ * @param {boolean} [excludeSelf=false]
+ * @returns {string}
+ */
+ getKeyPath: function (excludeSelf) {
+ var sep = this.tree.options.keyPathSeparator;
+
+ return sep + this.getPath(!excludeSelf, "key", sep);
+ },
+ /** Return the last child of this node or null.
+ * @returns {FancytreeNode | null}
+ */
+ getLastChild: function () {
+ return this.children
+ ? this.children[this.children.length - 1]
+ : null;
+ },
+ /** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... .
+ * @returns {int}
+ */
+ getLevel: function () {
+ var level = 0,
+ dtn = this.parent;
+ while (dtn) {
+ level++;
+ dtn = dtn.parent;
+ }
+ return level;
+ },
+ /** Return the successor node (under the same parent) or null.
+ * @returns {FancytreeNode | null}
+ */
+ getNextSibling: function () {
+ // TODO: use indexOf, if available: (not in IE6)
+ if (this.parent) {
+ var i,
+ l,
+ ac = this.parent.children;
+
+ for (i = 0, l = ac.length - 1; i < l; i++) {
+ // up to length-2, so next(last) = null
+ if (ac[i] === this) {
+ return ac[i + 1];
+ }
+ }
+ }
+ return null;
+ },
+ /** Return the parent node (null for the system root node).
+ * @returns {FancytreeNode | null}
+ */
+ getParent: function () {
+ // TODO: return null for top-level nodes?
+ return this.parent;
+ },
+ /** Return an array of all parent nodes (top-down).
+ * @param {boolean} [includeRoot=false] Include the invisible system root node.
+ * @param {boolean} [includeSelf=false] Include the node itself.
+ * @returns {FancytreeNode[]}
+ */
+ getParentList: function (includeRoot, includeSelf) {
+ var l = [],
+ dtn = includeSelf ? this : this.parent;
+ while (dtn) {
+ if (includeRoot || dtn.parent) {
+ l.unshift(dtn);
+ }
+ dtn = dtn.parent;
+ }
+ return l;
+ },
+ /** Return a string representing the hierachical node path, e.g. "a/b/c".
+ * @param {boolean} [includeSelf=true]
+ * @param {string | function} [part="title"] node property name or callback
+ * @param {string} [separator="/"]
+ * @returns {string}
+ * @since v2.31
+ */
+ getPath: function (includeSelf, part, separator) {
+ includeSelf = includeSelf !== false;
+ part = part || "title";
+ separator = separator || "/";
+
+ var val,
+ path = [],
+ isFunc = _isFunction(part);
+
+ this.visitParents(function (n) {
+ if (n.parent) {
+ val = isFunc ? part(n) : n[part];
+ path.unshift(val);
+ }
+ }, includeSelf);
+ return path.join(separator);
+ },
+ /** Return the predecessor node (under the same parent) or null.
+ * @returns {FancytreeNode | null}
+ */
+ getPrevSibling: function () {
+ if (this.parent) {
+ var i,
+ l,
+ ac = this.parent.children;
+
+ for (i = 1, l = ac.length; i < l; i++) {
+ // start with 1, so prev(first) = null
+ if (ac[i] === this) {
+ return ac[i - 1];
+ }
+ }
+ }
+ return null;
+ },
+ /**
+ * Return an array of selected descendant nodes.
+ * @param {boolean} [stopOnParents=false] only return the topmost selected
+ * node (useful with selectMode 3)
+ * @returns {FancytreeNode[]}
+ */
+ getSelectedNodes: function (stopOnParents) {
+ var nodeList = [];
+ this.visit(function (node) {
+ if (node.selected) {
+ nodeList.push(node);
+ if (stopOnParents === true) {
+ return "skip"; // stop processing this branch
+ }
+ }
+ });
+ return nodeList;
+ },
+ /** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded).
+ * @returns {boolean | undefined}
+ */
+ hasChildren: function () {
+ if (this.lazy) {
+ if (this.children == null) {
+ // null or undefined: Not yet loaded
+ return undefined;
+ } else if (this.children.length === 0) {
+ // Loaded, but response was empty
+ return false;
+ } else if (
+ this.children.length === 1 &&
+ this.children[0].isStatusNode()
+ ) {
+ // Currently loading or load error
+ return undefined;
+ }
+ return true;
+ }
+ return !!(this.children && this.children.length);
+ },
+ /**
+ * Return true if node has `className` defined in .extraClasses.
+ *
+ * @param {string} className class name (separate multiple classes by space)
+ * @returns {boolean}
+ *
+ * @since 2.32
+ */
+ hasClass: function (className) {
+ return (
+ (" " + (this.extraClasses || "") + " ").indexOf(
+ " " + className + " "
+ ) >= 0
+ );
+ },
+ /** Return true if node has keyboard focus.
+ * @returns {boolean}
+ */
+ hasFocus: function () {
+ return this.tree.hasFocus() && this.tree.focusNode === this;
+ },
+ /** Write to browser console if debugLevel >= 3 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ info: function (msg) {
+ if (this.tree.options.debugLevel >= 3) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("info", arguments);
+ }
+ },
+ /** Return true if node is active (see also FancytreeNode#isSelected).
+ * @returns {boolean}
+ */
+ isActive: function () {
+ return this.tree.activeNode === this;
+ },
+ /** Return true if node is vertically below `otherNode`, i.e. rendered in a subsequent row.
+ * @param {FancytreeNode} otherNode
+ * @returns {boolean}
+ * @since 2.28
+ */
+ isBelowOf: function (otherNode) {
+ return this.getIndexHier(".", 5) > otherNode.getIndexHier(".", 5);
+ },
+ /** Return true if node is a direct child of otherNode.
+ * @param {FancytreeNode} otherNode
+ * @returns {boolean}
+ */
+ isChildOf: function (otherNode) {
+ return this.parent && this.parent === otherNode;
+ },
+ /** Return true, if node is a direct or indirect sub node of otherNode.
+ * @param {FancytreeNode} otherNode
+ * @returns {boolean}
+ */
+ isDescendantOf: function (otherNode) {
+ if (!otherNode || otherNode.tree !== this.tree) {
+ return false;
+ }
+ var p = this.parent;
+ while (p) {
+ if (p === otherNode) {
+ return true;
+ }
+ if (p === p.parent) {
+ $.error("Recursive parent link: " + p);
+ }
+ p = p.parent;
+ }
+ return false;
+ },
+ /** Return true if node is expanded.
+ * @returns {boolean}
+ */
+ isExpanded: function () {
+ return !!this.expanded;
+ },
+ /** Return true if node is the first node of its parent's children.
+ * @returns {boolean}
+ */
+ isFirstSibling: function () {
+ var p = this.parent;
+ return !p || p.children[0] === this;
+ },
+ /** Return true if node is a folder, i.e. has the node.folder attribute set.
+ * @returns {boolean}
+ */
+ isFolder: function () {
+ return !!this.folder;
+ },
+ /** Return true if node is the last node of its parent's children.
+ * @returns {boolean}
+ */
+ isLastSibling: function () {
+ var p = this.parent;
+ return !p || p.children[p.children.length - 1] === this;
+ },
+ /** Return true if node is lazy (even if data was already loaded)
+ * @returns {boolean}
+ */
+ isLazy: function () {
+ return !!this.lazy;
+ },
+ /** Return true if node is lazy and loaded. For non-lazy nodes always return true.
+ * @returns {boolean}
+ */
+ isLoaded: function () {
+ return !this.lazy || this.hasChildren() !== undefined; // Also checks if the only child is a status node
+ },
+ /** Return true if children are currently beeing loaded, i.e. a Ajax request is pending.
+ * @returns {boolean}
+ */
+ isLoading: function () {
+ return !!this._isLoading;
+ },
+ /*
+ * @deprecated since v2.4.0: Use isRootNode() instead
+ */
+ isRoot: function () {
+ return this.isRootNode();
+ },
+ /** Return true if node is partially selected (tri-state).
+ * @returns {boolean}
+ * @since 2.23
+ */
+ isPartsel: function () {
+ return !this.selected && !!this.partsel;
+ },
+ /** (experimental) Return true if this is partially loaded.
+ * @returns {boolean}
+ * @since 2.15
+ */
+ isPartload: function () {
+ return !!this.partload;
+ },
+ /** Return true if this is the (invisible) system root node.
+ * @returns {boolean}
+ * @since 2.4
+ */
+ isRootNode: function () {
+ return this.tree.rootNode === this;
+ },
+ /** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive).
+ * @returns {boolean}
+ */
+ isSelected: function () {
+ return !!this.selected;
+ },
+ /** Return true if this node is a temporarily generated system node like
+ * 'loading', 'paging', or 'error' (node.statusNodeType contains the type).
+ * @returns {boolean}
+ */
+ isStatusNode: function () {
+ return !!this.statusNodeType;
+ },
+ /** Return true if this node is a status node of type 'paging'.
+ * @returns {boolean}
+ * @since 2.15
+ */
+ isPagingNode: function () {
+ return this.statusNodeType === "paging";
+ },
+ /** Return true if this a top level node, i.e. a direct child of the (invisible) system root node.
+ * @returns {boolean}
+ * @since 2.4
+ */
+ isTopLevel: function () {
+ return this.tree.rootNode === this.parent;
+ },
+ /** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false.
+ * @returns {boolean}
+ */
+ isUndefined: function () {
+ return this.hasChildren() === undefined; // also checks if the only child is a status node
+ },
+ /** Return true if all parent nodes are expanded. Note: this does not check
+ * whether the node is scrolled into the visible part of the screen.
+ * @returns {boolean}
+ */
+ isVisible: function () {
+ var i,
+ l,
+ n,
+ hasFilter = this.tree.enableFilter,
+ parents = this.getParentList(false, false);
+
+ // TODO: check $(n.span).is(":visible")
+ // i.e. return false for nodes (but not parents) that are hidden
+ // by a filter
+ if (hasFilter && !this.match && !this.subMatchCount) {
+ // this.debug( "isVisible: HIDDEN (" + hasFilter + ", " + this.match + ", " + this.match + ")" );
+ return false;
+ }
+
+ for (i = 0, l = parents.length; i < l; i++) {
+ n = parents[i];
+
+ if (!n.expanded) {
+ // this.debug("isVisible: HIDDEN (parent collapsed)");
+ return false;
+ }
+ // if (hasFilter && !n.match && !n.subMatchCount) {
+ // this.debug("isVisible: HIDDEN (" + hasFilter + ", " + this.match + ", " + this.match + ")");
+ // return false;
+ // }
+ }
+ // this.debug("isVisible: VISIBLE");
+ return true;
+ },
+ /** Deprecated.
+ * @deprecated since 2014-02-16: use load() instead.
+ */
+ lazyLoad: function (discard) {
+ $.error(
+ "FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead."
+ );
+ },
+ /**
+ * Load all children of a lazy node if neccessary. The <i>expanded</i> state is maintained.
+ * @param {boolean} [forceReload=false] Pass true to discard any existing nodes before. Otherwise this method does nothing if the node was already loaded.
+ * @returns {$.Promise}
+ */
+ load: function (forceReload) {
+ var res,
+ source,
+ self = this,
+ wasExpanded = this.isExpanded();
+
+ _assert(this.isLazy(), "load() requires a lazy node");
+ // _assert( forceReload || this.isUndefined(), "Pass forceReload=true to re-load a lazy node" );
+ if (!forceReload && !this.isUndefined()) {
+ return _getResolvedPromise(this);
+ }
+ if (this.isLoaded()) {
+ this.resetLazy(); // also collapses
+ }
+ // This method is also called by setExpanded() and loadKeyPath(), so we
+ // have to avoid recursion.
+ source = this.tree._triggerNodeEvent("lazyLoad", this);
+ if (source === false) {
+ // #69
+ return _getResolvedPromise(this);
+ }
+ _assert(
+ typeof source !== "boolean",
+ "lazyLoad event must return source in data.result"
+ );
+ res = this.tree._callHook("nodeLoadChildren", this, source);
+ if (wasExpanded) {
+ this.expanded = true;
+ res.always(function () {
+ self.render();
+ });
+ } else {
+ res.always(function () {
+ self.renderStatus(); // fix expander icon to 'loaded'
+ });
+ }
+ return res;
+ },
+ /** Expand all parents and optionally scroll into visible area as neccessary.
+ * Promise is resolved, when lazy loading and animations are done.
+ * @param {object} [opts] passed to `setExpanded()`.
+ * Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
+ * @returns {$.Promise}
+ */
+ makeVisible: function (opts) {
+ var i,
+ self = this,
+ deferreds = [],
+ dfd = new $.Deferred(),
+ parents = this.getParentList(false, false),
+ len = parents.length,
+ effects = !(opts && opts.noAnimation === true),
+ scroll = !(opts && opts.scrollIntoView === false);
+
+ // Expand bottom-up, so only the top node is animated
+ for (i = len - 1; i >= 0; i--) {
+ // self.debug("pushexpand" + parents[i]);
+ deferreds.push(parents[i].setExpanded(true, opts));
+ }
+ $.when.apply($, deferreds).done(function () {
+ // All expands have finished
+ // self.debug("expand DONE", scroll);
+ if (scroll) {
+ self.scrollIntoView(effects).done(function () {
+ // self.debug("scroll DONE");
+ dfd.resolve();
+ });
+ } else {
+ dfd.resolve();
+ }
+ });
+ return dfd.promise();
+ },
+ /** Move this node to targetNode.
+ * @param {FancytreeNode} targetNode
+ * @param {string} mode <pre>
+ * 'child': append this node as last child of targetNode.
+ * This is the default. To be compatble with the D'n'd
+ * hitMode, we also accept 'over'.
+ * 'firstChild': add this node as first child of targetNode.
+ * 'before': add this node as sibling before targetNode.
+ * 'after': add this node as sibling after targetNode.</pre>
+ * @param {function} [map] optional callback(FancytreeNode) to allow modifcations
+ */
+ moveTo: function (targetNode, mode, map) {
+ if (mode === undefined || mode === "over") {
+ mode = "child";
+ } else if (mode === "firstChild") {
+ if (targetNode.children && targetNode.children.length) {
+ mode = "before";
+ targetNode = targetNode.children[0];
+ } else {
+ mode = "child";
+ }
+ }
+ var pos,
+ tree = this.tree,
+ prevParent = this.parent,
+ targetParent =
+ mode === "child" ? targetNode : targetNode.parent;
+
+ if (this === targetNode) {
+ return;
+ } else if (!this.parent) {
+ $.error("Cannot move system root");
+ } else if (targetParent.isDescendantOf(this)) {
+ $.error("Cannot move a node to its own descendant");
+ }
+ if (targetParent !== prevParent) {
+ prevParent.triggerModifyChild("remove", this);
+ }
+ // Unlink this node from current parent
+ if (this.parent.children.length === 1) {
+ if (this.parent === targetParent) {
+ return; // #258
+ }
+ this.parent.children = this.parent.lazy ? [] : null;
+ this.parent.expanded = false;
+ } else {
+ pos = $.inArray(this, this.parent.children);
+ _assert(pos >= 0, "invalid source parent");
+ this.parent.children.splice(pos, 1);
+ }
+ // Remove from source DOM parent
+ // if(this.parent.ul){
+ // this.parent.ul.removeChild(this.li);
+ // }
+
+ // Insert this node to target parent's child list
+ this.parent = targetParent;
+ if (targetParent.hasChildren()) {
+ switch (mode) {
+ case "child":
+ // Append to existing target children
+ targetParent.children.push(this);
+ break;
+ case "before":
+ // Insert this node before target node
+ pos = $.inArray(targetNode, targetParent.children);
+ _assert(pos >= 0, "invalid target parent");
+ targetParent.children.splice(pos, 0, this);
+ break;
+ case "after":
+ // Insert this node after target node
+ pos = $.inArray(targetNode, targetParent.children);
+ _assert(pos >= 0, "invalid target parent");
+ targetParent.children.splice(pos + 1, 0, this);
+ break;
+ default:
+ $.error("Invalid mode " + mode);
+ }
+ } else {
+ targetParent.children = [this];
+ }
+ // Parent has no <ul> tag yet:
+ // if( !targetParent.ul ) {
+ // // This is the parent's first child: create UL tag
+ // // (Hidden, because it will be
+ // targetParent.ul = document.createElement("ul");
+ // targetParent.ul.style.display = "none";
+ // targetParent.li.appendChild(targetParent.ul);
+ // }
+ // // Issue 319: Add to target DOM parent (only if node was already rendered(expanded))
+ // if(this.li){
+ // targetParent.ul.appendChild(this.li);
+ // }
+
+ // Let caller modify the nodes
+ if (map) {
+ targetNode.visit(map, true);
+ }
+ if (targetParent === prevParent) {
+ targetParent.triggerModifyChild("move", this);
+ } else {
+ // prevParent.triggerModifyChild("remove", this);
+ targetParent.triggerModifyChild("add", this);
+ }
+ // Handle cross-tree moves
+ if (tree !== targetNode.tree) {
+ // Fix node.tree for all source nodes
+ // _assert(false, "Cross-tree move is not yet implemented.");
+ this.warn("Cross-tree moveTo is experimental!");
+ this.visit(function (n) {
+ // TODO: fix selection state and activation, ...
+ n.tree = targetNode.tree;
+ }, true);
+ }
+
+ // A collaposed node won't re-render children, so we have to remove it manually
+ // if( !targetParent.expanded ){
+ // prevParent.ul.removeChild(this.li);
+ // }
+ tree._callHook("treeStructureChanged", tree, "moveTo");
+
+ // Update HTML markup
+ if (!prevParent.isDescendantOf(targetParent)) {
+ prevParent.render();
+ }
+ if (
+ !targetParent.isDescendantOf(prevParent) &&
+ targetParent !== prevParent
+ ) {
+ targetParent.render();
+ }
+ // TODO: fix selection state
+ // TODO: fix active state
+
+ /*
+ var tree = this.tree;
+ var opts = tree.options;
+ var pers = tree.persistence;
+
+ // Always expand, if it's below minExpandLevel
+ // tree.logDebug ("%s._addChildNode(%o), l=%o", this, ftnode, ftnode.getLevel());
+ if ( opts.minExpandLevel >= ftnode.getLevel() ) {
+ // tree.logDebug ("Force expand for %o", ftnode);
+ this.bExpanded = true;
+ }
+
+ // In multi-hier mode, update the parents selection state
+ // DT issue #82: only if not initializing, because the children may not exist yet
+ // if( !ftnode.data.isStatusNode() && opts.selectMode==3 && !isInitializing )
+ // ftnode._fixSelectionState();
+
+ // In multi-hier mode, update the parents selection state
+ if( ftnode.bSelected && opts.selectMode==3 ) {
+ var p = this;
+ while( p ) {
+ if( !p.hasSubSel )
+ p._setSubSel(true);
+ p = p.parent;
+ }
+ }
+ // render this node and the new child
+ if ( tree.bEnableUpdate )
+ this.render();
+ return ftnode;
+ */
+ },
+ /** Set focus relative to this node and optionally activate.
+ *
+ * 'left' collapses the node if it is expanded, or move to the parent
+ * otherwise.
+ * 'right' expands the node if it is collapsed, or move to the first
+ * child otherwise.
+ *
+ * @param {string|number} where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.
+ * (Alternatively the keyCode that would normally trigger this move,
+ * e.g. `$.ui.keyCode.LEFT` = 'left'.
+ * @param {boolean} [activate=true]
+ * @returns {$.Promise}
+ */
+ navigate: function (where, activate) {
+ var node,
+ KC = $.ui.keyCode;
+
+ // Handle optional expand/collapse action for LEFT/RIGHT
+ switch (where) {
+ case "left":
+ case KC.LEFT:
+ if (this.expanded) {
+ return this.setExpanded(false);
+ }
+ break;
+ case "right":
+ case KC.RIGHT:
+ if (!this.expanded && (this.children || this.lazy)) {
+ return this.setExpanded();
+ }
+ break;
+ }
+ // Otherwise activate or focus the related node
+ node = this.findRelatedNode(where);
+ if (node) {
+ // setFocus/setActive will scroll later (if autoScroll is specified)
+ try {
+ node.makeVisible({ scrollIntoView: false });
+ } catch (e) {} // #272
+ if (activate === false) {
+ node.setFocus();
+ return _getResolvedPromise();
+ }
+ return node.setActive();
+ }
+ this.warn("Could not find related node '" + where + "'.");
+ return _getResolvedPromise();
+ },
+ /**
+ * Remove this node (not allowed for system root).
+ */
+ remove: function () {
+ return this.parent.removeChild(this);
+ },
+ /**
+ * Remove childNode from list of direct children.
+ * @param {FancytreeNode} childNode
+ */
+ removeChild: function (childNode) {
+ return this.tree._callHook("nodeRemoveChild", this, childNode);
+ },
+ /**
+ * Remove all child nodes and descendents. This converts the node into a leaf.<br>
+ * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy()
+ * in order to trigger lazyLoad on next expand.
+ */
+ removeChildren: function () {
+ return this.tree._callHook("nodeRemoveChildren", this);
+ },
+ /**
+ * Remove class from node's span tag and .extraClasses.
+ *
+ * @param {string} className class name
+ *
+ * @since 2.17
+ */
+ removeClass: function (className) {
+ return this.toggleClass(className, false);
+ },
+ /**
+ * This method renders and updates all HTML markup that is required
+ * to display this node in its current state.<br>
+ * Note:
+ * <ul>
+ * <li>It should only be neccessary to call this method after the node object
+ * was modified by direct access to its properties, because the common
+ * API methods (node.setTitle(), moveTo(), addChildren(), remove(), ...)
+ * already handle this.
+ * <li> {@link FancytreeNode#renderTitle} and {@link FancytreeNode#renderStatus}
+ * are implied. If changes are more local, calling only renderTitle() or
+ * renderStatus() may be sufficient and faster.
+ * </ul>
+ *
+ * @param {boolean} [force=false] re-render, even if html markup was already created
+ * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+ */
+ render: function (force, deep) {
+ return this.tree._callHook("nodeRender", this, force, deep);
+ },
+ /** Create HTML markup for the node's outer `<span>` (expander, checkbox, icon, and title).
+ * Implies {@link FancytreeNode#renderStatus}.
+ * @see Fancytree_Hooks#nodeRenderTitle
+ */
+ renderTitle: function () {
+ return this.tree._callHook("nodeRenderTitle", this);
+ },
+ /** Update element's CSS classes according to node state.
+ * @see Fancytree_Hooks#nodeRenderStatus
+ */
+ renderStatus: function () {
+ return this.tree._callHook("nodeRenderStatus", this);
+ },
+ /**
+ * (experimental) Replace this node with `source`.
+ * (Currently only available for paging nodes.)
+ * @param {NodeData[]} source List of child node definitions
+ * @since 2.15
+ */
+ replaceWith: function (source) {
+ var res,
+ parent = this.parent,
+ pos = $.inArray(this, parent.children),
+ self = this;
+
+ _assert(
+ this.isPagingNode(),
+ "replaceWith() currently requires a paging status node"
+ );
+
+ res = this.tree._callHook("nodeLoadChildren", this, source);
+ res.done(function (data) {
+ // New nodes are currently children of `this`.
+ var children = self.children;
+ // Prepend newly loaded child nodes to `this`
+ // Move new children after self
+ for (i = 0; i < children.length; i++) {
+ children[i].parent = parent;
+ }
+ parent.children.splice.apply(
+ parent.children,
+ [pos + 1, 0].concat(children)
+ );
+
+ // Remove self
+ self.children = null;
+ self.remove();
+ // Redraw new nodes
+ parent.render();
+ // TODO: set node.partload = false if this was tha last paging node?
+ // parent.addPagingNode(false);
+ }).fail(function () {
+ self.setExpanded();
+ });
+ return res;
+ // $.error("Not implemented: replaceWith()");
+ },
+ /**
+ * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad
+ * event is triggered on next expand.
+ */
+ resetLazy: function () {
+ this.removeChildren();
+ this.expanded = false;
+ this.lazy = true;
+ this.children = undefined;
+ this.renderStatus();
+ },
+ /** Schedule activity for delayed execution (cancel any pending request).
+ * scheduleAction('cancel') will only cancel a pending request (if any).
+ * @param {string} mode
+ * @param {number} ms
+ */
+ scheduleAction: function (mode, ms) {
+ if (this.tree.timer) {
+ clearTimeout(this.tree.timer);
+ this.tree.debug("clearTimeout(%o)", this.tree.timer);
+ }
+ this.tree.timer = null;
+ var self = this; // required for closures
+ switch (mode) {
+ case "cancel":
+ // Simply made sure that timer was cleared
+ break;
+ case "expand":
+ this.tree.timer = setTimeout(function () {
+ self.tree.debug("setTimeout: trigger expand");
+ self.setExpanded(true);
+ }, ms);
+ break;
+ case "activate":
+ this.tree.timer = setTimeout(function () {
+ self.tree.debug("setTimeout: trigger activate");
+ self.setActive(true);
+ }, ms);
+ break;
+ default:
+ $.error("Invalid mode " + mode);
+ }
+ // this.tree.debug("setTimeout(%s, %s): %s", mode, ms, this.tree.timer);
+ },
+ /**
+ *
+ * @param {boolean | PlainObject} [effects=false] animation options.
+ * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in
+ * any case, even if `this` is outside the scroll pane.
+ * @returns {$.Promise}
+ */
+ scrollIntoView: function (effects, options) {
+ if (options !== undefined && _isNode(options)) {
+ throw Error(
+ "scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead."
+ );
+ }
+ // The scroll parent is typically the plain tree's <UL> container.
+ // For ext-table, we choose the nearest parent that has `position: relative`
+ // and `overflow` set.
+ // (This default can be overridden by the local or global `scrollParent` option.)
+ var opts = $.extend(
+ {
+ effects:
+ effects === true
+ ? { duration: 200, queue: false }
+ : effects,
+ scrollOfs: this.tree.options.scrollOfs,
+ scrollParent: this.tree.options.scrollParent,
+ topNode: null,
+ },
+ options
+ ),
+ $scrollParent = opts.scrollParent,
+ $container = this.tree.$container,
+ overflowY = $container.css("overflow-y");
+
+ if (!$scrollParent) {
+ if (this.tree.tbody) {
+ $scrollParent = $container.scrollParent();
+ } else if (overflowY === "scroll" || overflowY === "auto") {
+ $scrollParent = $container;
+ } else {
+ // #922 plain tree in a non-fixed-sized UL scrolls inside its parent
+ $scrollParent = $container.scrollParent();
+ }
+ } else if (!$scrollParent.jquery) {
+ // Make sure we have a jQuery object
+ $scrollParent = $($scrollParent);
+ }
+ if (
+ $scrollParent[0] === document ||
+ $scrollParent[0] === document.body
+ ) {
+ // `document` may be returned by $().scrollParent(), if nothing is found,
+ // but would not work: (see #894)
+ this.debug(
+ "scrollIntoView(): normalizing scrollParent to 'window':",
+ $scrollParent[0]
+ );
+ $scrollParent = $(window);
+ }
+ // eslint-disable-next-line one-var
+ var topNodeY,
+ nodeY,
+ horzScrollbarHeight,
+ containerOffsetTop,
+ dfd = new $.Deferred(),
+ self = this,
+ nodeHeight = $(this.span).height(),
+ topOfs = opts.scrollOfs.top || 0,
+ bottomOfs = opts.scrollOfs.bottom || 0,
+ containerHeight = $scrollParent.height(),
+ scrollTop = $scrollParent.scrollTop(),
+ $animateTarget = $scrollParent,
+ isParentWindow = $scrollParent[0] === window,
+ topNode = opts.topNode || null,
+ newScrollTop = null;
+
+ // this.debug("scrollIntoView(), scrollTop=" + scrollTop, opts.scrollOfs);
+ // _assert($(this.span).is(":visible"), "scrollIntoView node is invisible"); // otherwise we cannot calc offsets
+ if (this.isRootNode() || !this.isVisible()) {
+ // We cannot calc offsets for hidden elements
+ this.info("scrollIntoView(): node is invisible.");
+ return _getResolvedPromise();
+ }
+ if (isParentWindow) {
+ nodeY = $(this.span).offset().top;
+ topNodeY =
+ topNode && topNode.span ? $(topNode.span).offset().top : 0;
+ $animateTarget = $("html,body");
+ } else {
+ _assert(
+ $scrollParent[0] !== document &&
+ $scrollParent[0] !== document.body,
+ "scrollParent should be a simple element or `window`, not document or body."
+ );
+
+ containerOffsetTop = $scrollParent.offset().top;
+ nodeY =
+ $(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent
+ topNodeY = topNode
+ ? $(topNode.span).offset().top -
+ containerOffsetTop +
+ scrollTop
+ : 0;
+ horzScrollbarHeight = Math.max(
+ 0,
+ $scrollParent.innerHeight() - $scrollParent[0].clientHeight
+ );
+ containerHeight -= horzScrollbarHeight;
+ }
+
+ // this.debug(" scrollIntoView(), nodeY=" + nodeY + ", containerHeight=" + containerHeight);
+ if (nodeY < scrollTop + topOfs) {
+ // Node is above visible container area
+ newScrollTop = nodeY - topOfs;
+ // this.debug(" scrollIntoView(), UPPER newScrollTop=" + newScrollTop);
+ } else if (
+ nodeY + nodeHeight >
+ scrollTop + containerHeight - bottomOfs
+ ) {
+ newScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs;
+ // this.debug(" scrollIntoView(), LOWER newScrollTop=" + newScrollTop);
+ // If a topNode was passed, make sure that it is never scrolled
+ // outside the upper border
+ if (topNode) {
+ _assert(
+ topNode.isRootNode() || topNode.isVisible(),
+ "topNode must be visible"
+ );
+ if (topNodeY < newScrollTop) {
+ newScrollTop = topNodeY - topOfs;
+ // this.debug(" scrollIntoView(), TOP newScrollTop=" + newScrollTop);
+ }
+ }
+ }
+
+ if (newScrollTop === null) {
+ dfd.resolveWith(this);
+ } else {
+ // this.debug(" scrollIntoView(), SET newScrollTop=" + newScrollTop);
+ if (opts.effects) {
+ opts.effects.complete = function () {
+ dfd.resolveWith(self);
+ };
+ $animateTarget.stop(true).animate(
+ {
+ scrollTop: newScrollTop,
+ },
+ opts.effects
+ );
+ } else {
+ $animateTarget[0].scrollTop = newScrollTop;
+ dfd.resolveWith(this);
+ }
+ }
+ return dfd.promise();
+ },
+
+ /**Activate this node.
+ *
+ * The `cell` option requires the ext-table and ext-ariagrid extensions.
+ *
+ * @param {boolean} [flag=true] pass false to deactivate
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false, cell: null}
+ * @returns {$.Promise}
+ */
+ setActive: function (flag, opts) {
+ return this.tree._callHook("nodeSetActive", this, flag, opts);
+ },
+ /**Expand or collapse this node. Promise is resolved, when lazy loading and animations are done.
+ * @param {boolean} [flag=true] pass false to collapse
+ * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}
+ * @returns {$.Promise}
+ */
+ setExpanded: function (flag, opts) {
+ return this.tree._callHook("nodeSetExpanded", this, flag, opts);
+ },
+ /**Set keyboard focus to this node.
+ * @param {boolean} [flag=true] pass false to blur
+ * @see Fancytree#setFocus
+ */
+ setFocus: function (flag) {
+ return this.tree._callHook("nodeSetFocus", this, flag);
+ },
+ /**Select this node, i.e. check the checkbox.
+ * @param {boolean} [flag=true] pass false to deselect
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, p
+ * propagateDown: null, propagateUp: null, callback: null }
+ */
+ setSelected: function (flag, opts) {
+ return this.tree._callHook("nodeSetSelected", this, flag, opts);
+ },
+ /**Mark a lazy node as 'error', 'loading', 'nodata', or 'ok'.
+ * @param {string} status 'error'|'loading'|'nodata'|'ok'
+ * @param {string} [message]
+ * @param {string} [details]
+ */
+ setStatus: function (status, message, details) {
+ return this.tree._callHook(
+ "nodeSetStatus",
+ this,
+ status,
+ message,
+ details
+ );
+ },
+ /**Rename this node.
+ * @param {string} title
+ */
+ setTitle: function (title) {
+ this.title = title;
+ this.renderTitle();
+ this.triggerModify("rename");
+ },
+ /**Sort child list by title.
+ * @param {function} [cmp] custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title).
+ * @param {boolean} [deep=false] pass true to sort all descendant nodes
+ */
+ sortChildren: function (cmp, deep) {
+ var i,
+ l,
+ cl = this.children;
+
+ if (!cl) {
+ return;
+ }
+ cmp =
+ cmp ||
+ function (a, b) {
+ var x = a.title.toLowerCase(),
+ y = b.title.toLowerCase();
+
+ // eslint-disable-next-line no-nested-ternary
+ return x === y ? 0 : x > y ? 1 : -1;
+ };
+ cl.sort(cmp);
+ if (deep) {
+ for (i = 0, l = cl.length; i < l; i++) {
+ if (cl[i].children) {
+ cl[i].sortChildren(cmp, "$norender$");
+ }
+ }
+ }
+ if (deep !== "$norender$") {
+ this.render();
+ }
+ this.triggerModifyChild("sort");
+ },
+ /** Convert node (or whole branch) into a plain object.
+ *
+ * The result is compatible with node.addChildren().
+ *
+ * @param {boolean} [recursive=false] include child nodes
+ * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications.
+ * Return `false` to ignore this node or `"skip"` to include this node without its children.
+ * @returns {NodeData}
+ */
+ toDict: function (recursive, callback) {
+ var i,
+ l,
+ node,
+ res,
+ dict = {},
+ self = this;
+
+ $.each(NODE_ATTRS, function (i, a) {
+ if (self[a] || self[a] === false) {
+ dict[a] = self[a];
+ }
+ });
+ if (!$.isEmptyObject(this.data)) {
+ dict.data = $.extend({}, this.data);
+ if ($.isEmptyObject(dict.data)) {
+ delete dict.data;
+ }
+ }
+ if (callback) {
+ res = callback(dict, self);
+ if (res === false) {
+ return false; // Don't include this node nor its children
+ }
+ if (res === "skip") {
+ recursive = false; // Include this node, but not the children
+ }
+ }
+ if (recursive) {
+ if (_isArray(this.children)) {
+ dict.children = [];
+ for (i = 0, l = this.children.length; i < l; i++) {
+ node = this.children[i];
+ if (!node.isStatusNode()) {
+ res = node.toDict(true, callback);
+ if (res !== false) {
+ dict.children.push(res);
+ }
+ }
+ }
+ }
+ }
+ return dict;
+ },
+ /**
+ * Set, clear, or toggle class of node's span tag and .extraClasses.
+ *
+ * @param {string} className class name (separate multiple classes by space)
+ * @param {boolean} [flag] true/false to add/remove class. If omitted, class is toggled.
+ * @returns {boolean} true if a class was added
+ *
+ * @since 2.17
+ */
+ toggleClass: function (value, flag) {
+ var className,
+ hasClass,
+ rnotwhite = /\S+/g,
+ classNames = value.match(rnotwhite) || [],
+ i = 0,
+ wasAdded = false,
+ statusElem = this[this.tree.statusClassPropName],
+ curClasses = " " + (this.extraClasses || "") + " ";
+
+ // this.info("toggleClass('" + value + "', " + flag + ")", curClasses);
+ // Modify DOM element directly if it already exists
+ if (statusElem) {
+ $(statusElem).toggleClass(value, flag);
+ }
+ // Modify node.extraClasses to make this change persistent
+ // Toggle if flag was not passed
+ while ((className = classNames[i++])) {
+ hasClass = curClasses.indexOf(" " + className + " ") >= 0;
+ flag = flag === undefined ? !hasClass : !!flag;
+ if (flag) {
+ if (!hasClass) {
+ curClasses += className + " ";
+ wasAdded = true;
+ }
+ } else {
+ while (curClasses.indexOf(" " + className + " ") > -1) {
+ curClasses = curClasses.replace(
+ " " + className + " ",
+ " "
+ );
+ }
+ }
+ }
+ this.extraClasses = _trim(curClasses);
+ // this.info("-> toggleClass('" + value + "', " + flag + "): '" + this.extraClasses + "'");
+ return wasAdded;
+ },
+ /** Flip expanded status. */
+ toggleExpanded: function () {
+ return this.tree._callHook("nodeToggleExpanded", this);
+ },
+ /** Flip selection status. */
+ toggleSelected: function () {
+ return this.tree._callHook("nodeToggleSelected", this);
+ },
+ toString: function () {
+ return "FancytreeNode@" + this.key + "[title='" + this.title + "']";
+ // return "<FancytreeNode(#" + this.key + ", '" + this.title + "')>";
+ },
+ /**
+ * Trigger `modifyChild` event on a parent to signal that a child was modified.
+ * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
+ * @param {FancytreeNode} [childNode]
+ * @param {object} [extra]
+ */
+ triggerModifyChild: function (operation, childNode, extra) {
+ var data,
+ modifyChild = this.tree.options.modifyChild;
+
+ if (modifyChild) {
+ if (childNode && childNode.parent !== this) {
+ $.error(
+ "childNode " + childNode + " is not a child of " + this
+ );
+ }
+ data = {
+ node: this,
+ tree: this.tree,
+ operation: operation,
+ childNode: childNode || null,
+ };
+ if (extra) {
+ $.extend(data, extra);
+ }
+ modifyChild({ type: "modifyChild" }, data);
+ }
+ },
+ /**
+ * Trigger `modifyChild` event on node.parent(!).
+ * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
+ * @param {object} [extra]
+ */
+ triggerModify: function (operation, extra) {
+ this.parent.triggerModifyChild(operation, this, extra);
+ },
+ /** Call fn(node) for all child nodes in hierarchical order (depth-first).<br>
+ * Stop iteration, if fn() returns false. Skip current branch, if fn() returns "skip".<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and
+ * its children only.
+ * @param {boolean} [includeSelf=false]
+ * @returns {boolean}
+ */
+ visit: function (fn, includeSelf) {
+ var i,
+ l,
+ res = true,
+ children = this.children;
+
+ if (includeSelf === true) {
+ res = fn(this);
+ if (res === false || res === "skip") {
+ return res;
+ }
+ }
+ if (children) {
+ for (i = 0, l = children.length; i < l; i++) {
+ res = children[i].visit(fn, true);
+ if (res === false) {
+ break;
+ }
+ }
+ }
+ return res;
+ },
+ /** Call fn(node) for all child nodes and recursively load lazy children.<br>
+ * <b>Note:</b> If you need this method, you probably should consider to review
+ * your architecture! Recursivley loading nodes is a perfect way for lazy
+ * programmers to flood the server with requests ;-)
+ *
+ * @param {function} [fn] optional callback function.
+ * Return false to stop iteration, return "skip" to skip this node and
+ * its children only.
+ * @param {boolean} [includeSelf=false]
+ * @returns {$.Promise}
+ * @since 2.4
+ */
+ visitAndLoad: function (fn, includeSelf, _recursion) {
+ var dfd,
+ res,
+ loaders,
+ node = this;
+
+ // node.debug("visitAndLoad");
+ if (fn && includeSelf === true) {
+ res = fn(node);
+ if (res === false || res === "skip") {
+ return _recursion ? res : _getResolvedPromise();
+ }
+ }
+ if (!node.children && !node.lazy) {
+ return _getResolvedPromise();
+ }
+ dfd = new $.Deferred();
+ loaders = [];
+ // node.debug("load()...");
+ node.load().done(function () {
+ // node.debug("load()... done.");
+ for (var i = 0, l = node.children.length; i < l; i++) {
+ res = node.children[i].visitAndLoad(fn, true, true);
+ if (res === false) {
+ dfd.reject();
+ break;
+ } else if (res !== "skip") {
+ loaders.push(res); // Add promise to the list
+ }
+ }
+ $.when.apply(this, loaders).then(function () {
+ dfd.resolve();
+ });
+ });
+ return dfd.promise();
+ },
+ /** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>
+ * Stop iteration, if fn() returns false.<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and children only.
+ * @param {boolean} [includeSelf=false]
+ * @returns {boolean}
+ */
+ visitParents: function (fn, includeSelf) {
+ // Visit parent nodes (bottom up)
+ if (includeSelf && fn(this) === false) {
+ return false;
+ }
+ var p = this.parent;
+ while (p) {
+ if (fn(p) === false) {
+ return false;
+ }
+ p = p.parent;
+ }
+ return true;
+ },
+ /** Call fn(node) for all sibling nodes.<br>
+ * Stop iteration, if fn() returns false.<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration.
+ * @param {boolean} [includeSelf=false]
+ * @returns {boolean}
+ */
+ visitSiblings: function (fn, includeSelf) {
+ var i,
+ l,
+ n,
+ ac = this.parent.children;
+
+ for (i = 0, l = ac.length; i < l; i++) {
+ n = ac[i];
+ if (includeSelf || n !== this) {
+ if (fn(n) === false) {
+ return false;
+ }
+ }
+ }
+ return true;
+ },
+ /** Write warning to browser console if debugLevel >= 2 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ warn: function (msg) {
+ if (this.tree.options.debugLevel >= 2) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("warn", arguments);
+ }
+ },
+ };
+
+ /******************************************************************************
+ * Fancytree
+ */
+ /**
+ * Construct a new tree object.
+ *
+ * @class Fancytree
+ * @classdesc The controller behind a fancytree.
+ * This class also contains 'hook methods': see {@link Fancytree_Hooks}.
+ *
+ * @param {Widget} widget
+ *
+ * @property {string} _id Automatically generated unique tree instance ID, e.g. "1".
+ * @property {string} _ns Automatically generated unique tree namespace, e.g. ".fancytree-1".
+ * @property {FancytreeNode} activeNode Currently active node or null.
+ * @property {string} ariaPropName Property name of FancytreeNode that contains the element which will receive the aria attributes.
+ * Typically "li", but "tr" for table extension.
+ * @property {jQueryObject} $container Outer `<ul>` element (or `<table>` element for ext-table).
+ * @property {jQueryObject} $div A jQuery object containing the element used to instantiate the tree widget (`widget.element`)
+ * @property {object|array} columns Recommended place to store shared column meta data. @since 2.27
+ * @property {object} data Metadata, i.e. properties that may be passed to `source` in addition to a children array.
+ * @property {object} ext Hash of all active plugin instances.
+ * @property {FancytreeNode} focusNode Currently focused node or null.
+ * @property {FancytreeNode} lastSelectedNode Used to implement selectMode 1 (single select)
+ * @property {string} nodeContainerAttrName Property name of FancytreeNode that contains the outer element of single nodes.
+ * Typically "li", but "tr" for table extension.
+ * @property {FancytreeOptions} options Current options, i.e. default options + options passed to constructor.
+ * @property {FancytreeNode} rootNode Invisible system root node.
+ * @property {string} statusClassPropName Property name of FancytreeNode that contains the element which will receive the status classes.
+ * Typically "span", but "tr" for table extension.
+ * @property {object} types Map for shared type specific meta data, used with node.type attribute. @since 2.27
+ * @property {object} viewport See ext-vieport. @since v2.31
+ * @property {object} widget Base widget instance.
+ */
+ function Fancytree(widget) {
+ this.widget = widget;
+ this.$div = widget.element;
+ this.options = widget.options;
+ if (this.options) {
+ if (this.options.lazyload !== undefined) {
+ $.error(
+ "The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."
+ );
+ }
+ if (this.options.loaderror !== undefined) {
+ $.error(
+ "The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."
+ );
+ }
+ if (this.options.fx !== undefined) {
+ $.error(
+ "The 'fx' option was replaced by 'toggleEffect' since 2014-11-30."
+ );
+ }
+ if (this.options.removeNode !== undefined) {
+ $.error(
+ "The 'removeNode' event was replaced by 'modifyChild' since 2.20 (2016-09-10)."
+ );
+ }
+ }
+ this.ext = {}; // Active extension instances
+ this.types = {};
+ this.columns = {};
+ // allow to init tree.data.foo from <div data-foo=''>
+ this.data = _getElementDataAsDict(this.$div);
+ // TODO: use widget.uuid instead?
+ this._id = "" + (this.options.treeId || $.ui.fancytree._nextId++);
+ // TODO: use widget.eventNamespace instead?
+ this._ns = ".fancytree-" + this._id; // append for namespaced events
+ this.activeNode = null;
+ this.focusNode = null;
+ this._hasFocus = null;
+ this._tempCache = {};
+ this._lastMousedownNode = null;
+ this._enableUpdate = true;
+ this.lastSelectedNode = null;
+ this.systemFocusElement = null;
+ this.lastQuicksearchTerm = "";
+ this.lastQuicksearchTime = 0;
+ this.viewport = null; // ext-grid
+
+ this.statusClassPropName = "span";
+ this.ariaPropName = "li";
+ this.nodeContainerAttrName = "li";
+
+ // Remove previous markup if any
+ this.$div.find(">ul.fancytree-container").remove();
+
+ // Create a node without parent.
+ var fakeParent = { tree: this },
+ $ul;
+ this.rootNode = new FancytreeNode(fakeParent, {
+ title: "root",
+ key: "root_" + this._id,
+ children: null,
+ expanded: true,
+ });
+ this.rootNode.parent = null;
+
+ // Create root markup
+ $ul = $("<ul>", {
+ id: "ft-id-" + this._id,
+ class: "ui-fancytree fancytree-container fancytree-plain",
+ }).appendTo(this.$div);
+ this.$container = $ul;
+ this.rootNode.ul = $ul[0];
+
+ if (this.options.debugLevel == null) {
+ this.options.debugLevel = FT.debugLevel;
+ }
+ // // Add container to the TAB chain
+ // // See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant
+ // // #577: Allow to set tabindex to "0", "-1" and ""
+ // this.$container.attr("tabindex", this.options.tabindex);
+
+ // if( this.options.rtl ) {
+ // this.$container.attr("DIR", "RTL").addClass("fancytree-rtl");
+ // // }else{
+ // // this.$container.attr("DIR", null).removeClass("fancytree-rtl");
+ // }
+ // if(this.options.aria){
+ // this.$container.attr("role", "tree");
+ // if( this.options.selectMode !== 1 ) {
+ // this.$container.attr("aria-multiselectable", true);
+ // }
+ // }
+ }
+
+ Fancytree.prototype = /** @lends Fancytree# */ {
+ /* Return a context object that can be re-used for _callHook().
+ * @param {Fancytree | FancytreeNode | EventData} obj
+ * @param {Event} originalEvent
+ * @param {Object} extra
+ * @returns {EventData}
+ */
+ _makeHookContext: function (obj, originalEvent, extra) {
+ var ctx, tree;
+ if (obj.node !== undefined) {
+ // obj is already a context object
+ if (originalEvent && obj.originalEvent !== originalEvent) {
+ $.error("invalid args");
+ }
+ ctx = obj;
+ } else if (obj.tree) {
+ // obj is a FancytreeNode
+ tree = obj.tree;
+ ctx = {
+ node: obj,
+ tree: tree,
+ widget: tree.widget,
+ options: tree.widget.options,
+ originalEvent: originalEvent,
+ typeInfo: tree.types[obj.type] || {},
+ };
+ } else if (obj.widget) {
+ // obj is a Fancytree
+ ctx = {
+ node: null,
+ tree: obj,
+ widget: obj.widget,
+ options: obj.widget.options,
+ originalEvent: originalEvent,
+ };
+ } else {
+ $.error("invalid args");
+ }
+ if (extra) {
+ $.extend(ctx, extra);
+ }
+ return ctx;
+ },
+ /* Trigger a hook function: funcName(ctx, [...]).
+ *
+ * @param {string} funcName
+ * @param {Fancytree|FancytreeNode|EventData} contextObject
+ * @param {any} [_extraArgs] optional additional arguments
+ * @returns {any}
+ */
+ _callHook: function (funcName, contextObject, _extraArgs) {
+ var ctx = this._makeHookContext(contextObject),
+ fn = this[funcName],
+ args = Array.prototype.slice.call(arguments, 2);
+ if (!_isFunction(fn)) {
+ $.error("_callHook('" + funcName + "') is not a function");
+ }
+ args.unshift(ctx);
+ // this.debug("_hook", funcName, ctx.node && ctx.node.toString() || ctx.tree.toString(), args);
+ return fn.apply(this, args);
+ },
+ _setExpiringValue: function (key, value, ms) {
+ this._tempCache[key] = {
+ value: value,
+ expire: Date.now() + (+ms || 50),
+ };
+ },
+ _getExpiringValue: function (key) {
+ var entry = this._tempCache[key];
+ if (entry && entry.expire > Date.now()) {
+ return entry.value;
+ }
+ delete this._tempCache[key];
+ return null;
+ },
+ /* Check if this tree has extension `name` enabled.
+ *
+ * @param {string} name name of the required extension
+ */
+ _usesExtension: function (name) {
+ return $.inArray(name, this.options.extensions) >= 0;
+ },
+ /* Check if current extensions dependencies are met and throw an error if not.
+ *
+ * This method may be called inside the `treeInit` hook for custom extensions.
+ *
+ * @param {string} name name of the required extension
+ * @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present
+ * @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter)
+ * @param {string} [message] optional error message (defaults to a descriptve error message)
+ */
+ _requireExtension: function (name, required, before, message) {
+ if (before != null) {
+ before = !!before;
+ }
+ var thisName = this._local.name,
+ extList = this.options.extensions,
+ isBefore =
+ $.inArray(name, extList) < $.inArray(thisName, extList),
+ isMissing = required && this.ext[name] == null,
+ badOrder = !isMissing && before != null && before !== isBefore;
+
+ _assert(
+ thisName && thisName !== name,
+ "invalid or same name '" + thisName + "' (require yourself?)"
+ );
+
+ if (isMissing || badOrder) {
+ if (!message) {
+ if (isMissing || required) {
+ message =
+ "'" +
+ thisName +
+ "' extension requires '" +
+ name +
+ "'";
+ if (badOrder) {
+ message +=
+ " to be registered " +
+ (before ? "before" : "after") +
+ " itself";
+ }
+ } else {
+ message =
+ "If used together, `" +
+ name +
+ "` must be registered " +
+ (before ? "before" : "after") +
+ " `" +
+ thisName +
+ "`";
+ }
+ }
+ $.error(message);
+ return false;
+ }
+ return true;
+ },
+ /** Activate node with a given key and fire focus and activate events.
+ *
+ * A previously activated node will be deactivated.
+ * If activeVisible option is set, all parents will be expanded as necessary.
+ * Pass key = false, to deactivate the current node only.
+ * @param {string} key
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}
+ * @returns {FancytreeNode} activated node (null, if not found)
+ */
+ activateKey: function (key, opts) {
+ var node = this.getNodeByKey(key);
+ if (node) {
+ node.setActive(true, opts);
+ } else if (this.activeNode) {
+ this.activeNode.setActive(false, opts);
+ }
+ return node;
+ },
+ /** (experimental) Add child status nodes that indicate 'More...', ....
+ * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.
+ * @param {string} [mode='append'] 'child'|firstChild'
+ * @since 2.15
+ */
+ addPagingNode: function (node, mode) {
+ return this.rootNode.addPagingNode(node, mode);
+ },
+ /**
+ * (experimental) Apply a modification (or navigation) operation.
+ *
+ * Valid commands:
+ * - 'moveUp', 'moveDown'
+ * - 'indent', 'outdent'
+ * - 'remove'
+ * - 'edit', 'addChild', 'addSibling': (reqires ext-edit extension)
+ * - 'cut', 'copy', 'paste': (use an internal singleton 'clipboard')
+ * - 'down', 'first', 'last', 'left', 'parent', 'right', 'up': navigate
+ *
+ * @param {string} cmd
+ * @param {FancytreeNode} [node=active_node]
+ * @param {object} [opts] Currently unused
+ *
+ * @since 2.32
+ */
+ applyCommand: function (cmd, node, opts_) {
+ var // clipboard,
+ refNode;
+ // opts = $.extend(
+ // { setActive: true, clipboard: CLIPBOARD },
+ // opts_
+ // );
+
+ node = node || this.getActiveNode();
+ // clipboard = opts.clipboard;
+
+ switch (cmd) {
+ // Sorting and indentation:
+ case "moveUp":
+ refNode = node.getPrevSibling();
+ if (refNode) {
+ node.moveTo(refNode, "before");
+ node.setActive();
+ }
+ break;
+ case "moveDown":
+ refNode = node.getNextSibling();
+ if (refNode) {
+ node.moveTo(refNode, "after");
+ node.setActive();
+ }
+ break;
+ case "indent":
+ refNode = node.getPrevSibling();
+ if (refNode) {
+ node.moveTo(refNode, "child");
+ refNode.setExpanded();
+ node.setActive();
+ }
+ break;
+ case "outdent":
+ if (!node.isTopLevel()) {
+ node.moveTo(node.getParent(), "after");
+ node.setActive();
+ }
+ break;
+ // Remove:
+ case "remove":
+ refNode = node.getPrevSibling() || node.getParent();
+ node.remove();
+ if (refNode) {
+ refNode.setActive();
+ }
+ break;
+ // Add, edit (requires ext-edit):
+ case "addChild":
+ node.editCreateNode("child", "");
+ break;
+ case "addSibling":
+ node.editCreateNode("after", "");
+ break;
+ case "rename":
+ node.editStart();
+ break;
+ // Simple clipboard simulation:
+ // case "cut":
+ // clipboard = { mode: cmd, data: node };
+ // break;
+ // case "copy":
+ // clipboard = {
+ // mode: cmd,
+ // data: node.toDict(function(d, n) {
+ // delete d.key;
+ // }),
+ // };
+ // break;
+ // case "clear":
+ // clipboard = null;
+ // break;
+ // case "paste":
+ // if (clipboard.mode === "cut") {
+ // // refNode = node.getPrevSibling();
+ // clipboard.data.moveTo(node, "child");
+ // clipboard.data.setActive();
+ // } else if (clipboard.mode === "copy") {
+ // node.addChildren(clipboard.data).setActive();
+ // }
+ // break;
+ // Navigation commands:
+ case "down":
+ case "first":
+ case "last":
+ case "left":
+ case "parent":
+ case "right":
+ case "up":
+ return node.navigate(cmd);
+ default:
+ $.error("Unhandled command: '" + cmd + "'");
+ }
+ },
+ /** (experimental) Modify existing data model.
+ *
+ * @param {Array} patchList array of [key, NodePatch] arrays
+ * @returns {$.Promise} resolved, when all patches have been applied
+ * @see TreePatch
+ */
+ applyPatch: function (patchList) {
+ var dfd,
+ i,
+ p2,
+ key,
+ patch,
+ node,
+ patchCount = patchList.length,
+ deferredList = [];
+
+ for (i = 0; i < patchCount; i++) {
+ p2 = patchList[i];
+ _assert(
+ p2.length === 2,
+ "patchList must be an array of length-2-arrays"
+ );
+ key = p2[0];
+ patch = p2[1];
+ node = key === null ? this.rootNode : this.getNodeByKey(key);
+ if (node) {
+ dfd = new $.Deferred();
+ deferredList.push(dfd);
+ node.applyPatch(patch).always(_makeResolveFunc(dfd, node));
+ } else {
+ this.warn("could not find node with key '" + key + "'");
+ }
+ }
+ // Return a promise that is resolved, when ALL patches were applied
+ return $.when.apply($, deferredList).promise();
+ },
+ /* TODO: implement in dnd extension
+ cancelDrag: function() {
+ var dd = $.ui.ddmanager.current;
+ if(dd){
+ dd.cancel();
+ }
+ },
+ */
+ /** Remove all nodes.
+ * @since 2.14
+ */
+ clear: function (source) {
+ this._callHook("treeClear", this);
+ },
+ /** Return the number of nodes.
+ * @returns {integer}
+ */
+ count: function () {
+ return this.rootNode.countChildren();
+ },
+ /** Write to browser console if debugLevel >= 4 (prepending tree name)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ debug: function (msg) {
+ if (this.options.debugLevel >= 4) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("log", arguments);
+ }
+ },
+ /** Destroy this widget, restore previous markup and cleanup resources.
+ *
+ * @since 2.34
+ */
+ destroy: function () {
+ this.widget.destroy();
+ },
+ /** Enable (or disable) the tree control.
+ *
+ * @param {boolean} [flag=true] pass false to disable
+ * @since 2.30
+ */
+ enable: function (flag) {
+ if (flag === false) {
+ this.widget.disable();
+ } else {
+ this.widget.enable();
+ }
+ },
+ /** Temporarily suppress rendering to improve performance on bulk-updates.
+ *
+ * @param {boolean} flag
+ * @returns {boolean} previous status
+ * @since 2.19
+ */
+ enableUpdate: function (flag) {
+ flag = flag !== false;
+ if (!!this._enableUpdate === !!flag) {
+ return flag;
+ }
+ this._enableUpdate = flag;
+ if (flag) {
+ this.debug("enableUpdate(true): redraw "); //, this._dirtyRoots);
+ this._callHook("treeStructureChanged", this, "enableUpdate");
+ this.render();
+ } else {
+ // this._dirtyRoots = null;
+ this.debug("enableUpdate(false)...");
+ }
+ return !flag; // return previous value
+ },
+ /** Write error to browser console if debugLevel >= 1 (prepending tree info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ error: function (msg) {
+ if (this.options.debugLevel >= 1) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("error", arguments);
+ }
+ },
+ /** Expand (or collapse) all parent nodes.
+ *
+ * This convenience method uses `tree.visit()` and `tree.setExpanded()`
+ * internally.
+ *
+ * @param {boolean} [flag=true] pass false to collapse
+ * @param {object} [opts] passed to setExpanded()
+ * @since 2.30
+ */
+ expandAll: function (flag, opts) {
+ var prev = this.enableUpdate(false);
+
+ flag = flag !== false;
+ this.visit(function (node) {
+ if (
+ node.hasChildren() !== false &&
+ node.isExpanded() !== flag
+ ) {
+ node.setExpanded(flag, opts);
+ }
+ });
+ this.enableUpdate(prev);
+ },
+ /**Find all nodes that matches condition.
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode[]} array of nodes (may be empty)
+ * @see FancytreeNode#findAll
+ * @since 2.12
+ */
+ findAll: function (match) {
+ return this.rootNode.findAll(match);
+ },
+ /**Find first node that matches condition.
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode} matching node or null
+ * @see FancytreeNode#findFirst
+ * @since 2.12
+ */
+ findFirst: function (match) {
+ return this.rootNode.findFirst(match);
+ },
+ /** Find the next visible node that starts with `match`, starting at `startNode`
+ * and wrap-around at the end.
+ *
+ * @param {string|function} match
+ * @param {FancytreeNode} [startNode] defaults to first node
+ * @returns {FancytreeNode} matching node or null
+ */
+ findNextNode: function (match, startNode) {
+ //, visibleOnly) {
+ var res = null,
+ firstNode = this.getFirstChild();
+
+ match =
+ typeof match === "string"
+ ? _makeNodeTitleStartMatcher(match)
+ : match;
+ startNode = startNode || firstNode;
+
+ function _checkNode(n) {
+ // console.log("_check " + n)
+ if (match(n)) {
+ res = n;
+ }
+ if (res || n === startNode) {
+ return false;
+ }
+ }
+ this.visitRows(_checkNode, {
+ start: startNode,
+ includeSelf: false,
+ });
+ // Wrap around search
+ if (!res && startNode !== firstNode) {
+ this.visitRows(_checkNode, {
+ start: firstNode,
+ includeSelf: true,
+ });
+ }
+ return res;
+ },
+ /** Find a node relative to another node.
+ *
+ * @param {FancytreeNode} node
+ * @param {string|number} where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.
+ * (Alternatively the keyCode that would normally trigger this move,
+ * e.g. `$.ui.keyCode.LEFT` = 'left'.
+ * @param {boolean} [includeHidden=false] Not yet implemented
+ * @returns {FancytreeNode|null}
+ * @since v2.31
+ */
+ findRelatedNode: function (node, where, includeHidden) {
+ var res = null,
+ KC = $.ui.keyCode;
+
+ switch (where) {
+ case "parent":
+ case KC.BACKSPACE:
+ if (node.parent && node.parent.parent) {
+ res = node.parent;
+ }
+ break;
+ case "first":
+ case KC.HOME:
+ // First visible node
+ this.visit(function (n) {
+ if (n.isVisible()) {
+ res = n;
+ return false;
+ }
+ });
+ break;
+ case "last":
+ case KC.END:
+ this.visit(function (n) {
+ // last visible node
+ if (n.isVisible()) {
+ res = n;
+ }
+ });
+ break;
+ case "left":
+ case KC.LEFT:
+ if (node.expanded) {
+ node.setExpanded(false);
+ } else if (node.parent && node.parent.parent) {
+ res = node.parent;
+ }
+ break;
+ case "right":
+ case KC.RIGHT:
+ if (!node.expanded && (node.children || node.lazy)) {
+ node.setExpanded();
+ res = node;
+ } else if (node.children && node.children.length) {
+ res = node.children[0];
+ }
+ break;
+ case "up":
+ case KC.UP:
+ this.visitRows(
+ function (n) {
+ res = n;
+ return false;
+ },
+ { start: node, reverse: true, includeSelf: false }
+ );
+ break;
+ case "down":
+ case KC.DOWN:
+ this.visitRows(
+ function (n) {
+ res = n;
+ return false;
+ },
+ { start: node, includeSelf: false }
+ );
+ break;
+ default:
+ this.tree.warn("Unknown relation '" + where + "'.");
+ }
+ return res;
+ },
+ // TODO: fromDict
+ /**
+ * Generate INPUT elements that can be submitted with html forms.
+ *
+ * In selectMode 3 only the topmost selected nodes are considered, unless
+ * `opts.stopOnParents: false` is passed.
+ *
+ * @example
+ * // Generate input elements for active and selected nodes
+ * tree.generateFormElements();
+ * // Generate input elements selected nodes, using a custom `name` attribute
+ * tree.generateFormElements("cust_sel", false);
+ * // Generate input elements using a custom filter
+ * tree.generateFormElements(true, true, { filter: function(node) {
+ * return node.isSelected() && node.data.yes;
+ * }});
+ *
+ * @param {boolean | string} [selected=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID[]')
+ * @param {boolean | string} [active=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID_active')
+ * @param {object} [opts] default { filter: null, stopOnParents: true }
+ */
+ generateFormElements: function (selected, active, opts) {
+ opts = opts || {};
+
+ var nodeList,
+ selectedName =
+ typeof selected === "string"
+ ? selected
+ : "ft_" + this._id + "[]",
+ activeName =
+ typeof active === "string"
+ ? active
+ : "ft_" + this._id + "_active",
+ id = "fancytree_result_" + this._id,
+ $result = $("#" + id),
+ stopOnParents =
+ this.options.selectMode === 3 &&
+ opts.stopOnParents !== false;
+
+ if ($result.length) {
+ $result.empty();
+ } else {
+ $result = $("<div>", {
+ id: id,
+ })
+ .hide()
+ .insertAfter(this.$container);
+ }
+ if (active !== false && this.activeNode) {
+ $result.append(
+ $("<input>", {
+ type: "radio",
+ name: activeName,
+ value: this.activeNode.key,
+ checked: true,
+ })
+ );
+ }
+ function _appender(node) {
+ $result.append(
+ $("<input>", {
+ type: "checkbox",
+ name: selectedName,
+ value: node.key,
+ checked: true,
+ })
+ );
+ }
+ if (opts.filter) {
+ this.visit(function (node) {
+ var res = opts.filter(node);
+ if (res === "skip") {
+ return res;
+ }
+ if (res !== false) {
+ _appender(node);
+ }
+ });
+ } else if (selected !== false) {
+ nodeList = this.getSelectedNodes(stopOnParents);
+ $.each(nodeList, function (idx, node) {
+ _appender(node);
+ });
+ }
+ },
+ /**
+ * Return the currently active node or null.
+ * @returns {FancytreeNode}
+ */
+ getActiveNode: function () {
+ return this.activeNode;
+ },
+ /** Return the first top level node if any (not the invisible root node).
+ * @returns {FancytreeNode | null}
+ */
+ getFirstChild: function () {
+ return this.rootNode.getFirstChild();
+ },
+ /**
+ * Return node that has keyboard focus or null.
+ * @returns {FancytreeNode}
+ */
+ getFocusNode: function () {
+ return this.focusNode;
+ },
+ /**
+ * Return current option value.
+ * (Note: this is the preferred variant of `$().fancytree("option", "KEY")`)
+ *
+ * @param {string} name option name (may contain '.')
+ * @returns {any}
+ */
+ getOption: function (optionName) {
+ return this.widget.option(optionName);
+ },
+ /**
+ * Return node with a given key or null if not found.
+ *
+ * @param {string} key
+ * @param {FancytreeNode} [searchRoot] only search below this node
+ * @returns {FancytreeNode | null}
+ */
+ getNodeByKey: function (key, searchRoot) {
+ // Search the DOM by element ID (assuming this is faster than traversing all nodes).
+ var el, match;
+ // TODO: use tree.keyMap if available
+ // TODO: check opts.generateIds === true
+ if (!searchRoot) {
+ el = document.getElementById(this.options.idPrefix + key);
+ if (el) {
+ return el.ftnode ? el.ftnode : null;
+ }
+ }
+ // Not found in the DOM, but still may be in an unrendered part of tree
+ searchRoot = searchRoot || this.rootNode;
+ match = null;
+ key = "" + key; // Convert to string (#1005)
+ searchRoot.visit(function (node) {
+ if (node.key === key) {
+ match = node;
+ return false; // Stop iteration
+ }
+ }, true);
+ return match;
+ },
+ /** Return the invisible system root node.
+ * @returns {FancytreeNode}
+ */
+ getRootNode: function () {
+ return this.rootNode;
+ },
+ /**
+ * Return an array of selected nodes.
+ *
+ * Note: you cannot send this result via Ajax directly. Instead the
+ * node object need to be converted to plain objects, for example
+ * by using `$.map()` and `node.toDict()`.
+ * @param {boolean} [stopOnParents=false] only return the topmost selected
+ * node (useful with selectMode 3)
+ * @returns {FancytreeNode[]}
+ */
+ getSelectedNodes: function (stopOnParents) {
+ return this.rootNode.getSelectedNodes(stopOnParents);
+ },
+ /** Return true if the tree control has keyboard focus
+ * @returns {boolean}
+ */
+ hasFocus: function () {
+ // var ae = document.activeElement,
+ // hasFocus = !!(
+ // ae && $(ae).closest(".fancytree-container").length
+ // );
+
+ // if (hasFocus !== !!this._hasFocus) {
+ // this.warn(
+ // "hasFocus(): fix inconsistent container state, now: " +
+ // hasFocus
+ // );
+ // this._hasFocus = hasFocus;
+ // this.$container.toggleClass("fancytree-treefocus", hasFocus);
+ // }
+ // return hasFocus;
+ return !!this._hasFocus;
+ },
+ /** Write to browser console if debugLevel >= 3 (prepending tree name)
+ * @param {*} msg string or object or array of such
+ */
+ info: function (msg) {
+ if (this.options.debugLevel >= 3) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("info", arguments);
+ }
+ },
+ /** Return true if any node is currently beeing loaded, i.e. a Ajax request is pending.
+ * @returns {boolean}
+ * @since 2.32
+ */
+ isLoading: function () {
+ var res = false;
+
+ this.rootNode.visit(function (n) {
+ // also visit rootNode
+ if (n._isLoading || n._requestId) {
+ res = true;
+ return false;
+ }
+ }, true);
+ return res;
+ },
+ /*
+ TODO: isInitializing: function() {
+ return ( this.phase=="init" || this.phase=="postInit" );
+ },
+ TODO: isReloading: function() {
+ return ( this.phase=="init" || this.phase=="postInit" ) && this.options.persist && this.persistence.cookiesFound;
+ },
+ TODO: isUserEvent: function() {
+ return ( this.phase=="userEvent" );
+ },
+ */
+
+ /**
+ * Make sure that a node with a given ID is loaded, by traversing - and
+ * loading - its parents. This method is meant for lazy hierarchies.
+ * A callback is executed for every node as we go.
+ * @example
+ * // Resolve using node.key:
+ * tree.loadKeyPath("/_3/_23/_26/_27", function(node, status){
+ * if(status === "loaded") {
+ * console.log("loaded intermediate node " + node);
+ * }else if(status === "ok") {
+ * node.activate();
+ * }
+ * });
+ * // Use deferred promise:
+ * tree.loadKeyPath("/_3/_23/_26/_27").progress(function(data){
+ * if(data.status === "loaded") {
+ * console.log("loaded intermediate node " + data.node);
+ * }else if(data.status === "ok") {
+ * node.activate();
+ * }
+ * }).done(function(){
+ * ...
+ * });
+ * // Custom path segment resolver:
+ * tree.loadKeyPath("/321/431/21/2", {
+ * matchKey: function(node, key){
+ * return node.data.refKey === key;
+ * },
+ * callback: function(node, status){
+ * if(status === "loaded") {
+ * console.log("loaded intermediate node " + node);
+ * }else if(status === "ok") {
+ * node.activate();
+ * }
+ * }
+ * });
+ * @param {string | string[]} keyPathList one or more key paths (e.g. '/3/2_1/7')
+ * @param {function | object} optsOrCallback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error').
+ * Pass an object to define custom key matchers for the path segments: {callback: function, matchKey: function}.
+ * @returns {$.Promise}
+ */
+ loadKeyPath: function (keyPathList, optsOrCallback) {
+ var callback,
+ i,
+ path,
+ self = this,
+ dfd = new $.Deferred(),
+ parent = this.getRootNode(),
+ sep = this.options.keyPathSeparator,
+ pathSegList = [],
+ opts = $.extend({}, optsOrCallback);
+
+ // Prepare options
+ if (typeof optsOrCallback === "function") {
+ callback = optsOrCallback;
+ } else if (optsOrCallback && optsOrCallback.callback) {
+ callback = optsOrCallback.callback;
+ }
+ opts.callback = function (ctx, node, status) {
+ if (callback) {
+ callback.call(ctx, node, status);
+ }
+ dfd.notifyWith(ctx, [{ node: node, status: status }]);
+ };
+ if (opts.matchKey == null) {
+ opts.matchKey = function (node, key) {
+ return node.key === key;
+ };
+ }
+ // Convert array of path strings to array of segment arrays
+ if (!_isArray(keyPathList)) {
+ keyPathList = [keyPathList];
+ }
+ for (i = 0; i < keyPathList.length; i++) {
+ path = keyPathList[i];
+ // strip leading slash
+ if (path.charAt(0) === sep) {
+ path = path.substr(1);
+ }
+ // segListMap[path] = { parent: parent, segList: path.split(sep) };
+ pathSegList.push(path.split(sep));
+ // targetList.push({ parent: parent, segList: path.split(sep)/* , path: path*/});
+ }
+ // The timeout forces async behavior always (even if nodes are all loaded)
+ // This way a potential progress() event will fire.
+ setTimeout(function () {
+ self._loadKeyPathImpl(dfd, opts, parent, pathSegList).done(
+ function () {
+ dfd.resolve();
+ }
+ );
+ }, 0);
+ return dfd.promise();
+ },
+ /*
+ * Resolve a list of paths, relative to one parent node.
+ */
+ _loadKeyPathImpl: function (dfd, opts, parent, pathSegList) {
+ var deferredList,
+ i,
+ key,
+ node,
+ nodeKey,
+ remain,
+ remainMap,
+ tmpParent,
+ segList,
+ subDfd,
+ self = this;
+
+ function __findChild(parent, key) {
+ // console.log("__findChild", key, parent);
+ var i,
+ l,
+ cl = parent.children;
+
+ if (cl) {
+ for (i = 0, l = cl.length; i < l; i++) {
+ if (opts.matchKey(cl[i], key)) {
+ return cl[i];
+ }
+ }
+ }
+ return null;
+ }
+
+ // console.log("_loadKeyPathImpl, parent=", parent, ", pathSegList=", pathSegList);
+
+ // Pass 1:
+ // Handle all path segments for nodes that are already loaded.
+ // Collect distinct top-most lazy nodes in a map.
+ // Note that we can use node.key to de-dupe entries, even if a custom matcher would
+ // look for other node attributes.
+ // map[node.key] => {node: node, pathList: [list of remaining rest-paths]}
+ remainMap = {};
+
+ for (i = 0; i < pathSegList.length; i++) {
+ segList = pathSegList[i];
+ // target = targetList[i];
+
+ // Traverse and pop path segments (i.e. keys), until we hit a lazy, unloaded node
+ tmpParent = parent;
+ while (segList.length) {
+ key = segList.shift();
+ node = __findChild(tmpParent, key);
+ if (!node) {
+ this.warn(
+ "loadKeyPath: key not found: " +
+ key +
+ " (parent: " +
+ tmpParent +
+ ")"
+ );
+ opts.callback(this, key, "error");
+ break;
+ } else if (segList.length === 0) {
+ opts.callback(this, node, "ok");
+ break;
+ } else if (!node.lazy || node.hasChildren() !== undefined) {
+ opts.callback(this, node, "loaded");
+ tmpParent = node;
+ } else {
+ opts.callback(this, node, "loaded");
+ key = node.key; //target.segList.join(sep);
+ if (remainMap[key]) {
+ remainMap[key].pathSegList.push(segList);
+ } else {
+ remainMap[key] = {
+ parent: node,
+ pathSegList: [segList],
+ };
+ }
+ break;
+ }
+ }
+ }
+ // console.log("_loadKeyPathImpl AFTER pass 1, remainMap=", remainMap);
+
+ // Now load all lazy nodes and continue iteration for remaining paths
+ deferredList = [];
+
+ // Avoid jshint warning 'Don't make functions within a loop.':
+ function __lazyload(dfd, parent, pathSegList) {
+ // console.log("__lazyload", parent, "pathSegList=", pathSegList);
+ opts.callback(self, parent, "loading");
+ parent
+ .load()
+ .done(function () {
+ self._loadKeyPathImpl
+ .call(self, dfd, opts, parent, pathSegList)
+ .always(_makeResolveFunc(dfd, self));
+ })
+ .fail(function (errMsg) {
+ self.warn("loadKeyPath: error loading lazy " + parent);
+ opts.callback(self, node, "error");
+ dfd.rejectWith(self);
+ });
+ }
+ // remainMap contains parent nodes, each with a list of relative sub-paths.
+ // We start loading all of them now, and pass the the list to each loader.
+ for (nodeKey in remainMap) {
+ if (_hasProp(remainMap, nodeKey)) {
+ remain = remainMap[nodeKey];
+ // console.log("for(): remain=", remain, "remainMap=", remainMap);
+ // key = remain.segList.shift();
+ // node = __findChild(remain.parent, key);
+ // if (node == null) { // #576
+ // // Issue #576, refactored for v2.27:
+ // // The root cause was, that sometimes the wrong parent was used here
+ // // to find the next segment.
+ // // Falling back to getNodeByKey() was a hack that no longer works if a custom
+ // // matcher is used, because we cannot assume that a single segment-key is unique
+ // // throughout the tree.
+ // self.error("loadKeyPath: error loading child by key '" + key + "' (parent: " + target.parent + ")", target);
+ // // node = self.getNodeByKey(key);
+ // continue;
+ // }
+ subDfd = new $.Deferred();
+ deferredList.push(subDfd);
+ __lazyload(subDfd, remain.parent, remain.pathSegList);
+ }
+ }
+ // Return a promise that is resolved, when ALL paths were loaded
+ return $.when.apply($, deferredList).promise();
+ },
+ /** Re-fire beforeActivate, activate, and (optional) focus events.
+ * Calling this method in the `init` event, will activate the node that
+ * was marked 'active' in the source data, and optionally set the keyboard
+ * focus.
+ * @param [setFocus=false]
+ */
+ reactivate: function (setFocus) {
+ var res,
+ node = this.activeNode;
+
+ if (!node) {
+ return _getResolvedPromise();
+ }
+ this.activeNode = null; // Force re-activating
+ res = node.setActive(true, { noFocus: true });
+ if (setFocus) {
+ node.setFocus();
+ }
+ return res;
+ },
+ /** Reload tree from source and return a promise.
+ * @param [source] optional new source (defaults to initial source data)
+ * @returns {$.Promise}
+ */
+ reload: function (source) {
+ this._callHook("treeClear", this);
+ return this._callHook("treeLoad", this, source);
+ },
+ /**Render tree (i.e. create DOM elements for all top-level nodes).
+ * @param {boolean} [force=false] create DOM elemnts, even if parent is collapsed
+ * @param {boolean} [deep=false]
+ */
+ render: function (force, deep) {
+ return this.rootNode.render(force, deep);
+ },
+ /**(De)select all nodes.
+ * @param {boolean} [flag=true]
+ * @since 2.28
+ */
+ selectAll: function (flag) {
+ this.visit(function (node) {
+ node.setSelected(flag);
+ });
+ },
+ // TODO: selectKey: function(key, select)
+ // TODO: serializeArray: function(stopOnParents)
+ /**
+ * @param {boolean} [flag=true]
+ */
+ setFocus: function (flag) {
+ return this._callHook("treeSetFocus", this, flag);
+ },
+ /**
+ * Set current option value.
+ * (Note: this is the preferred variant of `$().fancytree("option", "KEY", VALUE)`)
+ * @param {string} name option name (may contain '.')
+ * @param {any} new value
+ */
+ setOption: function (optionName, value) {
+ return this.widget.option(optionName, value);
+ },
+ /**
+ * Call console.time() when in debug mode (verbose >= 4).
+ *
+ * @param {string} label
+ */
+ debugTime: function (label) {
+ if (this.options.debugLevel >= 4) {
+ window.console.time(this + " - " + label);
+ }
+ },
+ /**
+ * Call console.timeEnd() when in debug mode (verbose >= 4).
+ *
+ * @param {string} label
+ */
+ debugTimeEnd: function (label) {
+ if (this.options.debugLevel >= 4) {
+ window.console.timeEnd(this + " - " + label);
+ }
+ },
+ /**
+ * Return all nodes as nested list of {@link NodeData}.
+ *
+ * @param {boolean} [includeRoot=false] Returns the hidden system root node (and its children)
+ * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications.
+ * Return `false` to ignore this node or "skip" to include this node without its children.
+ * @returns {Array | object}
+ * @see FancytreeNode#toDict
+ */
+ toDict: function (includeRoot, callback) {
+ var res = this.rootNode.toDict(true, callback);
+ return includeRoot ? res : res.children;
+ },
+ /* Implicitly called for string conversions.
+ * @returns {string}
+ */
+ toString: function () {
+ return "Fancytree@" + this._id;
+ // return "<Fancytree(#" + this._id + ")>";
+ },
+ /* _trigger a widget event with additional node ctx.
+ * @see EventData
+ */
+ _triggerNodeEvent: function (type, node, originalEvent, extra) {
+ // this.debug("_trigger(" + type + "): '" + ctx.node.title + "'", ctx);
+ var ctx = this._makeHookContext(node, originalEvent, extra),
+ res = this.widget._trigger(type, originalEvent, ctx);
+ if (res !== false && ctx.result !== undefined) {
+ return ctx.result;
+ }
+ return res;
+ },
+ /* _trigger a widget event with additional tree data. */
+ _triggerTreeEvent: function (type, originalEvent, extra) {
+ // this.debug("_trigger(" + type + ")", ctx);
+ var ctx = this._makeHookContext(this, originalEvent, extra),
+ res = this.widget._trigger(type, originalEvent, ctx);
+
+ if (res !== false && ctx.result !== undefined) {
+ return ctx.result;
+ }
+ return res;
+ },
+ /** Call fn(node) for all nodes in hierarchical order (depth-first).
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and children only.
+ * @returns {boolean} false, if the iterator was stopped.
+ */
+ visit: function (fn) {
+ return this.rootNode.visit(fn, false);
+ },
+ /** Call fn(node) for all nodes in vertical order, top down (or bottom up).<br>
+ * Stop iteration, if fn() returns false.<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and children only.
+ * @param {object} [options]
+ * Defaults:
+ * {start: First top node, reverse: false, includeSelf: true, includeHidden: false}
+ * @returns {boolean} false if iteration was cancelled
+ * @since 2.28
+ */
+ visitRows: function (fn, opts) {
+ if (!this.rootNode.hasChildren()) {
+ return false;
+ }
+ if (opts && opts.reverse) {
+ delete opts.reverse;
+ return this._visitRowsUp(fn, opts);
+ }
+ opts = opts || {};
+
+ var i,
+ nextIdx,
+ parent,
+ res,
+ siblings,
+ siblingOfs = 0,
+ skipFirstNode = opts.includeSelf === false,
+ includeHidden = !!opts.includeHidden,
+ checkFilter = !includeHidden && this.enableFilter,
+ node = opts.start || this.rootNode.children[0];
+
+ parent = node.parent;
+ while (parent) {
+ // visit siblings
+ siblings = parent.children;
+ nextIdx = siblings.indexOf(node) + siblingOfs;
+ _assert(
+ nextIdx >= 0,
+ "Could not find " +
+ node +
+ " in parent's children: " +
+ parent
+ );
+
+ for (i = nextIdx; i < siblings.length; i++) {
+ node = siblings[i];
+ if (checkFilter && !node.match && !node.subMatchCount) {
+ continue;
+ }
+ if (!skipFirstNode && fn(node) === false) {
+ return false;
+ }
+ skipFirstNode = false;
+ // Dive into node's child nodes
+ if (
+ node.children &&
+ node.children.length &&
+ (includeHidden || node.expanded)
+ ) {
+ // Disable warning: Functions declared within loops referencing an outer
+ // scoped variable may lead to confusing semantics:
+ /*jshint -W083 */
+ res = node.visit(function (n) {
+ if (checkFilter && !n.match && !n.subMatchCount) {
+ return "skip";
+ }
+ if (fn(n) === false) {
+ return false;
+ }
+ if (!includeHidden && n.children && !n.expanded) {
+ return "skip";
+ }
+ }, false);
+ /*jshint +W083 */
+ if (res === false) {
+ return false;
+ }
+ }
+ }
+ // Visit parent nodes (bottom up)
+ node = parent;
+ parent = parent.parent;
+ siblingOfs = 1; //
+ }
+ return true;
+ },
+ /* Call fn(node) for all nodes in vertical order, bottom up.
+ */
+ _visitRowsUp: function (fn, opts) {
+ var children,
+ idx,
+ parent,
+ includeHidden = !!opts.includeHidden,
+ node = opts.start || this.rootNode.children[0];
+
+ while (true) {
+ parent = node.parent;
+ children = parent.children;
+
+ if (children[0] === node) {
+ // If this is already the first sibling, goto parent
+ node = parent;
+ if (!node.parent) {
+ break; // first node of the tree
+ }
+ children = parent.children;
+ } else {
+ // Otherwise, goto prev. sibling
+ idx = children.indexOf(node);
+ node = children[idx - 1];
+ // If the prev. sibling has children, follow down to last descendant
+ while (
+ // See: https://github.com/eslint/eslint/issues/11302
+ // eslint-disable-next-line no-unmodified-loop-condition
+ (includeHidden || node.expanded) &&
+ node.children &&
+ node.children.length
+ ) {
+ children = node.children;
+ parent = node;
+ node = children[children.length - 1];
+ }
+ }
+ // Skip invisible
+ if (!includeHidden && !node.isVisible()) {
+ continue;
+ }
+ if (fn(node) === false) {
+ return false;
+ }
+ }
+ },
+ /** Write warning to browser console if debugLevel >= 2 (prepending tree info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ warn: function (msg) {
+ if (this.options.debugLevel >= 2) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("warn", arguments);
+ }
+ },
+ };
+
+ /**
+ * These additional methods of the {@link Fancytree} class are 'hook functions'
+ * that can be used and overloaded by extensions.
+ *
+ * @see [writing extensions](https://github.com/mar10/fancytree/wiki/TutorialExtensions)
+ * @mixin Fancytree_Hooks
+ */
+ $.extend(
+ Fancytree.prototype,
+ /** @lends Fancytree_Hooks# */
+ {
+ /** Default handling for mouse click events.
+ *
+ * @param {EventData} ctx
+ */
+ nodeClick: function (ctx) {
+ var activate,
+ expand,
+ // event = ctx.originalEvent,
+ targetType = ctx.targetType,
+ node = ctx.node;
+
+ // this.debug("ftnode.onClick(" + event.type + "): ftnode:" + this + ", button:" + event.button + ", which: " + event.which, ctx);
+ // TODO: use switch
+ // TODO: make sure clicks on embedded <input> doesn't steal focus (see table sample)
+ if (targetType === "expander") {
+ if (node.isLoading()) {
+ // #495: we probably got a click event while a lazy load is pending.
+ // The 'expanded' state is not yet set, so 'toggle' would expand
+ // and trigger lazyLoad again.
+ // It would be better to allow to collapse/expand the status node
+ // while loading (instead of ignoring), but that would require some
+ // more work.
+ node.debug("Got 2nd click while loading: ignored");
+ return;
+ }
+ // Clicking the expander icon always expands/collapses
+ this._callHook("nodeToggleExpanded", ctx);
+ } else if (targetType === "checkbox") {
+ // Clicking the checkbox always (de)selects
+ this._callHook("nodeToggleSelected", ctx);
+ if (ctx.options.focusOnSelect) {
+ // #358
+ this._callHook("nodeSetFocus", ctx, true);
+ }
+ } else {
+ // Honor `clickFolderMode` for
+ expand = false;
+ activate = true;
+ if (node.folder) {
+ switch (ctx.options.clickFolderMode) {
+ case 2: // expand only
+ expand = true;
+ activate = false;
+ break;
+ case 3: // expand and activate
+ activate = true;
+ expand = true; //!node.isExpanded();
+ break;
+ // else 1 or 4: just activate
+ }
+ }
+ if (activate) {
+ this.nodeSetFocus(ctx);
+ this._callHook("nodeSetActive", ctx, true);
+ }
+ if (expand) {
+ if (!activate) {
+ // this._callHook("nodeSetFocus", ctx);
+ }
+ // this._callHook("nodeSetExpanded", ctx, true);
+ this._callHook("nodeToggleExpanded", ctx);
+ }
+ }
+ // Make sure that clicks stop, otherwise <a href='#'> jumps to the top
+ // if(event.target.localName === "a" && event.target.className === "fancytree-title"){
+ // event.preventDefault();
+ // }
+ // TODO: return promise?
+ },
+ /** Collapse all other children of same parent.
+ *
+ * @param {EventData} ctx
+ * @param {object} callOpts
+ */
+ nodeCollapseSiblings: function (ctx, callOpts) {
+ // TODO: return promise?
+ var ac,
+ i,
+ l,
+ node = ctx.node;
+
+ if (node.parent) {
+ ac = node.parent.children;
+ for (i = 0, l = ac.length; i < l; i++) {
+ if (ac[i] !== node && ac[i].expanded) {
+ this._callHook(
+ "nodeSetExpanded",
+ ac[i],
+ false,
+ callOpts
+ );
+ }
+ }
+ }
+ },
+ /** Default handling for mouse douleclick events.
+ * @param {EventData} ctx
+ */
+ nodeDblclick: function (ctx) {
+ // TODO: return promise?
+ if (
+ ctx.targetType === "title" &&
+ ctx.options.clickFolderMode === 4
+ ) {
+ // this.nodeSetFocus(ctx);
+ // this._callHook("nodeSetActive", ctx, true);
+ this._callHook("nodeToggleExpanded", ctx);
+ }
+ // TODO: prevent text selection on dblclicks
+ if (ctx.targetType === "title") {
+ ctx.originalEvent.preventDefault();
+ }
+ },
+ /** Default handling for mouse keydown events.
+ *
+ * NOTE: this may be called with node == null if tree (but no node) has focus.
+ * @param {EventData} ctx
+ */
+ nodeKeydown: function (ctx) {
+ // TODO: return promise?
+ var matchNode,
+ stamp,
+ _res,
+ focusNode,
+ event = ctx.originalEvent,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ which = event.which,
+ // #909: Use event.key, to get unicode characters.
+ // We can't use `/\w/.test(key)`, because that would
+ // only detect plain ascii alpha-numerics. But we still need
+ // to ignore modifier-only, whitespace, cursor-keys, etc.
+ key = event.key || String.fromCharCode(which),
+ specialModifiers = !!(
+ event.altKey ||
+ event.ctrlKey ||
+ event.metaKey
+ ),
+ isAlnum =
+ !MODIFIERS[which] &&
+ !SPECIAL_KEYCODES[which] &&
+ !specialModifiers,
+ $target = $(event.target),
+ handled = true,
+ activate = !(event.ctrlKey || !opts.autoActivate);
+
+ // (node || FT).debug("ftnode.nodeKeydown(" + event.type + "): ftnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+ // FT.debug( "eventToString(): " + FT.eventToString(event) + ", key='" + key + "', isAlnum: " + isAlnum );
+
+ // Set focus to active (or first node) if no other node has the focus yet
+ if (!node) {
+ focusNode = this.getActiveNode() || this.getFirstChild();
+ if (focusNode) {
+ focusNode.setFocus();
+ node = ctx.node = this.focusNode;
+ node.debug("Keydown force focus on active node");
+ }
+ }
+
+ if (
+ opts.quicksearch &&
+ isAlnum &&
+ !$target.is(":input:enabled")
+ ) {
+ // Allow to search for longer streaks if typed in quickly
+ stamp = Date.now();
+ if (stamp - tree.lastQuicksearchTime > 500) {
+ tree.lastQuicksearchTerm = "";
+ }
+ tree.lastQuicksearchTime = stamp;
+ tree.lastQuicksearchTerm += key;
+ // tree.debug("quicksearch find", tree.lastQuicksearchTerm);
+ matchNode = tree.findNextNode(
+ tree.lastQuicksearchTerm,
+ tree.getActiveNode()
+ );
+ if (matchNode) {
+ matchNode.setActive();
+ }
+ event.preventDefault();
+ return;
+ }
+ switch (FT.eventToString(event)) {
+ case "+":
+ case "=": // 187: '+' @ Chrome, Safari
+ tree.nodeSetExpanded(ctx, true);
+ break;
+ case "-":
+ tree.nodeSetExpanded(ctx, false);
+ break;
+ case "space":
+ if (node.isPagingNode()) {
+ tree._triggerNodeEvent("clickPaging", ctx, event);
+ } else if (
+ FT.evalOption("checkbox", node, node, opts, false)
+ ) {
+ // #768
+ tree.nodeToggleSelected(ctx);
+ } else {
+ tree.nodeSetActive(ctx, true);
+ }
+ break;
+ case "return":
+ tree.nodeSetActive(ctx, true);
+ break;
+ case "home":
+ case "end":
+ case "backspace":
+ case "left":
+ case "right":
+ case "up":
+ case "down":
+ _res = node.navigate(event.which, activate);
+ break;
+ default:
+ handled = false;
+ }
+ if (handled) {
+ event.preventDefault();
+ }
+ },
+
+ // /** Default handling for mouse keypress events. */
+ // nodeKeypress: function(ctx) {
+ // var event = ctx.originalEvent;
+ // },
+
+ // /** Trigger lazyLoad event (async). */
+ // nodeLazyLoad: function(ctx) {
+ // var node = ctx.node;
+ // if(this._triggerNodeEvent())
+ // },
+ /** Load child nodes (async).
+ *
+ * @param {EventData} ctx
+ * @param {object[]|object|string|$.Promise|function} source
+ * @returns {$.Promise} The deferred will be resolved as soon as the (ajax)
+ * data was rendered.
+ */
+ nodeLoadChildren: function (ctx, source) {
+ var ajax,
+ delay,
+ ajaxDfd = null,
+ resultDfd,
+ isAsync = true,
+ tree = ctx.tree,
+ node = ctx.node,
+ nodePrevParent = node.parent,
+ tag = "nodeLoadChildren",
+ requestId = Date.now();
+
+ // `source` is a callback: use the returned result instead:
+ if (_isFunction(source)) {
+ source = source.call(tree, { type: "source" }, ctx);
+ _assert(
+ !_isFunction(source),
+ "source callback must not return another function"
+ );
+ }
+ // `source` is already a promise:
+ if (_isFunction(source.then)) {
+ // _assert(_isFunction(source.always), "Expected jQuery?");
+ ajaxDfd = source;
+ } else if (source.url) {
+ // `source` is an Ajax options object
+ ajax = $.extend({}, ctx.options.ajax, source);
+ if (ajax.debugDelay) {
+ // Simulate a slow server
+ delay = ajax.debugDelay;
+ delete ajax.debugDelay; // remove debug option
+ if (_isArray(delay)) {
+ // random delay range [min..max]
+ delay =
+ delay[0] +
+ Math.random() * (delay[1] - delay[0]);
+ }
+ node.warn(
+ "nodeLoadChildren waiting debugDelay " +
+ Math.round(delay) +
+ " ms ..."
+ );
+ ajaxDfd = $.Deferred(function (ajaxDfd) {
+ setTimeout(function () {
+ $.ajax(ajax)
+ .done(function () {
+ ajaxDfd.resolveWith(this, arguments);
+ })
+ .fail(function () {
+ ajaxDfd.rejectWith(this, arguments);
+ });
+ }, delay);
+ });
+ } else {
+ ajaxDfd = $.ajax(ajax);
+ }
+ } else if ($.isPlainObject(source) || _isArray(source)) {
+ // `source` is already a constant dict or list, but we convert
+ // to a thenable for unified processing.
+ // 2020-01-03: refactored.
+ // `ajaxDfd = $.when(source)` would do the trick, but the returned
+ // promise will resolve async, which broke some tests and
+ // would probably also break current implementations out there.
+ // So we mock-up a thenable that resolves synchronously:
+ ajaxDfd = {
+ then: function (resolve, reject) {
+ resolve(source, null, null);
+ },
+ };
+ isAsync = false;
+ } else {
+ $.error("Invalid source type: " + source);
+ }
+
+ // Check for overlapping requests
+ if (node._requestId) {
+ node.warn(
+ "Recursive load request #" +
+ requestId +
+ " while #" +
+ node._requestId +
+ " is pending."
+ );
+ node._requestId = requestId;
+ // node.debug("Send load request #" + requestId);
+ }
+
+ if (isAsync) {
+ tree.debugTime(tag);
+ tree.nodeSetStatus(ctx, "loading");
+ }
+
+ // The async Ajax request has now started...
+ // Defer the deferred:
+ // we want to be able to reject invalid responses, even if
+ // the raw HTTP Ajax XHR resolved as Ok.
+ // We use the ajaxDfd.then() syntax here, which is compatible with
+ // jQuery and ECMA6.
+ // However resultDfd is a jQuery deferred, which is currently the
+ // expected result type of nodeLoadChildren()
+ resultDfd = new $.Deferred();
+ ajaxDfd.then(
+ function (data, textStatus, jqXHR) {
+ // ajaxDfd was resolved, but we reject or resolve resultDfd
+ // depending on the response data
+ var errorObj, res;
+
+ if (
+ (source.dataType === "json" ||
+ source.dataType === "jsonp") &&
+ typeof data === "string"
+ ) {
+ $.error(
+ "Ajax request returned a string (did you get the JSON dataType wrong?)."
+ );
+ }
+ if (node._requestId && node._requestId > requestId) {
+ // The expected request time stamp is later than `requestId`
+ // (which was kept as as closure variable to this handler function)
+ // node.warn("Ignored load response for obsolete request #" + requestId + " (expected #" + node._requestId + ")");
+ resultDfd.rejectWith(this, [
+ RECURSIVE_REQUEST_ERROR,
+ ]);
+ return;
+ // } else {
+ // node.debug("Response returned for load request #" + requestId);
+ }
+ if (node.parent === null && nodePrevParent !== null) {
+ resultDfd.rejectWith(this, [
+ INVALID_REQUEST_TARGET_ERROR,
+ ]);
+ return;
+ }
+ // Allow to adjust the received response data in the `postProcess` event.
+ if (ctx.options.postProcess) {
+ // The handler may either
+ // - modify `ctx.response` in-place (and leave `ctx.result` undefined)
+ // => res = undefined
+ // - return a replacement in `ctx.result`
+ // => res = <new data>
+ // If res contains an `error` property, an error status is displayed
+ try {
+ res = tree._triggerNodeEvent(
+ "postProcess",
+ ctx,
+ ctx.originalEvent,
+ {
+ response: data,
+ error: null,
+ dataType: source.dataType,
+ }
+ );
+ if (res.error) {
+ tree.warn(
+ "postProcess returned error:",
+ res
+ );
+ }
+ } catch (e) {
+ res = {
+ error: e,
+ message: "" + e,
+ details: "postProcess failed",
+ };
+ }
+ if (res.error) {
+ // Either postProcess failed with an exception, or the returned
+ // result object has an 'error' property attached:
+ errorObj = $.isPlainObject(res.error)
+ ? res.error
+ : { message: res.error };
+ errorObj = tree._makeHookContext(
+ node,
+ null,
+ errorObj
+ );
+ resultDfd.rejectWith(this, [errorObj]);
+ return;
+ }
+ if (
+ _isArray(res) ||
+ ($.isPlainObject(res) && _isArray(res.children))
+ ) {
+ // Use `ctx.result` if valid
+ // (otherwise use existing data, which may have been modified in-place)
+ data = res;
+ }
+ } else if (
+ data &&
+ _hasProp(data, "d") &&
+ ctx.options.enableAspx
+ ) {
+ // Process ASPX WebMethod JSON object inside "d" property
+ // (only if no postProcess event was defined)
+ if (ctx.options.enableAspx === 42) {
+ tree.warn(
+ "The default for enableAspx will change to `false` in the fututure. " +
+ "Pass `enableAspx: true` or implement postProcess to silence this warning."
+ );
+ }
+ data =
+ typeof data.d === "string"
+ ? $.parseJSON(data.d)
+ : data.d;
+ }
+ resultDfd.resolveWith(this, [data]);
+ },
+ function (jqXHR, textStatus, errorThrown) {
+ // ajaxDfd was rejected, so we reject resultDfd as well
+ var errorObj = tree._makeHookContext(node, null, {
+ error: jqXHR,
+ args: Array.prototype.slice.call(arguments),
+ message: errorThrown,
+ details: jqXHR.status + ": " + errorThrown,
+ });
+ resultDfd.rejectWith(this, [errorObj]);
+ }
+ );
+
+ // The async Ajax request has now started.
+ // resultDfd will be resolved/rejected after the response arrived,
+ // was postProcessed, and checked.
+ // Now we implement the UI update and add the data to the tree.
+ // We also return this promise to the caller.
+ resultDfd
+ .done(function (data) {
+ tree.nodeSetStatus(ctx, "ok");
+ var children, metaData, noDataRes;
+
+ if ($.isPlainObject(data)) {
+ // We got {foo: 'abc', children: [...]}
+ // Copy extra properties to tree.data.foo
+ _assert(
+ node.isRootNode(),
+ "source may only be an object for root nodes (expecting an array of child objects otherwise)"
+ );
+ _assert(
+ _isArray(data.children),
+ "if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"
+ );
+ metaData = data;
+ children = data.children;
+ delete metaData.children;
+ // Copy some attributes to tree.data
+ $.each(TREE_ATTRS, function (i, attr) {
+ if (metaData[attr] !== undefined) {
+ tree[attr] = metaData[attr];
+ delete metaData[attr];
+ }
+ });
+ // Copy all other attributes to tree.data.NAME
+ $.extend(tree.data, metaData);
+ } else {
+ children = data;
+ }
+ _assert(
+ _isArray(children),
+ "expected array of children"
+ );
+ node._setChildren(children);
+
+ if (tree.options.nodata && children.length === 0) {
+ if (_isFunction(tree.options.nodata)) {
+ noDataRes = tree.options.nodata.call(
+ tree,
+ { type: "nodata" },
+ ctx
+ );
+ } else if (
+ tree.options.nodata === true &&
+ node.isRootNode()
+ ) {
+ noDataRes = tree.options.strings.noData;
+ } else if (
+ typeof tree.options.nodata === "string" &&
+ node.isRootNode()
+ ) {
+ noDataRes = tree.options.nodata;
+ }
+ if (noDataRes) {
+ node.setStatus("nodata", noDataRes);
+ }
+ }
+ // trigger fancytreeloadchildren
+ tree._triggerNodeEvent("loadChildren", node);
+ })
+ .fail(function (error) {
+ var ctxErr;
+
+ if (error === RECURSIVE_REQUEST_ERROR) {
+ node.warn(
+ "Ignored response for obsolete load request #" +
+ requestId +
+ " (expected #" +
+ node._requestId +
+ ")"
+ );
+ return;
+ } else if (error === INVALID_REQUEST_TARGET_ERROR) {
+ node.warn(
+ "Lazy parent node was removed while loading: discarding response."
+ );
+ return;
+ } else if (error.node && error.error && error.message) {
+ // error is already a context object
+ ctxErr = error;
+ } else {
+ ctxErr = tree._makeHookContext(node, null, {
+ error: error, // it can be jqXHR or any custom error
+ args: Array.prototype.slice.call(arguments),
+ message: error
+ ? error.message || error.toString()
+ : "",
+ });
+ if (ctxErr.message === "[object Object]") {
+ ctxErr.message = "";
+ }
+ }
+ node.warn(
+ "Load children failed (" + ctxErr.message + ")",
+ ctxErr
+ );
+ if (
+ tree._triggerNodeEvent(
+ "loadError",
+ ctxErr,
+ null
+ ) !== false
+ ) {
+ tree.nodeSetStatus(
+ ctx,
+ "error",
+ ctxErr.message,
+ ctxErr.details
+ );
+ }
+ })
+ .always(function () {
+ node._requestId = null;
+ if (isAsync) {
+ tree.debugTimeEnd(tag);
+ }
+ });
+
+ return resultDfd.promise();
+ },
+ /** [Not Implemented] */
+ nodeLoadKeyPath: function (ctx, keyPathList) {
+ // TODO: implement and improve
+ // http://code.google.com/p/dynatree/issues/detail?id=222
+ },
+ /**
+ * Remove a single direct child of ctx.node.
+ * @param {EventData} ctx
+ * @param {FancytreeNode} childNode dircect child of ctx.node
+ */
+ nodeRemoveChild: function (ctx, childNode) {
+ var idx,
+ node = ctx.node,
+ // opts = ctx.options,
+ subCtx = $.extend({}, ctx, { node: childNode }),
+ children = node.children;
+
+ // FT.debug("nodeRemoveChild()", node.toString(), childNode.toString());
+
+ if (children.length === 1) {
+ _assert(childNode === children[0], "invalid single child");
+ return this.nodeRemoveChildren(ctx);
+ }
+ if (
+ this.activeNode &&
+ (childNode === this.activeNode ||
+ this.activeNode.isDescendantOf(childNode))
+ ) {
+ this.activeNode.setActive(false); // TODO: don't fire events
+ }
+ if (
+ this.focusNode &&
+ (childNode === this.focusNode ||
+ this.focusNode.isDescendantOf(childNode))
+ ) {
+ this.focusNode = null;
+ }
+ // TODO: persist must take care to clear select and expand cookies
+ this.nodeRemoveMarkup(subCtx);
+ this.nodeRemoveChildren(subCtx);
+ idx = $.inArray(childNode, children);
+ _assert(idx >= 0, "invalid child");
+ // Notify listeners
+ node.triggerModifyChild("remove", childNode);
+ // Unlink to support GC
+ childNode.visit(function (n) {
+ n.parent = null;
+ }, true);
+ this._callHook("treeRegisterNode", this, false, childNode);
+ // remove from child list
+ children.splice(idx, 1);
+ },
+ /**Remove HTML markup for all descendents of ctx.node.
+ * @param {EventData} ctx
+ */
+ nodeRemoveChildMarkup: function (ctx) {
+ var node = ctx.node;
+
+ // FT.debug("nodeRemoveChildMarkup()", node.toString());
+ // TODO: Unlink attr.ftnode to support GC
+ if (node.ul) {
+ if (node.isRootNode()) {
+ $(node.ul).empty();
+ } else {
+ $(node.ul).remove();
+ node.ul = null;
+ }
+ node.visit(function (n) {
+ n.li = n.ul = null;
+ });
+ }
+ },
+ /**Remove all descendants of ctx.node.
+ * @param {EventData} ctx
+ */
+ nodeRemoveChildren: function (ctx) {
+ var //subCtx,
+ tree = ctx.tree,
+ node = ctx.node,
+ children = node.children;
+ // opts = ctx.options;
+
+ // FT.debug("nodeRemoveChildren()", node.toString());
+ if (!children) {
+ return;
+ }
+ if (this.activeNode && this.activeNode.isDescendantOf(node)) {
+ this.activeNode.setActive(false); // TODO: don't fire events
+ }
+ if (this.focusNode && this.focusNode.isDescendantOf(node)) {
+ this.focusNode = null;
+ }
+ // TODO: persist must take care to clear select and expand cookies
+ this.nodeRemoveChildMarkup(ctx);
+ // Unlink children to support GC
+ // TODO: also delete this.children (not possible using visit())
+ // subCtx = $.extend({}, ctx);
+ node.triggerModifyChild("remove", null);
+ node.visit(function (n) {
+ n.parent = null;
+ tree._callHook("treeRegisterNode", tree, false, n);
+ });
+ if (node.lazy) {
+ // 'undefined' would be interpreted as 'not yet loaded' for lazy nodes
+ node.children = [];
+ } else {
+ node.children = null;
+ }
+ if (!node.isRootNode()) {
+ node.expanded = false; // #449, #459
+ }
+ this.nodeRenderStatus(ctx);
+ },
+ /**Remove HTML markup for ctx.node and all its descendents.
+ * @param {EventData} ctx
+ */
+ nodeRemoveMarkup: function (ctx) {
+ var node = ctx.node;
+ // FT.debug("nodeRemoveMarkup()", node.toString());
+ // TODO: Unlink attr.ftnode to support GC
+ if (node.li) {
+ $(node.li).remove();
+ node.li = null;
+ }
+ this.nodeRemoveChildMarkup(ctx);
+ },
+ /**
+ * Create `<li><span>..</span> .. </li>` tags for this node.
+ *
+ * This method takes care that all HTML markup is created that is required
+ * to display this node in its current state.
+ *
+ * Call this method to create new nodes, or after the strucuture
+ * was changed (e.g. after moving this node or adding/removing children)
+ * nodeRenderTitle() and nodeRenderStatus() are implied.
+ *
+ * ```html
+ * <li id='KEY' ftnode=NODE>
+ * <span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'>
+ * <span class="fancytree-expander"></span>
+ * <span class="fancytree-checkbox"></span> // only present in checkbox mode
+ * <span class="fancytree-icon"></span>
+ * <a href="#" class="fancytree-title"> Node 1 </a>
+ * </span>
+ * <ul> // only present if node has children
+ * <li id='KEY' ftnode=NODE> child1 ... </li>
+ * <li id='KEY' ftnode=NODE> child2 ... </li>
+ * </ul>
+ * </li>
+ * ```
+ *
+ * @param {EventData} ctx
+ * @param {boolean} [force=false] re-render, even if html markup was already created
+ * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+ * @param {boolean} [collapsed=false] force root node to be collapsed, so we can apply animated expand later
+ */
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ /* This method must take care of all cases where the current data mode
+ * (i.e. node hierarchy) does not match the current markup.
+ *
+ * - node was not yet rendered:
+ * create markup
+ * - node was rendered: exit fast
+ * - children have been added
+ * - children have been removed
+ */
+ var childLI,
+ childNode1,
+ childNode2,
+ i,
+ l,
+ next,
+ subCtx,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ aria = opts.aria,
+ firstTime = false,
+ parent = node.parent,
+ isRootNode = !parent,
+ children = node.children,
+ successorLi = null;
+ // FT.debug("nodeRender(" + !!force + ", " + !!deep + ")", node.toString());
+
+ if (tree._enableUpdate === false) {
+ // tree.debug("no render", tree._enableUpdate);
+ return;
+ }
+ if (!isRootNode && !parent.ul) {
+ // Calling node.collapse on a deep, unrendered node
+ return;
+ }
+ _assert(isRootNode || parent.ul, "parent UL must exist");
+
+ // Render the node
+ if (!isRootNode) {
+ // Discard markup on force-mode, or if it is not linked to parent <ul>
+ if (
+ node.li &&
+ (force || node.li.parentNode !== node.parent.ul)
+ ) {
+ if (node.li.parentNode === node.parent.ul) {
+ // #486: store following node, so we can insert the new markup there later
+ successorLi = node.li.nextSibling;
+ } else {
+ // May happen, when a top-level node was dropped over another
+ this.debug(
+ "Unlinking " +
+ node +
+ " (must be child of " +
+ node.parent +
+ ")"
+ );
+ }
+ // this.debug("nodeRemoveMarkup...");
+ this.nodeRemoveMarkup(ctx);
+ }
+ // Create <li><span /> </li>
+ // node.debug("render...");
+ if (node.li) {
+ // this.nodeRenderTitle(ctx);
+ this.nodeRenderStatus(ctx);
+ } else {
+ // node.debug("render... really");
+ firstTime = true;
+ node.li = document.createElement("li");
+ node.li.ftnode = node;
+
+ if (node.key && opts.generateIds) {
+ node.li.id = opts.idPrefix + node.key;
+ }
+ node.span = document.createElement("span");
+ node.span.className = "fancytree-node";
+ if (aria && !node.tr) {
+ $(node.li).attr("role", "treeitem");
+ }
+ node.li.appendChild(node.span);
+
+ // Create inner HTML for the <span> (expander, checkbox, icon, and title)
+ this.nodeRenderTitle(ctx);
+
+ // Allow tweaking and binding, after node was created for the first time
+ if (opts.createNode) {
+ opts.createNode.call(
+ tree,
+ { type: "createNode" },
+ ctx
+ );
+ }
+ }
+ // Allow tweaking after node state was rendered
+ if (opts.renderNode) {
+ opts.renderNode.call(tree, { type: "renderNode" }, ctx);
+ }
+ }
+
+ // Visit child nodes
+ if (children) {
+ if (isRootNode || node.expanded || deep === true) {
+ // Create a UL to hold the children
+ if (!node.ul) {
+ node.ul = document.createElement("ul");
+ if (
+ (collapsed === true && !_recursive) ||
+ !node.expanded
+ ) {
+ // hide top UL, so we can use an animation to show it later
+ node.ul.style.display = "none";
+ }
+ if (aria) {
+ $(node.ul).attr("role", "group");
+ }
+ if (node.li) {
+ // issue #67
+ node.li.appendChild(node.ul);
+ } else {
+ node.tree.$div.append(node.ul);
+ }
+ }
+ // Add child markup
+ for (i = 0, l = children.length; i < l; i++) {
+ subCtx = $.extend({}, ctx, { node: children[i] });
+ this.nodeRender(subCtx, force, deep, false, true);
+ }
+ // Remove <li> if nodes have moved to another parent
+ childLI = node.ul.firstChild;
+ while (childLI) {
+ childNode2 = childLI.ftnode;
+ if (childNode2 && childNode2.parent !== node) {
+ node.debug(
+ "_fixParent: remove missing " + childNode2,
+ childLI
+ );
+ next = childLI.nextSibling;
+ childLI.parentNode.removeChild(childLI);
+ childLI = next;
+ } else {
+ childLI = childLI.nextSibling;
+ }
+ }
+ // Make sure, that <li> order matches node.children order.
+ childLI = node.ul.firstChild;
+ for (i = 0, l = children.length - 1; i < l; i++) {
+ childNode1 = children[i];
+ childNode2 = childLI.ftnode;
+ if (childNode1 === childNode2) {
+ childLI = childLI.nextSibling;
+ } else {
+ // node.debug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2);
+ node.ul.insertBefore(
+ childNode1.li,
+ childNode2.li
+ );
+ }
+ }
+ }
+ } else {
+ // No children: remove markup if any
+ if (node.ul) {
+ // alert("remove child markup for " + node);
+ this.warn("remove child markup for " + node);
+ this.nodeRemoveChildMarkup(ctx);
+ }
+ }
+ if (!isRootNode) {
+ // Update element classes according to node state
+ // this.nodeRenderStatus(ctx);
+ // Finally add the whole structure to the DOM, so the browser can render
+ if (firstTime) {
+ // #486: successorLi is set, if we re-rendered (i.e. discarded)
+ // existing markup, which we want to insert at the same position.
+ // (null is equivalent to append)
+ // parent.ul.appendChild(node.li);
+ parent.ul.insertBefore(node.li, successorLi);
+ }
+ }
+ },
+ /** Create HTML inside the node's outer `<span>` (i.e. expander, checkbox,
+ * icon, and title).
+ *
+ * nodeRenderStatus() is implied.
+ * @param {EventData} ctx
+ * @param {string} [title] optinal new title
+ */
+ nodeRenderTitle: function (ctx, title) {
+ // set node connector images, links and text
+ var checkbox,
+ className,
+ icon,
+ nodeTitle,
+ role,
+ tabindex,
+ tooltip,
+ iconTooltip,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ aria = opts.aria,
+ level = node.getLevel(),
+ ares = [];
+
+ if (title !== undefined) {
+ node.title = title;
+ }
+ if (!node.span || tree._enableUpdate === false) {
+ // Silently bail out if node was not rendered yet, assuming
+ // node.render() will be called as the node becomes visible
+ return;
+ }
+ // Connector (expanded, expandable or simple)
+ role =
+ aria && node.hasChildren() !== false
+ ? " role='button'"
+ : "";
+ if (level < opts.minExpandLevel) {
+ if (!node.lazy) {
+ node.expanded = true;
+ }
+ if (level > 1) {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-expander fancytree-expander-fixed'></span>"
+ );
+ }
+ // .. else (i.e. for root level) skip expander/connector alltogether
+ } else {
+ ares.push(
+ "<span " + role + " class='fancytree-expander'></span>"
+ );
+ }
+ // Checkbox mode
+ checkbox = FT.evalOption("checkbox", node, node, opts, false);
+
+ if (checkbox && !node.isStatusNode()) {
+ role = aria ? " role='checkbox'" : "";
+ className = "fancytree-checkbox";
+ if (
+ checkbox === "radio" ||
+ (node.parent && node.parent.radiogroup)
+ ) {
+ className += " fancytree-radio";
+ }
+ ares.push(
+ "<span " + role + " class='" + className + "'></span>"
+ );
+ }
+ // Folder or doctype icon
+ if (node.data.iconClass !== undefined) {
+ // 2015-11-16
+ // Handle / warn about backward compatibility
+ if (node.icon) {
+ $.error(
+ "'iconClass' node option is deprecated since v2.14.0: use 'icon' only instead"
+ );
+ } else {
+ node.warn(
+ "'iconClass' node option is deprecated since v2.14.0: use 'icon' instead"
+ );
+ node.icon = node.data.iconClass;
+ }
+ }
+ // If opts.icon is a callback and returns something other than undefined, use that
+ // else if node.icon is a boolean or string, use that
+ // else if opts.icon is a boolean or string, use that
+ // else show standard icon (which may be different for folders or documents)
+ icon = FT.evalOption("icon", node, node, opts, true);
+ // if( typeof icon !== "boolean" ) {
+ // // icon is defined, but not true/false: must be a string
+ // icon = "" + icon;
+ // }
+ if (icon !== false) {
+ role = aria ? " role='presentation'" : "";
+
+ iconTooltip = FT.evalOption(
+ "iconTooltip",
+ node,
+ node,
+ opts,
+ null
+ );
+ iconTooltip = iconTooltip
+ ? " title='" + _escapeTooltip(iconTooltip) + "'"
+ : "";
+
+ if (typeof icon === "string") {
+ if (TEST_IMG.test(icon)) {
+ // node.icon is an image url. Prepend imagePath
+ icon =
+ icon.charAt(0) === "/"
+ ? icon
+ : (opts.imagePath || "") + icon;
+ ares.push(
+ "<img src='" +
+ icon +
+ "' class='fancytree-icon'" +
+ iconTooltip +
+ " alt='' />"
+ );
+ } else {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-custom-icon " +
+ icon +
+ "'" +
+ iconTooltip +
+ "></span>"
+ );
+ }
+ } else if (icon.text) {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-custom-icon " +
+ (icon.addClass || "") +
+ "'" +
+ iconTooltip +
+ ">" +
+ FT.escapeHtml(icon.text) +
+ "</span>"
+ );
+ } else if (icon.html) {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-custom-icon " +
+ (icon.addClass || "") +
+ "'" +
+ iconTooltip +
+ ">" +
+ icon.html +
+ "</span>"
+ );
+ } else {
+ // standard icon: theme css will take care of this
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-icon'" +
+ iconTooltip +
+ "></span>"
+ );
+ }
+ }
+ // Node title
+ nodeTitle = "";
+ if (opts.renderTitle) {
+ nodeTitle =
+ opts.renderTitle.call(
+ tree,
+ { type: "renderTitle" },
+ ctx
+ ) || "";
+ }
+ if (!nodeTitle) {
+ tooltip = FT.evalOption("tooltip", node, node, opts, null);
+ if (tooltip === true) {
+ tooltip = node.title;
+ }
+ // if( node.tooltip ) {
+ // tooltip = node.tooltip;
+ // } else if ( opts.tooltip ) {
+ // tooltip = opts.tooltip === true ? node.title : opts.tooltip.call(tree, node);
+ // }
+ tooltip = tooltip
+ ? " title='" + _escapeTooltip(tooltip) + "'"
+ : "";
+ tabindex = opts.titlesTabbable ? " tabindex='0'" : "";
+
+ nodeTitle =
+ "<span class='fancytree-title'" +
+ tooltip +
+ tabindex +
+ ">" +
+ (opts.escapeTitles
+ ? FT.escapeHtml(node.title)
+ : node.title) +
+ "</span>";
+ }
+ ares.push(nodeTitle);
+ // Note: this will trigger focusout, if node had the focus
+ //$(node.span).html(ares.join("")); // it will cleanup the jQuery data currently associated with SPAN (if any), but it executes more slowly
+ node.span.innerHTML = ares.join("");
+ // Update CSS classes
+ this.nodeRenderStatus(ctx);
+ if (opts.enhanceTitle) {
+ ctx.$title = $(">span.fancytree-title", node.span);
+ nodeTitle =
+ opts.enhanceTitle.call(
+ tree,
+ { type: "enhanceTitle" },
+ ctx
+ ) || "";
+ }
+ },
+ /** Update element classes according to node state.
+ * @param {EventData} ctx
+ */
+ nodeRenderStatus: function (ctx) {
+ // Set classes for current status
+ var $ariaElem,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ // nodeContainer = node[tree.nodeContainerAttrName],
+ hasChildren = node.hasChildren(),
+ isLastSib = node.isLastSibling(),
+ aria = opts.aria,
+ cn = opts._classNames,
+ cnList = [],
+ statusElem = node[tree.statusClassPropName];
+
+ if (!statusElem || tree._enableUpdate === false) {
+ // if this function is called for an unrendered node, ignore it (will be updated on nect render anyway)
+ return;
+ }
+ if (aria) {
+ $ariaElem = $(node.tr || node.li);
+ }
+ // Build a list of class names that we will add to the node <span>
+ cnList.push(cn.node);
+ if (tree.activeNode === node) {
+ cnList.push(cn.active);
+ // $(">span.fancytree-title", statusElem).attr("tabindex", "0");
+ // tree.$container.removeAttr("tabindex");
+ // }else{
+ // $(">span.fancytree-title", statusElem).removeAttr("tabindex");
+ // tree.$container.attr("tabindex", "0");
+ }
+ if (tree.focusNode === node) {
+ cnList.push(cn.focused);
+ }
+ if (node.expanded) {
+ cnList.push(cn.expanded);
+ }
+ if (aria) {
+ if (hasChildren === false) {
+ $ariaElem.removeAttr("aria-expanded");
+ } else {
+ $ariaElem.attr("aria-expanded", Boolean(node.expanded));
+ }
+ }
+ if (node.folder) {
+ cnList.push(cn.folder);
+ }
+ if (hasChildren !== false) {
+ cnList.push(cn.hasChildren);
+ }
+ // TODO: required?
+ if (isLastSib) {
+ cnList.push(cn.lastsib);
+ }
+ if (node.lazy && node.children == null) {
+ cnList.push(cn.lazy);
+ }
+ if (node.partload) {
+ cnList.push(cn.partload);
+ }
+ if (node.partsel) {
+ cnList.push(cn.partsel);
+ }
+ if (FT.evalOption("unselectable", node, node, opts, false)) {
+ cnList.push(cn.unselectable);
+ }
+ if (node._isLoading) {
+ cnList.push(cn.loading);
+ }
+ if (node._error) {
+ cnList.push(cn.error);
+ }
+ if (node.statusNodeType) {
+ cnList.push(cn.statusNodePrefix + node.statusNodeType);
+ }
+ if (node.selected) {
+ cnList.push(cn.selected);
+ if (aria) {
+ $ariaElem.attr("aria-selected", true);
+ }
+ } else if (aria) {
+ $ariaElem.attr("aria-selected", false);
+ }
+ if (node.extraClasses) {
+ cnList.push(node.extraClasses);
+ }
+ // IE6 doesn't correctly evaluate multiple class names,
+ // so we create combined class names that can be used in the CSS
+ if (hasChildren === false) {
+ cnList.push(
+ cn.combinedExpanderPrefix + "n" + (isLastSib ? "l" : "")
+ );
+ } else {
+ cnList.push(
+ cn.combinedExpanderPrefix +
+ (node.expanded ? "e" : "c") +
+ (node.lazy && node.children == null ? "d" : "") +
+ (isLastSib ? "l" : "")
+ );
+ }
+ cnList.push(
+ cn.combinedIconPrefix +
+ (node.expanded ? "e" : "c") +
+ (node.folder ? "f" : "")
+ );
+ // node.span.className = cnList.join(" ");
+ statusElem.className = cnList.join(" ");
+
+ // TODO: we should not set this in the <span> tag also, if we set it here:
+ // Maybe most (all) of the classes should be set in LI instead of SPAN?
+ if (node.li) {
+ // #719: we have to consider that there may be already other classes:
+ $(node.li).toggleClass(cn.lastsib, isLastSib);
+ }
+ },
+ /** Activate node.
+ * flag defaults to true.
+ * If flag is true, the node is activated (must be a synchronous operation)
+ * If flag is false, the node is deactivated (must be a synchronous operation)
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}
+ * @returns {$.Promise}
+ */
+ nodeSetActive: function (ctx, flag, callOpts) {
+ // Handle user click / [space] / [enter], according to clickFolderMode.
+ callOpts = callOpts || {};
+ var subCtx,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ noEvents = callOpts.noEvents === true,
+ noFocus = callOpts.noFocus === true,
+ scroll = callOpts.scrollIntoView !== false,
+ isActive = node === tree.activeNode;
+
+ // flag defaults to true
+ flag = flag !== false;
+ // node.debug("nodeSetActive", flag);
+
+ if (isActive === flag) {
+ // Nothing to do
+ return _getResolvedPromise(node);
+ }
+ // #1042: don't scroll between mousedown/-up when clicking an embedded link
+ if (
+ scroll &&
+ ctx.originalEvent &&
+ $(ctx.originalEvent.target).is("a,:checkbox")
+ ) {
+ node.info("Not scrolling while clicking an embedded link.");
+ scroll = false;
+ }
+ if (
+ flag &&
+ !noEvents &&
+ this._triggerNodeEvent(
+ "beforeActivate",
+ node,
+ ctx.originalEvent
+ ) === false
+ ) {
+ // Callback returned false
+ return _getRejectedPromise(node, ["rejected"]);
+ }
+ if (flag) {
+ if (tree.activeNode) {
+ _assert(
+ tree.activeNode !== node,
+ "node was active (inconsistency)"
+ );
+ subCtx = $.extend({}, ctx, { node: tree.activeNode });
+ tree.nodeSetActive(subCtx, false);
+ _assert(
+ tree.activeNode === null,
+ "deactivate was out of sync?"
+ );
+ }
+
+ if (opts.activeVisible) {
+ // If no focus is set (noFocus: true) and there is no focused node, this node is made visible.
+ // scroll = noFocus && tree.focusNode == null;
+ // #863: scroll by default (unless `scrollIntoView: false` was passed)
+ node.makeVisible({ scrollIntoView: scroll });
+ }
+ tree.activeNode = node;
+ tree.nodeRenderStatus(ctx);
+ if (!noFocus) {
+ tree.nodeSetFocus(ctx);
+ }
+ if (!noEvents) {
+ tree._triggerNodeEvent(
+ "activate",
+ node,
+ ctx.originalEvent
+ );
+ }
+ } else {
+ _assert(
+ tree.activeNode === node,
+ "node was not active (inconsistency)"
+ );
+ tree.activeNode = null;
+ this.nodeRenderStatus(ctx);
+ if (!noEvents) {
+ ctx.tree._triggerNodeEvent(
+ "deactivate",
+ node,
+ ctx.originalEvent
+ );
+ }
+ }
+ return _getResolvedPromise(node);
+ },
+ /** Expand or collapse node, return Deferred.promise.
+ *
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ * @param {object} [opts] additional options. Defaults to `{noAnimation: false, noEvents: false}`
+ * @returns {$.Promise} The deferred will be resolved as soon as the (lazy)
+ * data was retrieved, rendered, and the expand animation finished.
+ */
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ callOpts = callOpts || {};
+ var _afterLoad,
+ dfd,
+ i,
+ l,
+ parents,
+ prevAC,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ noAnimation = callOpts.noAnimation === true,
+ noEvents = callOpts.noEvents === true;
+
+ // flag defaults to true
+ flag = flag !== false;
+
+ // node.debug("nodeSetExpanded(" + flag + ")");
+
+ if ($(node.li).hasClass(opts._classNames.animating)) {
+ node.warn(
+ "setExpanded(" + flag + ") while animating: ignored."
+ );
+ return _getRejectedPromise(node, ["recursion"]);
+ }
+
+ if ((node.expanded && flag) || (!node.expanded && !flag)) {
+ // Nothing to do
+ // node.debug("nodeSetExpanded(" + flag + "): nothing to do");
+ return _getResolvedPromise(node);
+ } else if (flag && !node.lazy && !node.hasChildren()) {
+ // Prevent expanding of empty nodes
+ // return _getRejectedPromise(node, ["empty"]);
+ return _getResolvedPromise(node);
+ } else if (!flag && node.getLevel() < opts.minExpandLevel) {
+ // Prevent collapsing locked levels
+ return _getRejectedPromise(node, ["locked"]);
+ } else if (
+ !noEvents &&
+ this._triggerNodeEvent(
+ "beforeExpand",
+ node,
+ ctx.originalEvent
+ ) === false
+ ) {
+ // Callback returned false
+ return _getRejectedPromise(node, ["rejected"]);
+ }
+ // If this node inside a collpased node, no animation and scrolling is needed
+ if (!noAnimation && !node.isVisible()) {
+ noAnimation = callOpts.noAnimation = true;
+ }
+
+ dfd = new $.Deferred();
+
+ // Auto-collapse mode: collapse all siblings
+ if (flag && !node.expanded && opts.autoCollapse) {
+ parents = node.getParentList(false, true);
+ prevAC = opts.autoCollapse;
+ try {
+ opts.autoCollapse = false;
+ for (i = 0, l = parents.length; i < l; i++) {
+ // TODO: should return promise?
+ this._callHook(
+ "nodeCollapseSiblings",
+ parents[i],
+ callOpts
+ );
+ }
+ } finally {
+ opts.autoCollapse = prevAC;
+ }
+ }
+ // Trigger expand/collapse after expanding
+ dfd.done(function () {
+ var lastChild = node.getLastChild();
+
+ if (
+ flag &&
+ opts.autoScroll &&
+ !noAnimation &&
+ lastChild &&
+ tree._enableUpdate
+ ) {
+ // Scroll down to last child, but keep current node visible
+ lastChild
+ .scrollIntoView(true, { topNode: node })
+ .always(function () {
+ if (!noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ });
+ } else {
+ if (!noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ }
+ });
+ // vvv Code below is executed after loading finished:
+ _afterLoad = function (callback) {
+ var cn = opts._classNames,
+ isVisible,
+ isExpanded,
+ effect = opts.toggleEffect;
+
+ node.expanded = flag;
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ flag ? "expand" : "collapse"
+ );
+ // Create required markup, but make sure the top UL is hidden, so we
+ // can animate later
+ tree._callHook("nodeRender", ctx, false, false, true);
+
+ // Hide children, if node is collapsed
+ if (node.ul) {
+ isVisible = node.ul.style.display !== "none";
+ isExpanded = !!node.expanded;
+ if (isVisible === isExpanded) {
+ node.warn(
+ "nodeSetExpanded: UL.style.display already set"
+ );
+ } else if (!effect || noAnimation) {
+ node.ul.style.display =
+ node.expanded || !parent ? "" : "none";
+ } else {
+ // The UI toggle() effect works with the ext-wide extension,
+ // while jQuery.animate() has problems when the title span
+ // has position: absolute.
+ // Since jQuery UI 1.12, the blind effect requires the parent
+ // element to have 'position: relative'.
+ // See #716, #717
+ $(node.li).addClass(cn.animating); // #717
+
+ if (_isFunction($(node.ul)[effect.effect])) {
+ // tree.debug( "use jquery." + effect.effect + " method" );
+ $(node.ul)[effect.effect]({
+ duration: effect.duration,
+ always: function () {
+ // node.debug("fancytree-animating end: " + node.li.className);
+ $(this).removeClass(cn.animating); // #716
+ $(node.li).removeClass(cn.animating); // #717
+ callback();
+ },
+ });
+ } else {
+ // The UI toggle() effect works with the ext-wide extension,
+ // while jQuery.animate() has problems when the title span
+ // has positon: absolute.
+ // Since jQuery UI 1.12, the blind effect requires the parent
+ // element to have 'position: relative'.
+ // See #716, #717
+ // tree.debug("use specified effect (" + effect.effect + ") with the jqueryui.toggle method");
+
+ // try to stop an animation that might be already in progress
+ $(node.ul).stop(true, true); //< does not work after resetLazy has been called for a node whose animation wasn't complete and effect was "blind"
+
+ // dirty fix to remove a defunct animation (effect: "blind") after resetLazy has been called
+ $(node.ul)
+ .parent()
+ .find(".ui-effects-placeholder")
+ .remove();
+
+ $(node.ul).toggle(
+ effect.effect,
+ effect.options,
+ effect.duration,
+ function () {
+ // node.debug("fancytree-animating end: " + node.li.className);
+ $(this).removeClass(cn.animating); // #716
+ $(node.li).removeClass(cn.animating); // #717
+ callback();
+ }
+ );
+ }
+ return;
+ }
+ }
+ callback();
+ };
+ // ^^^ Code above is executed after loading finshed.
+
+ // Load lazy nodes, if any. Then continue with _afterLoad()
+ if (flag && node.lazy && node.hasChildren() === undefined) {
+ // node.debug("nodeSetExpanded: load start...");
+ node.load()
+ .done(function () {
+ // node.debug("nodeSetExpanded: load done");
+ if (dfd.notifyWith) {
+ // requires jQuery 1.6+
+ dfd.notifyWith(node, ["loaded"]);
+ }
+ _afterLoad(function () {
+ dfd.resolveWith(node);
+ });
+ })
+ .fail(function (errMsg) {
+ _afterLoad(function () {
+ dfd.rejectWith(node, [
+ "load failed (" + errMsg + ")",
+ ]);
+ });
+ });
+ /*
+ var source = tree._triggerNodeEvent("lazyLoad", node, ctx.originalEvent);
+ _assert(typeof source !== "boolean", "lazyLoad event must return source in data.result");
+ node.debug("nodeSetExpanded: load start...");
+ this._callHook("nodeLoadChildren", ctx, source).done(function(){
+ node.debug("nodeSetExpanded: load done");
+ if(dfd.notifyWith){ // requires jQuery 1.6+
+ dfd.notifyWith(node, ["loaded"]);
+ }
+ _afterLoad.call(tree);
+ }).fail(function(errMsg){
+ dfd.rejectWith(node, ["load failed (" + errMsg + ")"]);
+ });
+ */
+ } else {
+ _afterLoad(function () {
+ dfd.resolveWith(node);
+ });
+ }
+ // node.debug("nodeSetExpanded: returns");
+ return dfd.promise();
+ },
+ /** Focus or blur this node.
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ */
+ nodeSetFocus: function (ctx, flag) {
+ // ctx.node.debug("nodeSetFocus(" + flag + ")");
+ var ctx2,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = tree.options,
+ // et = ctx.originalEvent && ctx.originalEvent.type,
+ isInput = ctx.originalEvent
+ ? $(ctx.originalEvent.target).is(":input")
+ : false;
+
+ flag = flag !== false;
+
+ // (node || tree).debug("nodeSetFocus(" + flag + "), event: " + et + ", isInput: "+ isInput);
+ // Blur previous node if any
+ if (tree.focusNode) {
+ if (tree.focusNode === node && flag) {
+ // node.debug("nodeSetFocus(" + flag + "): nothing to do");
+ return;
+ }
+ ctx2 = $.extend({}, ctx, { node: tree.focusNode });
+ tree.focusNode = null;
+ this._triggerNodeEvent("blur", ctx2);
+ this._callHook("nodeRenderStatus", ctx2);
+ }
+ // Set focus to container and node
+ if (flag) {
+ if (!this.hasFocus()) {
+ node.debug("nodeSetFocus: forcing container focus");
+ this._callHook("treeSetFocus", ctx, true, {
+ calledByNode: true,
+ });
+ }
+ node.makeVisible({ scrollIntoView: false });
+ tree.focusNode = node;
+ if (opts.titlesTabbable) {
+ if (!isInput) {
+ // #621
+ $(node.span).find(".fancytree-title").focus();
+ }
+ }
+ if (opts.aria) {
+ // Set active descendant to node's span ID (create one, if needed)
+ $(tree.$container).attr(
+ "aria-activedescendant",
+ $(node.tr || node.li)
+ .uniqueId()
+ .attr("id")
+ );
+ // "ftal_" + opts.idPrefix + node.key);
+ }
+ // $(node.span).find(".fancytree-title").focus();
+ this._triggerNodeEvent("focus", ctx);
+
+ // determine if we have focus on or inside tree container
+ var hasFancytreeFocus =
+ document.activeElement === tree.$container.get(0) ||
+ $(document.activeElement, tree.$container).length >= 1;
+
+ if (!hasFancytreeFocus) {
+ // We cannot set KB focus to a node, so use the tree container
+ // #563, #570: IE scrolls on every call to .focus(), if the container
+ // is partially outside the viewport. So do it only, when absolutely
+ // necessary.
+ $(tree.$container).focus();
+ }
+
+ // if( opts.autoActivate ){
+ // tree.nodeSetActive(ctx, true);
+ // }
+ if (opts.autoScroll) {
+ node.scrollIntoView();
+ }
+ this._callHook("nodeRenderStatus", ctx);
+ }
+ },
+ /** (De)Select node, return new status (sync).
+ *
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ * @param {object} [opts] additional options. Defaults to {noEvents: false,
+ * propagateDown: null, propagateUp: null,
+ * callback: null,
+ * }
+ * @returns {boolean} previous status
+ */
+ nodeSetSelected: function (ctx, flag, callOpts) {
+ callOpts = callOpts || {};
+ var node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ noEvents = callOpts.noEvents === true,
+ parent = node.parent;
+
+ // flag defaults to true
+ flag = flag !== false;
+
+ // node.debug("nodeSetSelected(" + flag + ")", ctx);
+
+ // Cannot (de)select unselectable nodes directly (only by propagation or
+ // by setting the `.selected` property)
+ if (FT.evalOption("unselectable", node, node, opts, false)) {
+ return;
+ }
+
+ // Remember the user's intent, in case down -> up propagation prevents
+ // applying it to node.selected
+ node._lastSelectIntent = flag; // Confusing use of '!'
+
+ // Nothing to do?
+ if (!!node.selected === flag) {
+ if (opts.selectMode === 3 && node.partsel && !flag) {
+ // If propagation prevented selecting this node last time, we still
+ // want to allow to apply setSelected(false) now
+ } else {
+ return flag;
+ }
+ }
+
+ if (
+ !noEvents &&
+ this._triggerNodeEvent(
+ "beforeSelect",
+ node,
+ ctx.originalEvent
+ ) === false
+ ) {
+ return !!node.selected;
+ }
+ if (flag && opts.selectMode === 1) {
+ // single selection mode (we don't uncheck all tree nodes, for performance reasons)
+ if (tree.lastSelectedNode) {
+ tree.lastSelectedNode.setSelected(false);
+ }
+ node.selected = flag;
+ } else if (
+ opts.selectMode === 3 &&
+ parent &&
+ !parent.radiogroup &&
+ !node.radiogroup
+ ) {
+ // multi-hierarchical selection mode
+ node.selected = flag;
+ node.fixSelection3AfterClick(callOpts);
+ } else if (parent && parent.radiogroup) {
+ node.visitSiblings(function (n) {
+ n._changeSelectStatusAttrs(flag && n === node);
+ }, true);
+ } else {
+ // default: selectMode: 2, multi selection mode
+ node.selected = flag;
+ }
+ this.nodeRenderStatus(ctx);
+ tree.lastSelectedNode = flag ? node : null;
+ if (!noEvents) {
+ tree._triggerNodeEvent("select", ctx);
+ }
+ },
+ /** Show node status (ok, loading, error, nodata) using styles and a dummy child node.
+ *
+ * @param {EventData} ctx
+ * @param status
+ * @param message
+ * @param details
+ * @since 2.3
+ */
+ nodeSetStatus: function (ctx, status, message, details) {
+ var node = ctx.node,
+ tree = ctx.tree;
+
+ function _clearStatusNode() {
+ // Remove dedicated dummy node, if any
+ var firstChild = node.children ? node.children[0] : null;
+ if (firstChild && firstChild.isStatusNode()) {
+ try {
+ // I've seen exceptions here with loadKeyPath...
+ if (node.ul) {
+ node.ul.removeChild(firstChild.li);
+ firstChild.li = null; // avoid leaks (DT issue 215)
+ }
+ } catch (e) {}
+ if (node.children.length === 1) {
+ node.children = [];
+ } else {
+ node.children.shift();
+ }
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ "clearStatusNode"
+ );
+ }
+ }
+ function _setStatusNode(data, type) {
+ // Create/modify the dedicated dummy node for 'loading...' or
+ // 'error!' status. (only called for direct child of the invisible
+ // system root)
+ var firstChild = node.children ? node.children[0] : null;
+ if (firstChild && firstChild.isStatusNode()) {
+ $.extend(firstChild, data);
+ firstChild.statusNodeType = type;
+ tree._callHook("nodeRenderTitle", firstChild);
+ } else {
+ node._setChildren([data]);
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ "setStatusNode"
+ );
+ node.children[0].statusNodeType = type;
+ tree.render();
+ }
+ return node.children[0];
+ }
+
+ switch (status) {
+ case "ok":
+ _clearStatusNode();
+ node._isLoading = false;
+ node._error = null;
+ node.renderStatus();
+ break;
+ case "loading":
+ if (!node.parent) {
+ _setStatusNode(
+ {
+ title:
+ tree.options.strings.loading +
+ (message ? " (" + message + ")" : ""),
+ // icon: true, // needed for 'loding' icon
+ checkbox: false,
+ tooltip: details,
+ },
+ status
+ );
+ }
+ node._isLoading = true;
+ node._error = null;
+ node.renderStatus();
+ break;
+ case "error":
+ _setStatusNode(
+ {
+ title:
+ tree.options.strings.loadError +
+ (message ? " (" + message + ")" : ""),
+ // icon: false,
+ checkbox: false,
+ tooltip: details,
+ },
+ status
+ );
+ node._isLoading = false;
+ node._error = { message: message, details: details };
+ node.renderStatus();
+ break;
+ case "nodata":
+ _setStatusNode(
+ {
+ title: message || tree.options.strings.noData,
+ // icon: false,
+ checkbox: false,
+ tooltip: details,
+ },
+ status
+ );
+ node._isLoading = false;
+ node._error = null;
+ node.renderStatus();
+ break;
+ default:
+ $.error("invalid node status " + status);
+ }
+ },
+ /**
+ *
+ * @param {EventData} ctx
+ */
+ nodeToggleExpanded: function (ctx) {
+ return this.nodeSetExpanded(ctx, !ctx.node.expanded);
+ },
+ /**
+ * @param {EventData} ctx
+ */
+ nodeToggleSelected: function (ctx) {
+ var node = ctx.node,
+ flag = !node.selected;
+
+ // In selectMode: 3 this node may be unselected+partsel, even if
+ // setSelected(true) was called before, due to `unselectable` children.
+ // In this case, we now toggle as `setSelected(false)`
+ if (
+ node.partsel &&
+ !node.selected &&
+ node._lastSelectIntent === true
+ ) {
+ flag = false;
+ node.selected = true; // so it is not considered 'nothing to do'
+ }
+ node._lastSelectIntent = flag;
+ return this.nodeSetSelected(ctx, flag);
+ },
+ /** Remove all nodes.
+ * @param {EventData} ctx
+ */
+ treeClear: function (ctx) {
+ var tree = ctx.tree;
+ tree.activeNode = null;
+ tree.focusNode = null;
+ tree.$div.find(">ul.fancytree-container").empty();
+ // TODO: call destructors and remove reference loops
+ tree.rootNode.children = null;
+ tree._callHook("treeStructureChanged", ctx, "clear");
+ },
+ /** Widget was created (called only once, even it re-initialized).
+ * @param {EventData} ctx
+ */
+ treeCreate: function (ctx) {},
+ /** Widget was destroyed.
+ * @param {EventData} ctx
+ */
+ treeDestroy: function (ctx) {
+ this.$div.find(">ul.fancytree-container").remove();
+ if (this.$source) {
+ this.$source.removeClass("fancytree-helper-hidden");
+ }
+ },
+ /** Widget was (re-)initialized.
+ * @param {EventData} ctx
+ */
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ opts = tree.options;
+
+ //this.debug("Fancytree.treeInit()");
+ // Add container to the TAB chain
+ // See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant
+ // #577: Allow to set tabindex to "0", "-1" and ""
+ tree.$container.attr("tabindex", opts.tabindex);
+
+ // Copy some attributes to tree.data
+ $.each(TREE_ATTRS, function (i, attr) {
+ if (opts[attr] !== undefined) {
+ tree.info("Move option " + attr + " to tree");
+ tree[attr] = opts[attr];
+ delete opts[attr];
+ }
+ });
+
+ if (opts.checkboxAutoHide) {
+ tree.$container.addClass("fancytree-checkbox-auto-hide");
+ }
+ if (opts.rtl) {
+ tree.$container
+ .attr("DIR", "RTL")
+ .addClass("fancytree-rtl");
+ } else {
+ tree.$container
+ .removeAttr("DIR")
+ .removeClass("fancytree-rtl");
+ }
+ if (opts.aria) {
+ tree.$container.attr("role", "tree");
+ if (opts.selectMode !== 1) {
+ tree.$container.attr("aria-multiselectable", true);
+ }
+ }
+ this.treeLoad(ctx);
+ },
+ /** Parse Fancytree from source, as configured in the options.
+ * @param {EventData} ctx
+ * @param {object} [source] optional new source (use last data otherwise)
+ */
+ treeLoad: function (ctx, source) {
+ var metaData,
+ type,
+ $ul,
+ tree = ctx.tree,
+ $container = ctx.widget.element,
+ dfd,
+ // calling context for root node
+ rootCtx = $.extend({}, ctx, { node: this.rootNode });
+
+ if (tree.rootNode.children) {
+ this.treeClear(ctx);
+ }
+ source = source || this.options.source;
+
+ if (!source) {
+ type = $container.data("type") || "html";
+ switch (type) {
+ case "html":
+ // There should be an embedded `<ul>` with initial nodes,
+ // but another `<ul class='fancytree-container'>` is appended
+ // to the tree's <div> on startup anyway.
+ $ul = $container
+ .find(">ul")
+ .not(".fancytree-container")
+ .first();
+
+ if ($ul.length) {
+ $ul.addClass(
+ "ui-fancytree-source fancytree-helper-hidden"
+ );
+ source = $.ui.fancytree.parseHtml($ul);
+ // allow to init tree.data.foo from <ul data-foo=''>
+ this.data = $.extend(
+ this.data,
+ _getElementDataAsDict($ul)
+ );
+ } else {
+ FT.warn(
+ "No `source` option was passed and container does not contain `<ul>`: assuming `source: []`."
+ );
+ source = [];
+ }
+ break;
+ case "json":
+ source = $.parseJSON($container.text());
+ // $container already contains the <ul>, but we remove the plain (json) text
+ // $container.empty();
+ $container
+ .contents()
+ .filter(function () {
+ return this.nodeType === 3;
+ })
+ .remove();
+ if ($.isPlainObject(source)) {
+ // We got {foo: 'abc', children: [...]}
+ _assert(
+ _isArray(source.children),
+ "if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"
+ );
+ metaData = source;
+ source = source.children;
+ delete metaData.children;
+ // Copy some attributes to tree.data
+ $.each(TREE_ATTRS, function (i, attr) {
+ if (metaData[attr] !== undefined) {
+ tree[attr] = metaData[attr];
+ delete metaData[attr];
+ }
+ });
+ // Copy extra properties to tree.data.foo
+ $.extend(tree.data, metaData);
+ }
+ break;
+ default:
+ $.error("Invalid data-type: " + type);
+ }
+ } else if (typeof source === "string") {
+ // TODO: source is an element ID
+ $.error("Not implemented");
+ }
+
+ // preInit is fired when the widget markup is created, but nodes
+ // not yet loaded
+ tree._triggerTreeEvent("preInit", null);
+
+ // Trigger fancytreeinit after nodes have been loaded
+ dfd = this.nodeLoadChildren(rootCtx, source)
+ .done(function () {
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ "loadChildren"
+ );
+ tree.render();
+ if (ctx.options.selectMode === 3) {
+ tree.rootNode.fixSelection3FromEndNodes();
+ }
+ if (tree.activeNode && tree.options.activeVisible) {
+ tree.activeNode.makeVisible();
+ }
+ tree._triggerTreeEvent("init", null, { status: true });
+ })
+ .fail(function () {
+ tree.render();
+ tree._triggerTreeEvent("init", null, { status: false });
+ });
+ return dfd;
+ },
+ /** Node was inserted into or removed from the tree.
+ * @param {EventData} ctx
+ * @param {boolean} add
+ * @param {FancytreeNode} node
+ */
+ treeRegisterNode: function (ctx, add, node) {
+ ctx.tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ add ? "addNode" : "removeNode"
+ );
+ },
+ /** Widget got focus.
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ */
+ treeSetFocus: function (ctx, flag, callOpts) {
+ var targetNode;
+
+ flag = flag !== false;
+
+ // this.debug("treeSetFocus(" + flag + "), callOpts: ", callOpts, this.hasFocus());
+ // this.debug(" focusNode: " + this.focusNode);
+ // this.debug(" activeNode: " + this.activeNode);
+ if (flag !== this.hasFocus()) {
+ this._hasFocus = flag;
+ if (!flag && this.focusNode) {
+ // Node also looses focus if widget blurs
+ this.focusNode.setFocus(false);
+ } else if (flag && (!callOpts || !callOpts.calledByNode)) {
+ $(this.$container).focus();
+ }
+ this.$container.toggleClass("fancytree-treefocus", flag);
+ this._triggerTreeEvent(flag ? "focusTree" : "blurTree");
+ if (flag && !this.activeNode) {
+ // #712: Use last mousedowned node ('click' event fires after focusin)
+ targetNode =
+ this._lastMousedownNode || this.getFirstChild();
+ if (targetNode) {
+ targetNode.setFocus();
+ }
+ }
+ }
+ },
+ /** Widget option was set using `$().fancytree("option", "KEY", VALUE)`.
+ *
+ * Note: `key` may reference a nested option, e.g. 'dnd5.scroll'.
+ * In this case `value`contains the complete, modified `dnd5` option hash.
+ * We can check for changed values like
+ * if( value.scroll !== tree.options.dnd5.scroll ) {...}
+ *
+ * @param {EventData} ctx
+ * @param {string} key option name
+ * @param {any} value option value
+ */
+ treeSetOption: function (ctx, key, value) {
+ var tree = ctx.tree,
+ callDefault = true,
+ callCreate = false,
+ callRender = false;
+
+ switch (key) {
+ case "aria":
+ case "checkbox":
+ case "icon":
+ case "minExpandLevel":
+ case "tabindex":
+ // tree._callHook("treeCreate", tree);
+ callCreate = true;
+ callRender = true;
+ break;
+ case "checkboxAutoHide":
+ tree.$container.toggleClass(
+ "fancytree-checkbox-auto-hide",
+ !!value
+ );
+ break;
+ case "escapeTitles":
+ case "tooltip":
+ callRender = true;
+ break;
+ case "rtl":
+ if (value === false) {
+ tree.$container
+ .removeAttr("DIR")
+ .removeClass("fancytree-rtl");
+ } else {
+ tree.$container
+ .attr("DIR", "RTL")
+ .addClass("fancytree-rtl");
+ }
+ callRender = true;
+ break;
+ case "source":
+ callDefault = false;
+ tree._callHook("treeLoad", tree, value);
+ callRender = true;
+ break;
+ }
+ tree.debug(
+ "set option " +
+ key +
+ "=" +
+ value +
+ " <" +
+ typeof value +
+ ">"
+ );
+ if (callDefault) {
+ if (this.widget._super) {
+ // jQuery UI 1.9+
+ this.widget._super.call(this.widget, key, value);
+ } else {
+ // jQuery UI <= 1.8, we have to manually invoke the _setOption method from the base widget
+ $.Widget.prototype._setOption.call(
+ this.widget,
+ key,
+ value
+ );
+ }
+ }
+ if (callCreate) {
+ tree._callHook("treeCreate", tree);
+ }
+ if (callRender) {
+ tree.render(true, false); // force, not-deep
+ }
+ },
+ /** A Node was added, removed, moved, or it's visibility changed.
+ * @param {EventData} ctx
+ */
+ treeStructureChanged: function (ctx, type) {},
+ }
+ );
+
+ /*******************************************************************************
+ * jQuery UI widget boilerplate
+ */
+
+ /**
+ * The plugin (derrived from [jQuery.Widget](http://api.jqueryui.com/jQuery.widget/)).
+ *
+ * **Note:**
+ * These methods implement the standard jQuery UI widget API.
+ * It is recommended to use methods of the {Fancytree} instance instead
+ *
+ * @example
+ * // DEPRECATED: Access jQuery UI widget methods and members:
+ * var tree = $("#tree").fancytree("getTree");
+ * var node = $("#tree").fancytree("getActiveNode");
+ *
+ * // RECOMMENDED: Use the Fancytree object API
+ * var tree = $.ui.fancytree.getTree("#tree");
+ * var node = tree.getActiveNode();
+ *
+ * // or you may already have stored the tree instance upon creation:
+ * import {createTree, version} from 'jquery.fancytree'
+ * const tree = createTree('#tree', { ... });
+ * var node = tree.getActiveNode();
+ *
+ * @see {Fancytree_Static#getTree}
+ * @deprecated Use methods of the {Fancytree} instance instead
+ * @mixin Fancytree_Widget
+ */
+
+ $.widget(
+ "ui.fancytree",
+ /** @lends Fancytree_Widget# */
+ {
+ /**These options will be used as defaults
+ * @type {FancytreeOptions}
+ */
+ options: {
+ activeVisible: true,
+ ajax: {
+ type: "GET",
+ cache: false, // false: Append random '_' argument to the request url to prevent caching.
+ // timeout: 0, // >0: Make sure we get an ajax error if server is unreachable
+ dataType: "json", // Expect json format and pass json object to callbacks.
+ },
+ aria: true,
+ autoActivate: true,
+ autoCollapse: false,
+ autoScroll: false,
+ checkbox: false,
+ clickFolderMode: 4,
+ copyFunctionsToData: false,
+ debugLevel: null, // 0..4 (null: use global setting $.ui.fancytree.debugLevel)
+ disabled: false, // TODO: required anymore?
+ enableAspx: 42, // TODO: this is truethy, but distinguishable from true: default will change to false in the future
+ escapeTitles: false,
+ extensions: [],
+ focusOnSelect: false,
+ generateIds: false,
+ icon: true,
+ idPrefix: "ft_",
+ keyboard: true,
+ keyPathSeparator: "/",
+ minExpandLevel: 1,
+ nodata: true, // (bool, string, or callback) display message, when no data available
+ quicksearch: false,
+ rtl: false,
+ scrollOfs: { top: 0, bottom: 0 },
+ scrollParent: null,
+ selectMode: 2,
+ strings: {
+ loading: "Loading...", // &#8230; would be escaped when escapeTitles is true
+ loadError: "Load error!",
+ moreData: "More...",
+ noData: "No data.",
+ },
+ tabindex: "0",
+ titlesTabbable: false,
+ toggleEffect: { effect: "slideToggle", duration: 200 }, //< "toggle" or "slideToggle" to use jQuery instead of jQueryUI for toggleEffect animation
+ tooltip: false,
+ treeId: null,
+ _classNames: {
+ active: "fancytree-active",
+ animating: "fancytree-animating",
+ combinedExpanderPrefix: "fancytree-exp-",
+ combinedIconPrefix: "fancytree-ico-",
+ error: "fancytree-error",
+ expanded: "fancytree-expanded",
+ focused: "fancytree-focused",
+ folder: "fancytree-folder",
+ hasChildren: "fancytree-has-children",
+ lastsib: "fancytree-lastsib",
+ lazy: "fancytree-lazy",
+ loading: "fancytree-loading",
+ node: "fancytree-node",
+ partload: "fancytree-partload",
+ partsel: "fancytree-partsel",
+ radio: "fancytree-radio",
+ selected: "fancytree-selected",
+ statusNodePrefix: "fancytree-statusnode-",
+ unselectable: "fancytree-unselectable",
+ },
+ // events
+ lazyLoad: null,
+ postProcess: null,
+ },
+ _deprecationWarning: function (name) {
+ var tree = this.tree;
+
+ if (tree && tree.options.debugLevel >= 3) {
+ tree.warn(
+ "$().fancytree('" +
+ name +
+ "') is deprecated (see https://wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Widget.html"
+ );
+ }
+ },
+ /* Set up the widget, Called on first $().fancytree() */
+ _create: function () {
+ this.tree = new Fancytree(this);
+
+ this.$source =
+ this.source || this.element.data("type") === "json"
+ ? this.element
+ : this.element.find(">ul").first();
+ // Subclass Fancytree instance with all enabled extensions
+ var extension,
+ extName,
+ i,
+ opts = this.options,
+ extensions = opts.extensions,
+ base = this.tree;
+
+ for (i = 0; i < extensions.length; i++) {
+ extName = extensions[i];
+ extension = $.ui.fancytree._extensions[extName];
+ if (!extension) {
+ $.error(
+ "Could not apply extension '" +
+ extName +
+ "' (it is not registered, did you forget to include it?)"
+ );
+ }
+ // Add extension options as tree.options.EXTENSION
+ // _assert(!this.tree.options[extName], "Extension name must not exist as option name: " + extName);
+
+ // console.info("extend " + extName, extension.options, this.tree.options[extName])
+ // issue #876: we want to replace custom array-options, not merge them
+ this.tree.options[extName] = _simpleDeepMerge(
+ {},
+ extension.options,
+ this.tree.options[extName]
+ );
+ // this.tree.options[extName] = $.extend(true, {}, extension.options, this.tree.options[extName]);
+
+ // console.info("extend " + extName + " =>", this.tree.options[extName])
+ // console.info("extend " + extName + " org default =>", extension.options)
+
+ // Add a namespace tree.ext.EXTENSION, to hold instance data
+ _assert(
+ this.tree.ext[extName] === undefined,
+ "Extension name must not exist as Fancytree.ext attribute: '" +
+ extName +
+ "'"
+ );
+ // this.tree[extName] = extension;
+ this.tree.ext[extName] = {};
+ // Subclass Fancytree methods using proxies.
+ _subclassObject(this.tree, base, extension, extName);
+ // current extension becomes base for the next extension
+ base = extension;
+ }
+ //
+ if (opts.icons !== undefined) {
+ // 2015-11-16
+ if (opts.icon === true) {
+ this.tree.warn(
+ "'icons' tree option is deprecated since v2.14.0: use 'icon' instead"
+ );
+ opts.icon = opts.icons;
+ } else {
+ $.error(
+ "'icons' tree option is deprecated since v2.14.0: use 'icon' only instead"
+ );
+ }
+ }
+ if (opts.iconClass !== undefined) {
+ // 2015-11-16
+ if (opts.icon) {
+ $.error(
+ "'iconClass' tree option is deprecated since v2.14.0: use 'icon' only instead"
+ );
+ } else {
+ this.tree.warn(
+ "'iconClass' tree option is deprecated since v2.14.0: use 'icon' instead"
+ );
+ opts.icon = opts.iconClass;
+ }
+ }
+ if (opts.tabbable !== undefined) {
+ // 2016-04-04
+ opts.tabindex = opts.tabbable ? "0" : "-1";
+ this.tree.warn(
+ "'tabbable' tree option is deprecated since v2.17.0: use 'tabindex='" +
+ opts.tabindex +
+ "' instead"
+ );
+ }
+ //
+ this.tree._callHook("treeCreate", this.tree);
+ // Note: 'fancytreecreate' event is fired by widget base class
+ // this.tree._triggerTreeEvent("create");
+ },
+
+ /* Called on every $().fancytree() */
+ _init: function () {
+ this.tree._callHook("treeInit", this.tree);
+ // TODO: currently we call bind after treeInit, because treeInit
+ // might change tree.$container.
+ // It would be better, to move event binding into hooks altogether
+ this._bind();
+ },
+
+ /* Use the _setOption method to respond to changes to options. */
+ _setOption: function (key, value) {
+ return this.tree._callHook(
+ "treeSetOption",
+ this.tree,
+ key,
+ value
+ );
+ },
+
+ /** Use the destroy method to clean up any modifications your widget has made to the DOM */
+ _destroy: function () {
+ this._unbind();
+ this.tree._callHook("treeDestroy", this.tree);
+ // In jQuery UI 1.8, you must invoke the destroy method from the base widget
+ // $.Widget.prototype.destroy.call(this);
+ // TODO: delete tree and nodes to make garbage collect easier?
+ // TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method
+ },
+
+ // -------------------------------------------------------------------------
+
+ /* Remove all event handlers for our namespace */
+ _unbind: function () {
+ var ns = this.tree._ns;
+ this.element.off(ns);
+ this.tree.$container.off(ns);
+ $(document).off(ns);
+ },
+ /* Add mouse and kyboard handlers to the container */
+ _bind: function () {
+ var self = this,
+ opts = this.options,
+ tree = this.tree,
+ ns = tree._ns;
+ // selstartEvent = ( $.support.selectstart ? "selectstart" : "mousedown" )
+
+ // Remove all previuous handlers for this tree
+ this._unbind();
+
+ //alert("keydown" + ns + "foc=" + tree.hasFocus() + tree.$container);
+ // tree.debug("bind events; container: ", tree.$container);
+ tree.$container
+ .on("focusin" + ns + " focusout" + ns, function (event) {
+ var node = FT.getNode(event),
+ flag = event.type === "focusin";
+
+ if (!flag && node && $(event.target).is("a")) {
+ // #764
+ node.debug(
+ "Ignored focusout on embedded <a> element."
+ );
+ return;
+ }
+ // tree.treeOnFocusInOut.call(tree, event);
+ // tree.debug("Tree container got event " + event.type, node, event, FT.getEventTarget(event));
+ if (flag) {
+ if (tree._getExpiringValue("focusin")) {
+ // #789: IE 11 may send duplicate focusin events
+ tree.debug("Ignored double focusin.");
+ return;
+ }
+ tree._setExpiringValue("focusin", true, 50);
+
+ if (!node) {
+ // #789: IE 11 may send focusin before mousdown(?)
+ node = tree._getExpiringValue("mouseDownNode");
+ if (node) {
+ tree.debug(
+ "Reconstruct mouse target for focusin from recent event."
+ );
+ }
+ }
+ }
+ if (node) {
+ // For example clicking into an <input> that is part of a node
+ tree._callHook(
+ "nodeSetFocus",
+ tree._makeHookContext(node, event),
+ flag
+ );
+ } else {
+ if (
+ tree.tbody &&
+ $(event.target).parents(
+ "table.fancytree-container > thead"
+ ).length
+ ) {
+ // #767: ignore events in the table's header
+ tree.debug(
+ "Ignore focus event outside table body.",
+ event
+ );
+ } else {
+ tree._callHook("treeSetFocus", tree, flag);
+ }
+ }
+ })
+ .on(
+ "selectstart" + ns,
+ "span.fancytree-title",
+ function (event) {
+ // prevent mouse-drags to select text ranges
+ // tree.debug("<span title> got event " + event.type);
+ event.preventDefault();
+ }
+ )
+ .on("keydown" + ns, function (event) {
+ // TODO: also bind keyup and keypress
+ // tree.debug("got event " + event.type + ", hasFocus:" + tree.hasFocus());
+ // if(opts.disabled || opts.keyboard === false || !tree.hasFocus() ){
+ if (opts.disabled || opts.keyboard === false) {
+ return true;
+ }
+ var res,
+ node = tree.focusNode, // node may be null
+ ctx = tree._makeHookContext(node || tree, event),
+ prevPhase = tree.phase;
+
+ try {
+ tree.phase = "userEvent";
+ // If a 'fancytreekeydown' handler returns false, skip the default
+ // handling (implemented by tree.nodeKeydown()).
+ if (node) {
+ res = tree._triggerNodeEvent(
+ "keydown",
+ node,
+ event
+ );
+ } else {
+ res = tree._triggerTreeEvent("keydown", event);
+ }
+ if (res === "preventNav") {
+ res = true; // prevent keyboard navigation, but don't prevent default handling of embedded input controls
+ } else if (res !== false) {
+ res = tree._callHook("nodeKeydown", ctx);
+ }
+ return res;
+ } finally {
+ tree.phase = prevPhase;
+ }
+ })
+ .on("mousedown" + ns, function (event) {
+ var et = FT.getEventTarget(event);
+ // self.tree.debug("event(" + event.type + "): node: ", et.node);
+ // #712: Store the clicked node, so we can use it when we get a focusin event
+ // ('click' event fires after focusin)
+ // tree.debug("event(" + event.type + "): node: ", et.node);
+ tree._lastMousedownNode = et ? et.node : null;
+ // #789: Store the node also for a short period, so we can use it
+ // in a *resulting* focusin event
+ tree._setExpiringValue(
+ "mouseDownNode",
+ tree._lastMousedownNode
+ );
+ })
+ .on("click" + ns + " dblclick" + ns, function (event) {
+ if (opts.disabled) {
+ return true;
+ }
+ var ctx,
+ et = FT.getEventTarget(event),
+ node = et.node,
+ tree = self.tree,
+ prevPhase = tree.phase;
+
+ // self.tree.debug("event(" + event.type + "): node: ", node);
+ if (!node) {
+ return true; // Allow bubbling of other events
+ }
+ ctx = tree._makeHookContext(node, event);
+ // self.tree.debug("event(" + event.type + "): node: ", node);
+ try {
+ tree.phase = "userEvent";
+ switch (event.type) {
+ case "click":
+ ctx.targetType = et.type;
+ if (node.isPagingNode()) {
+ return (
+ tree._triggerNodeEvent(
+ "clickPaging",
+ ctx,
+ event
+ ) === true
+ );
+ }
+ return tree._triggerNodeEvent(
+ "click",
+ ctx,
+ event
+ ) === false
+ ? false
+ : tree._callHook("nodeClick", ctx);
+ case "dblclick":
+ ctx.targetType = et.type;
+ return tree._triggerNodeEvent(
+ "dblclick",
+ ctx,
+ event
+ ) === false
+ ? false
+ : tree._callHook("nodeDblclick", ctx);
+ }
+ } finally {
+ tree.phase = prevPhase;
+ }
+ });
+ },
+ /** Return the active node or null.
+ * @returns {FancytreeNode}
+ * @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getActiveNode: function () {
+ this._deprecationWarning("getActiveNode");
+ return this.tree.activeNode;
+ },
+ /** Return the matching node or null.
+ * @param {string} key
+ * @returns {FancytreeNode}
+ * @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getNodeByKey: function (key) {
+ this._deprecationWarning("getNodeByKey");
+ return this.tree.getNodeByKey(key);
+ },
+ /** Return the invisible system root node.
+ * @returns {FancytreeNode}
+ * @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getRootNode: function () {
+ this._deprecationWarning("getRootNode");
+ return this.tree.rootNode;
+ },
+ /** Return the current tree instance.
+ * @returns {Fancytree}
+ * @deprecated Use `$.ui.fancytree.getTree()` instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getTree: function () {
+ this._deprecationWarning("getTree");
+ return this.tree;
+ },
+ }
+ );
+
+ // $.ui.fancytree was created by the widget factory. Create a local shortcut:
+ FT = $.ui.fancytree;
+
+ /**
+ * Static members in the `$.ui.fancytree` namespace.
+ * This properties and methods can be accessed without instantiating a concrete
+ * Fancytree instance.
+ *
+ * @example
+ * // Access static members:
+ * var node = $.ui.fancytree.getNode(element);
+ * alert($.ui.fancytree.version);
+ *
+ * @mixin Fancytree_Static
+ */
+ $.extend(
+ $.ui.fancytree,
+ /** @lends Fancytree_Static# */
+ {
+ /** Version number `"MAJOR.MINOR.PATCH"`
+ * @type {string} */
+ version: "2.38.3", // Set to semver by 'grunt release'
+ /** @type {string}
+ * @description `"production" for release builds` */
+ buildType: "production", // Set to 'production' by 'grunt build'
+ /** @type {int}
+ * @description 0: silent .. 5: verbose (default: 3 for release builds). */
+ debugLevel: 3, // Set to 3 by 'grunt build'
+ // Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel
+
+ _nextId: 1,
+ _nextNodeKey: 1,
+ _extensions: {},
+ // focusTree: null,
+
+ /** Expose class object as `$.ui.fancytree._FancytreeClass`.
+ * Useful to extend `$.ui.fancytree._FancytreeClass.prototype`.
+ * @type {Fancytree}
+ */
+ _FancytreeClass: Fancytree,
+ /** Expose class object as $.ui.fancytree._FancytreeNodeClass
+ * Useful to extend `$.ui.fancytree._FancytreeNodeClass.prototype`.
+ * @type {FancytreeNode}
+ */
+ _FancytreeNodeClass: FancytreeNode,
+ /* Feature checks to provide backwards compatibility */
+ jquerySupports: {
+ // http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+ positionMyOfs: isVersionAtLeast($.ui.version, 1, 9),
+ },
+ /** Throw an error if condition fails (debug method).
+ * @param {boolean} cond
+ * @param {string} msg
+ */
+ assert: function (cond, msg) {
+ return _assert(cond, msg);
+ },
+ /** Create a new Fancytree instance on a target element.
+ *
+ * @param {Element | jQueryObject | string} el Target DOM element or selector
+ * @param {FancytreeOptions} [opts] Fancytree options
+ * @returns {Fancytree} new tree instance
+ * @example
+ * var tree = $.ui.fancytree.createTree("#tree", {
+ * source: {url: "my/webservice"}
+ * }); // Create tree for this matching element
+ *
+ * @since 2.25
+ */
+ createTree: function (el, opts) {
+ var $tree = $(el).fancytree(opts);
+ return FT.getTree($tree);
+ },
+ /** Return a function that executes *fn* at most every *timeout* ms.
+ * @param {integer} timeout
+ * @param {function} fn
+ * @param {boolean} [invokeAsap=false]
+ * @param {any} [ctx]
+ */
+ debounce: function (timeout, fn, invokeAsap, ctx) {
+ var timer;
+ if (arguments.length === 3 && typeof invokeAsap !== "boolean") {
+ ctx = invokeAsap;
+ invokeAsap = false;
+ }
+ return function () {
+ var args = arguments;
+ ctx = ctx || this;
+ // eslint-disable-next-line no-unused-expressions
+ invokeAsap && !timer && fn.apply(ctx, args);
+ clearTimeout(timer);
+ timer = setTimeout(function () {
+ // eslint-disable-next-line no-unused-expressions
+ invokeAsap || fn.apply(ctx, args);
+ timer = null;
+ }, timeout);
+ };
+ },
+ /** Write message to console if debugLevel >= 4
+ * @param {string} msg
+ */
+ debug: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 4) {
+ consoleApply("log", arguments);
+ }
+ },
+ /** Write error message to console if debugLevel >= 1.
+ * @param {string} msg
+ */
+ error: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 1) {
+ consoleApply("error", arguments);
+ }
+ },
+ /** Convert `<`, `>`, `&`, `"`, `'`, and `/` to the equivalent entities.
+ *
+ * @param {string} s
+ * @returns {string}
+ */
+ escapeHtml: function (s) {
+ return ("" + s).replace(REX_HTML, function (s) {
+ return ENTITY_MAP[s];
+ });
+ },
+ /** Make jQuery.position() arguments backwards compatible, i.e. if
+ * jQuery UI version <= 1.8, convert
+ * { my: "left+3 center", at: "left bottom", of: $target }
+ * to
+ * { my: "left center", at: "left bottom", of: $target, offset: "3 0" }
+ *
+ * See http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+ * and http://jsfiddle.net/mar10/6xtu9a4e/
+ *
+ * @param {object} opts
+ * @returns {object} the (potentially modified) original opts hash object
+ */
+ fixPositionOptions: function (opts) {
+ if (opts.offset || ("" + opts.my + opts.at).indexOf("%") >= 0) {
+ $.error(
+ "expected new position syntax (but '%' is not supported)"
+ );
+ }
+ if (!$.ui.fancytree.jquerySupports.positionMyOfs) {
+ var // parse 'left+3 center' into ['left+3 center', 'left', '+3', 'center', undefined]
+ myParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(
+ opts.my
+ ),
+ atParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(
+ opts.at
+ ),
+ // convert to numbers
+ dx =
+ (myParts[2] ? +myParts[2] : 0) +
+ (atParts[2] ? +atParts[2] : 0),
+ dy =
+ (myParts[4] ? +myParts[4] : 0) +
+ (atParts[4] ? +atParts[4] : 0);
+
+ opts = $.extend({}, opts, {
+ // make a copy and overwrite
+ my: myParts[1] + " " + myParts[3],
+ at: atParts[1] + " " + atParts[3],
+ });
+ if (dx || dy) {
+ opts.offset = "" + dx + " " + dy;
+ }
+ }
+ return opts;
+ },
+ /** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.
+ *
+ * @param {Event} event Mouse event, e.g. click, ...
+ * @returns {object} Return a {node: FancytreeNode, type: TYPE} object
+ * TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+ */
+ getEventTarget: function (event) {
+ var $target,
+ tree,
+ tcn = event && event.target ? event.target.className : "",
+ res = { node: this.getNode(event.target), type: undefined };
+ // We use a fast version of $(res.node).hasClass()
+ // See http://jsperf.com/test-for-classname/2
+ if (/\bfancytree-title\b/.test(tcn)) {
+ res.type = "title";
+ } else if (/\bfancytree-expander\b/.test(tcn)) {
+ res.type =
+ res.node.hasChildren() === false
+ ? "prefix"
+ : "expander";
+ // }else if( /\bfancytree-checkbox\b/.test(tcn) || /\bfancytree-radio\b/.test(tcn) ){
+ } else if (/\bfancytree-checkbox\b/.test(tcn)) {
+ res.type = "checkbox";
+ } else if (/\bfancytree(-custom)?-icon\b/.test(tcn)) {
+ res.type = "icon";
+ } else if (/\bfancytree-node\b/.test(tcn)) {
+ // Somewhere near the title
+ res.type = "title";
+ } else if (event && event.target) {
+ $target = $(event.target);
+ if ($target.is("ul[role=group]")) {
+ // #nnn: Clicking right to a node may hit the surrounding UL
+ tree = res.node && res.node.tree;
+ (tree || FT).debug("Ignoring click on outer UL.");
+ res.node = null;
+ } else if ($target.closest(".fancytree-title").length) {
+ // #228: clicking an embedded element inside a title
+ res.type = "title";
+ } else if ($target.closest(".fancytree-checkbox").length) {
+ // E.g. <svg> inside checkbox span
+ res.type = "checkbox";
+ } else if ($target.closest(".fancytree-expander").length) {
+ res.type = "expander";
+ }
+ }
+ return res;
+ },
+ /** Return a string describing the affected node region for a mouse event.
+ *
+ * @param {Event} event Mouse event, e.g. click, mousemove, ...
+ * @returns {string} 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+ */
+ getEventTargetType: function (event) {
+ return this.getEventTarget(event).type;
+ },
+ /** Return a FancytreeNode instance from element, event, or jQuery object.
+ *
+ * @param {Element | jQueryObject | Event} el
+ * @returns {FancytreeNode} matching node or null
+ */
+ getNode: function (el) {
+ if (el instanceof FancytreeNode) {
+ return el; // el already was a FancytreeNode
+ } else if (el instanceof $) {
+ el = el[0]; // el was a jQuery object: use the DOM element
+ } else if (el.originalEvent !== undefined) {
+ el = el.target; // el was an Event
+ }
+ while (el) {
+ if (el.ftnode) {
+ return el.ftnode;
+ }
+ el = el.parentNode;
+ }
+ return null;
+ },
+ /** Return a Fancytree instance, from element, index, event, or jQueryObject.
+ *
+ * @param {Element | jQueryObject | Event | integer | string} [el]
+ * @returns {Fancytree} matching tree or null
+ * @example
+ * $.ui.fancytree.getTree(); // Get first Fancytree instance on page
+ * $.ui.fancytree.getTree(1); // Get second Fancytree instance on page
+ * $.ui.fancytree.getTree(event); // Get tree for this mouse- or keyboard event
+ * $.ui.fancytree.getTree("foo"); // Get tree for this `opts.treeId`
+ * $.ui.fancytree.getTree("#tree"); // Get tree for this matching element
+ *
+ * @since 2.13
+ */
+ getTree: function (el) {
+ var widget,
+ orgEl = el;
+
+ if (el instanceof Fancytree) {
+ return el; // el already was a Fancytree
+ }
+ if (el === undefined) {
+ el = 0; // get first tree
+ }
+ if (typeof el === "number") {
+ el = $(".fancytree-container").eq(el); // el was an integer: return nth instance
+ } else if (typeof el === "string") {
+ // `el` may be a treeId or a selector:
+ el = $("#ft-id-" + orgEl).eq(0);
+ if (!el.length) {
+ el = $(orgEl).eq(0); // el was a selector: use first match
+ }
+ } else if (
+ el instanceof Element ||
+ el instanceof HTMLDocument
+ ) {
+ el = $(el);
+ } else if (el instanceof $) {
+ el = el.eq(0); // el was a jQuery object: use the first
+ } else if (el.originalEvent !== undefined) {
+ el = $(el.target); // el was an Event
+ }
+ // el is a jQuery object wit one element here
+ el = el.closest(":ui-fancytree");
+ widget = el.data("ui-fancytree") || el.data("fancytree"); // the latter is required by jQuery <= 1.8
+ return widget ? widget.tree : null;
+ },
+ /** Return an option value that has a default, but may be overridden by a
+ * callback or a node instance attribute.
+ *
+ * Evaluation sequence:
+ *
+ * If `tree.options.<optionName>` is a callback that returns something, use that.
+ * Else if `node.<optionName>` is defined, use that.
+ * Else if `tree.options.<optionName>` is a value, use that.
+ * Else use `defaultValue`.
+ *
+ * @param {string} optionName name of the option property (on node and tree)
+ * @param {FancytreeNode} node passed to the callback
+ * @param {object} nodeObject where to look for the local option property, e.g. `node` or `node.data`
+ * @param {object} treeOption where to look for the tree option, e.g. `tree.options` or `tree.options.dnd5`
+ * @param {any} [defaultValue]
+ * @returns {any}
+ *
+ * @example
+ * // Check for node.foo, tree,options.foo(), and tree.options.foo:
+ * $.ui.fancytree.evalOption("foo", node, node, tree.options);
+ * // Check for node.data.bar, tree,options.qux.bar(), and tree.options.qux.bar:
+ * $.ui.fancytree.evalOption("bar", node, node.data, tree.options.qux);
+ *
+ * @since 2.22
+ */
+ evalOption: function (
+ optionName,
+ node,
+ nodeObject,
+ treeOptions,
+ defaultValue
+ ) {
+ var ctx,
+ res,
+ tree = node.tree,
+ treeOpt = treeOptions[optionName],
+ nodeOpt = nodeObject[optionName];
+
+ if (_isFunction(treeOpt)) {
+ ctx = {
+ node: node,
+ tree: tree,
+ widget: tree.widget,
+ options: tree.widget.options,
+ typeInfo: tree.types[node.type] || {},
+ };
+ res = treeOpt.call(tree, { type: optionName }, ctx);
+ if (res == null) {
+ res = nodeOpt;
+ }
+ } else {
+ res = nodeOpt == null ? treeOpt : nodeOpt;
+ }
+ if (res == null) {
+ res = defaultValue; // no option set at all: return default
+ }
+ return res;
+ },
+ /** Set expander, checkbox, or node icon, supporting string and object format.
+ *
+ * @param {Element | jQueryObject} span
+ * @param {string} baseClass
+ * @param {string | object} icon
+ * @since 2.27
+ */
+ setSpanIcon: function (span, baseClass, icon) {
+ var $span = $(span);
+
+ if (typeof icon === "string") {
+ $span.attr("class", baseClass + " " + icon);
+ } else {
+ // support object syntax: { text: ligature, addClasse: classname }
+ if (icon.text) {
+ $span.text("" + icon.text);
+ } else if (icon.html) {
+ span.innerHTML = icon.html;
+ }
+ $span.attr(
+ "class",
+ baseClass + " " + (icon.addClass || "")
+ );
+ }
+ },
+ /** Convert a keydown or mouse event to a canonical string like 'ctrl+a',
+ * 'ctrl+shift+f2', 'shift+leftdblclick'.
+ *
+ * This is especially handy for switch-statements in event handlers.
+ *
+ * @param {event}
+ * @returns {string}
+ *
+ * @example
+
+ switch( $.ui.fancytree.eventToString(event) ) {
+ case "-":
+ tree.nodeSetExpanded(ctx, false);
+ break;
+ case "shift+return":
+ tree.nodeSetActive(ctx, true);
+ break;
+ case "down":
+ res = node.navigate(event.which, activate);
+ break;
+ default:
+ handled = false;
+ }
+ if( handled ){
+ event.preventDefault();
+ }
+ */
+ eventToString: function (event) {
+ // Poor-man's hotkeys. See here for a complete implementation:
+ // https://github.com/jeresig/jquery.hotkeys
+ var which = event.which,
+ et = event.type,
+ s = [];
+
+ if (event.altKey) {
+ s.push("alt");
+ }
+ if (event.ctrlKey) {
+ s.push("ctrl");
+ }
+ if (event.metaKey) {
+ s.push("meta");
+ }
+ if (event.shiftKey) {
+ s.push("shift");
+ }
+
+ if (et === "click" || et === "dblclick") {
+ s.push(MOUSE_BUTTONS[event.button] + et);
+ } else if (et === "wheel") {
+ s.push(et);
+ } else if (!IGNORE_KEYCODES[which]) {
+ s.push(
+ SPECIAL_KEYCODES[which] ||
+ String.fromCharCode(which).toLowerCase()
+ );
+ }
+ return s.join("+");
+ },
+ /** Write message to console if debugLevel >= 3
+ * @param {string} msg
+ */
+ info: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 3) {
+ consoleApply("info", arguments);
+ }
+ },
+ /* @deprecated: use eventToString(event) instead.
+ */
+ keyEventToString: function (event) {
+ this.warn(
+ "keyEventToString() is deprecated: use eventToString()"
+ );
+ return this.eventToString(event);
+ },
+ /** Return a wrapped handler method, that provides `this._super`.
+ *
+ * @example
+ // Implement `opts.createNode` event to add the 'draggable' attribute
+ $.ui.fancytree.overrideMethod(ctx.options, "createNode", function(event, data) {
+ // Default processing if any
+ this._super.apply(this, arguments);
+ // Add 'draggable' attribute
+ data.node.span.draggable = true;
+ });
+ *
+ * @param {object} instance
+ * @param {string} methodName
+ * @param {function} handler
+ * @param {object} [context] optional context
+ */
+ overrideMethod: function (instance, methodName, handler, context) {
+ var prevSuper,
+ _super = instance[methodName] || $.noop;
+
+ instance[methodName] = function () {
+ var self = context || this;
+
+ try {
+ prevSuper = self._super;
+ self._super = _super;
+ return handler.apply(self, arguments);
+ } finally {
+ self._super = prevSuper;
+ }
+ };
+ },
+ /**
+ * Parse tree data from HTML <ul> markup
+ *
+ * @param {jQueryObject} $ul
+ * @returns {NodeData[]}
+ */
+ parseHtml: function ($ul) {
+ var classes,
+ className,
+ extraClasses,
+ i,
+ iPos,
+ l,
+ tmp,
+ tmp2,
+ $children = $ul.find(">li"),
+ children = [];
+
+ $children.each(function () {
+ var allData,
+ lowerCaseAttr,
+ $li = $(this),
+ $liSpan = $li.find(">span", this).first(),
+ $liA = $liSpan.length ? null : $li.find(">a").first(),
+ d = { tooltip: null, data: {} };
+
+ if ($liSpan.length) {
+ d.title = $liSpan.html();
+ } else if ($liA && $liA.length) {
+ // If a <li><a> tag is specified, use it literally and extract href/target.
+ d.title = $liA.html();
+ d.data.href = $liA.attr("href");
+ d.data.target = $liA.attr("target");
+ d.tooltip = $liA.attr("title");
+ } else {
+ // If only a <li> tag is specified, use the trimmed string up to
+ // the next child <ul> tag.
+ d.title = $li.html();
+ iPos = d.title.search(/<ul/i);
+ if (iPos >= 0) {
+ d.title = d.title.substring(0, iPos);
+ }
+ }
+ d.title = _trim(d.title);
+
+ // Make sure all fields exist
+ for (i = 0, l = CLASS_ATTRS.length; i < l; i++) {
+ d[CLASS_ATTRS[i]] = undefined;
+ }
+ // Initialize to `true`, if class is set and collect extraClasses
+ classes = this.className.split(" ");
+ extraClasses = [];
+ for (i = 0, l = classes.length; i < l; i++) {
+ className = classes[i];
+ if (CLASS_ATTR_MAP[className]) {
+ d[className] = true;
+ } else {
+ extraClasses.push(className);
+ }
+ }
+ d.extraClasses = extraClasses.join(" ");
+
+ // Parse node options from ID, title and class attributes
+ tmp = $li.attr("title");
+ if (tmp) {
+ d.tooltip = tmp; // overrides <a title='...'>
+ }
+ tmp = $li.attr("id");
+ if (tmp) {
+ d.key = tmp;
+ }
+ // Translate hideCheckbox -> checkbox:false
+ if ($li.attr("hideCheckbox")) {
+ d.checkbox = false;
+ }
+ // Add <li data-NAME='...'> as node.data.NAME
+ allData = _getElementDataAsDict($li);
+ if (allData && !$.isEmptyObject(allData)) {
+ // #507: convert data-hidecheckbox (lower case) to hideCheckbox
+ for (lowerCaseAttr in NODE_ATTR_LOWERCASE_MAP) {
+ if (_hasProp(allData, lowerCaseAttr)) {
+ allData[
+ NODE_ATTR_LOWERCASE_MAP[lowerCaseAttr]
+ ] = allData[lowerCaseAttr];
+ delete allData[lowerCaseAttr];
+ }
+ }
+ // #56: Allow to set special node.attributes from data-...
+ for (i = 0, l = NODE_ATTRS.length; i < l; i++) {
+ tmp = NODE_ATTRS[i];
+ tmp2 = allData[tmp];
+ if (tmp2 != null) {
+ delete allData[tmp];
+ d[tmp] = tmp2;
+ }
+ }
+ // All other data-... goes to node.data...
+ $.extend(d.data, allData);
+ }
+ // Recursive reading of child nodes, if LI tag contains an UL tag
+ $ul = $li.find(">ul").first();
+ if ($ul.length) {
+ d.children = $.ui.fancytree.parseHtml($ul);
+ } else {
+ d.children = d.lazy ? undefined : null;
+ }
+ children.push(d);
+ // FT.debug("parse ", d, children);
+ });
+ return children;
+ },
+ /** Add Fancytree extension definition to the list of globally available extensions.
+ *
+ * @param {object} definition
+ */
+ registerExtension: function (definition) {
+ _assert(
+ definition.name != null,
+ "extensions must have a `name` property."
+ );
+ _assert(
+ definition.version != null,
+ "extensions must have a `version` property."
+ );
+ $.ui.fancytree._extensions[definition.name] = definition;
+ },
+ /** Replacement for the deprecated `jQuery.trim()`.
+ *
+ * @param {string} text
+ */
+ trim: _trim,
+ /** Inverse of escapeHtml().
+ *
+ * @param {string} s
+ * @returns {string}
+ */
+ unescapeHtml: function (s) {
+ var e = document.createElement("div");
+ e.innerHTML = s;
+ return e.childNodes.length === 0
+ ? ""
+ : e.childNodes[0].nodeValue;
+ },
+ /** Write warning message to console if debugLevel >= 2.
+ * @param {string} msg
+ */
+ warn: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 2) {
+ consoleApply("warn", arguments);
+ }
+ },
+ }
+ );
+
+ // Value returned by `require('jquery.fancytree')`
+ return $.ui.fancytree;
+}); // End of closure
+
+// Extending Fancytree
+// ===================
+//
+// See also the [live demo](https://wwWendt.de/tech/fancytree/demo/sample-ext-childcounter.html) of this code.
+//
+// Every extension should have a comment header containing some information
+// about the author, copyright and licensing. Also a pointer to the latest
+// source code.
+// Prefix with `/*!` so the comment is not removed by the minifier.
+
+/*!
+ * jquery.fancytree.childcounter.js
+ *
+ * Add a child counter bubble to tree nodes.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+// To keep the global namespace clean, we wrap everything in a closure.
+// The UMD wrapper pattern defines the dependencies on jQuery and the
+// Fancytree core module, and makes sure that we can use the `require()`
+// syntax with package loaders.
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ // Consider to use [strict mode](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
+ "use strict";
+
+ // The [coding guidelines](http://contribute.jquery.org/style-guide/js/)
+ // require jshint /eslint compliance.
+ // But for this sample, we want to allow unused variables for demonstration purpose.
+
+ /*eslint-disable no-unused-vars */
+
+ // Adding methods
+ // --------------
+
+ // New member functions can be added to the `Fancytree` class.
+ // This function will be available for every tree instance:
+ //
+ // var tree = $.ui.fancytree.getTree("#tree");
+ // tree.countSelected(false);
+
+ $.ui.fancytree._FancytreeClass.prototype.countSelected = function (
+ topOnly
+ ) {
+ var tree = this,
+ treeOptions = tree.options;
+
+ return tree.getSelectedNodes(topOnly).length;
+ };
+
+ // The `FancytreeNode` class can also be easily extended. This would be called
+ // like
+ // node.updateCounters();
+ //
+ // It is also good practice to add a docstring comment.
+ /**
+ * [ext-childcounter] Update counter badges for `node` and its parents.
+ * May be called in the `loadChildren` event, to update parents of lazy loaded
+ * nodes.
+ * @alias FancytreeNode#updateCounters
+ * @requires jquery.fancytree.childcounters.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.updateCounters = function () {
+ var node = this,
+ $badge = $("span.fancytree-childcounter", node.span),
+ extOpts = node.tree.options.childcounter,
+ count = node.countChildren(extOpts.deep);
+
+ node.data.childCounter = count;
+ if (
+ (count || !extOpts.hideZeros) &&
+ (!node.isExpanded() || !extOpts.hideExpanded)
+ ) {
+ if (!$badge.length) {
+ $badge = $("<span class='fancytree-childcounter'/>").appendTo(
+ $(
+ "span.fancytree-icon,span.fancytree-custom-icon",
+ node.span
+ )
+ );
+ }
+ $badge.text(count);
+ } else {
+ $badge.remove();
+ }
+ if (extOpts.deep && !node.isTopLevel() && !node.isRootNode()) {
+ node.parent.updateCounters();
+ }
+ };
+
+ // Finally, we can extend the widget API and create functions that are called
+ // like so:
+ //
+ // $("#tree").fancytree("widgetMethod1", "abc");
+
+ $.ui.fancytree.prototype.widgetMethod1 = function (arg1) {
+ var tree = this.tree;
+ return arg1;
+ };
+
+ // Register a Fancytree extension
+ // ------------------------------
+ // A full blown extension, extension is available for all trees and can be
+ // enabled like so (see also the [live demo](https://wwWendt.de/tech/fancytree/demo/sample-ext-childcounter.html)):
+ //
+ // <script src="../src/jquery.fancytree.js"></script>
+ // <script src="../src/jquery.fancytree.childcounter.js"></script>
+ // ...
+ //
+ // $("#tree").fancytree({
+ // extensions: ["childcounter"],
+ // childcounter: {
+ // hideExpanded: true
+ // },
+ // ...
+ // });
+ //
+
+ /* 'childcounter' extension */
+ $.ui.fancytree.registerExtension({
+ // Every extension must be registered by a unique name.
+ name: "childcounter",
+ // Version information should be compliant with [semver](http://semver.org)
+ version: "2.38.3",
+
+ // Extension specific options and their defaults.
+ // This options will be available as `tree.options.childcounter.hideExpanded`
+
+ options: {
+ deep: true,
+ hideZeros: true,
+ hideExpanded: false,
+ },
+
+ // Attributes other than `options` (or functions) can be defined here, and
+ // will be added to the tree.ext.EXTNAME namespace, in this case `tree.ext.childcounter.foo`.
+ // They can also be accessed as `this._local.foo` from within the extension
+ // methods.
+ foo: 42,
+
+ // Local functions are prefixed with an underscore '_'.
+ // Callable as `this._local._appendCounter()`.
+
+ _appendCounter: function (bar) {
+ var tree = this;
+ },
+
+ // **Override virtual methods for this extension.**
+ //
+ // Fancytree implements a number of 'hook methods', prefixed by 'node...' or 'tree...'.
+ // with a `ctx` argument (see [EventData](https://wwWendt.de/tech/fancytree/doc/jsdoc/global.html#EventData)
+ // for details) and an extended calling context:<br>
+ // `this` : the Fancytree instance<br>
+ // `this._local`: the namespace that contains extension attributes and private methods (same as this.ext.EXTNAME)<br>
+ // `this._super`: the virtual function that was overridden (member of previous extension or Fancytree)
+ //
+ // See also the [complete list of available hook functions](https://wwWendt.de/tech/fancytree/doc/jsdoc/Fancytree_Hooks.html).
+
+ /* Init */
+ // `treeInit` is triggered when a tree is initalized. We can set up classes or
+ // bind event handlers here...
+ treeInit: function (ctx) {
+ var tree = this, // same as ctx.tree,
+ opts = ctx.options,
+ extOpts = ctx.options.childcounter;
+ // Optionally check for dependencies with other extensions
+ /* this._requireExtension("glyph", false, false); */
+ // Call the base implementation
+ this._superApply(arguments);
+ // Add a class to the tree container
+ this.$container.addClass("fancytree-ext-childcounter");
+ },
+
+ // Destroy this tree instance (we only call the default implementation, so
+ // this method could as well be omitted).
+
+ treeDestroy: function (ctx) {
+ this._superApply(arguments);
+ },
+
+ // Overload the `renderTitle` hook, to append a counter badge
+ nodeRenderTitle: function (ctx, title) {
+ var node = ctx.node,
+ extOpts = ctx.options.childcounter,
+ count =
+ node.data.childCounter == null
+ ? node.countChildren(extOpts.deep)
+ : +node.data.childCounter;
+ // Let the base implementation render the title
+ // We use `_super()` instead of `_superApply()` here, since it is a little bit
+ // more performant when called often
+ this._super(ctx, title);
+ // Append a counter badge
+ if (
+ (count || !extOpts.hideZeros) &&
+ (!node.isExpanded() || !extOpts.hideExpanded)
+ ) {
+ $(
+ "span.fancytree-icon,span.fancytree-custom-icon",
+ node.span
+ ).append(
+ $("<span class='fancytree-childcounter'/>").text(count)
+ );
+ }
+ },
+ // Overload the `setExpanded` hook, so the counters are updated
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var tree = ctx.tree,
+ node = ctx.node;
+ // Let the base implementation expand/collapse the node, then redraw the title
+ // after the animation has finished
+ return this._superApply(arguments).always(function () {
+ tree.nodeRenderTitle(ctx);
+ });
+ },
+
+ // End of extension definition
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ *
+ * jquery.fancytree.clones.js
+ * Support faster lookup of nodes by key and shared ref-ids.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ var _assert = $.ui.fancytree.assert;
+
+ /* Return first occurrence of member from array. */
+ function _removeArrayMember(arr, elem) {
+ // TODO: use Array.indexOf for IE >= 9
+ var i;
+ for (i = arr.length - 1; i >= 0; i--) {
+ if (arr[i] === elem) {
+ arr.splice(i, 1);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
+ *
+ * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
+ * @see http://github.com/garycourt/murmurhash-js
+ * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
+ * @see http://sites.google.com/site/murmurhash/
+ *
+ * @param {string} key ASCII only
+ * @param {boolean} [asString=false]
+ * @param {number} seed Positive integer only
+ * @return {number} 32-bit positive integer hash
+ */
+ function hashMurmur3(key, asString, seed) {
+ /*eslint-disable no-bitwise */
+ var h1b,
+ k1,
+ remainder = key.length & 3,
+ bytes = key.length - remainder,
+ h1 = seed,
+ c1 = 0xcc9e2d51,
+ c2 = 0x1b873593,
+ i = 0;
+
+ while (i < bytes) {
+ k1 =
+ (key.charCodeAt(i) & 0xff) |
+ ((key.charCodeAt(++i) & 0xff) << 8) |
+ ((key.charCodeAt(++i) & 0xff) << 16) |
+ ((key.charCodeAt(++i) & 0xff) << 24);
+ ++i;
+
+ k1 =
+ ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) &
+ 0xffffffff;
+ k1 = (k1 << 15) | (k1 >>> 17);
+ k1 =
+ ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) &
+ 0xffffffff;
+
+ h1 ^= k1;
+ h1 = (h1 << 13) | (h1 >>> 19);
+ h1b =
+ ((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 =
+ (h1b & 0xffff) +
+ 0x6b64 +
+ ((((h1b >>> 16) + 0xe654) & 0xffff) << 16);
+ }
+
+ k1 = 0;
+
+ switch (remainder) {
+ case 3:
+ k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
+ // fall through
+ case 2:
+ k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
+ // fall through
+ case 1:
+ k1 ^= key.charCodeAt(i) & 0xff;
+
+ k1 =
+ ((k1 & 0xffff) * c1 +
+ ((((k1 >>> 16) * c1) & 0xffff) << 16)) &
+ 0xffffffff;
+ k1 = (k1 << 15) | (k1 >>> 17);
+ k1 =
+ ((k1 & 0xffff) * c2 +
+ ((((k1 >>> 16) * c2) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 ^= k1;
+ }
+
+ h1 ^= key.length;
+
+ h1 ^= h1 >>> 16;
+ h1 =
+ ((h1 & 0xffff) * 0x85ebca6b +
+ ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 ^= h1 >>> 13;
+ h1 =
+ ((h1 & 0xffff) * 0xc2b2ae35 +
+ ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 ^= h1 >>> 16;
+
+ if (asString) {
+ // Convert to 8 digit hex string
+ return ("0000000" + (h1 >>> 0).toString(16)).substr(-8);
+ }
+ return h1 >>> 0;
+ /*eslint-enable no-bitwise */
+ }
+
+ /*
+ * Return a unique key for node by calculating the hash of the parents refKey-list.
+ */
+ function calcUniqueKey(node) {
+ var key,
+ h1,
+ path = $.map(node.getParentList(false, true), function (e) {
+ return e.refKey || e.key;
+ });
+
+ path = path.join("/");
+ // 32-bit has a high probability of collisions, so we pump up to 64-bit
+ // https://security.stackexchange.com/q/209882/207588
+
+ h1 = hashMurmur3(path, true);
+ key = "id_" + h1 + hashMurmur3(h1 + path, true);
+
+ return key;
+ }
+
+ /**
+ * [ext-clones] Return a list of clone-nodes (i.e. same refKey) or null.
+ * @param {boolean} [includeSelf=false]
+ * @returns {FancytreeNode[] | null}
+ *
+ * @alias FancytreeNode#getCloneList
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.getCloneList = function (
+ includeSelf
+ ) {
+ var key,
+ tree = this.tree,
+ refList = tree.refMap[this.refKey] || null,
+ keyMap = tree.keyMap;
+
+ if (refList) {
+ key = this.key;
+ // Convert key list to node list
+ if (includeSelf) {
+ refList = $.map(refList, function (val) {
+ return keyMap[val];
+ });
+ } else {
+ refList = $.map(refList, function (val) {
+ return val === key ? null : keyMap[val];
+ });
+ if (refList.length < 1) {
+ refList = null;
+ }
+ }
+ }
+ return refList;
+ };
+
+ /**
+ * [ext-clones] Return true if this node has at least another clone with same refKey.
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#isClone
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.isClone = function () {
+ var refKey = this.refKey || null,
+ refList = (refKey && this.tree.refMap[refKey]) || null;
+ return !!(refList && refList.length > 1);
+ };
+
+ /**
+ * [ext-clones] Update key and/or refKey for an existing node.
+ * @param {string} key
+ * @param {string} refKey
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#reRegister
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.reRegister = function (
+ key,
+ refKey
+ ) {
+ key = key == null ? null : "" + key;
+ refKey = refKey == null ? null : "" + refKey;
+ // this.debug("reRegister", key, refKey);
+
+ var tree = this.tree,
+ prevKey = this.key,
+ prevRefKey = this.refKey,
+ keyMap = tree.keyMap,
+ refMap = tree.refMap,
+ refList = refMap[prevRefKey] || null,
+ // curCloneKeys = refList ? node.getCloneList(true),
+ modified = false;
+
+ // Key has changed: update all references
+ if (key != null && key !== this.key) {
+ if (keyMap[key]) {
+ $.error(
+ "[ext-clones] reRegister(" +
+ key +
+ "): already exists: " +
+ this
+ );
+ }
+ // Update keyMap
+ delete keyMap[prevKey];
+ keyMap[key] = this;
+ // Update refMap
+ if (refList) {
+ refMap[prevRefKey] = $.map(refList, function (e) {
+ return e === prevKey ? key : e;
+ });
+ }
+ this.key = key;
+ modified = true;
+ }
+
+ // refKey has changed
+ if (refKey != null && refKey !== this.refKey) {
+ // Remove previous refKeys
+ if (refList) {
+ if (refList.length === 1) {
+ delete refMap[prevRefKey];
+ } else {
+ refMap[prevRefKey] = $.map(refList, function (e) {
+ return e === prevKey ? null : e;
+ });
+ }
+ }
+ // Add refKey
+ if (refMap[refKey]) {
+ refMap[refKey].append(key);
+ } else {
+ refMap[refKey] = [this.key];
+ }
+ this.refKey = refKey;
+ modified = true;
+ }
+ return modified;
+ };
+
+ /**
+ * [ext-clones] Define a refKey for an existing node.
+ * @param {string} refKey
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#setRefKey
+ * @requires jquery.fancytree.clones.js
+ * @since 2.16
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.setRefKey = function (refKey) {
+ return this.reRegister(null, refKey);
+ };
+
+ /**
+ * [ext-clones] Return all nodes with a given refKey (null if not found).
+ * @param {string} refKey
+ * @param {FancytreeNode} [rootNode] optionally restrict results to descendants of this node
+ * @returns {FancytreeNode[] | null}
+ * @alias Fancytree#getNodesByRef
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.getNodesByRef = function (
+ refKey,
+ rootNode
+ ) {
+ var keyMap = this.keyMap,
+ refList = this.refMap[refKey] || null;
+
+ if (refList) {
+ // Convert key list to node list
+ if (rootNode) {
+ refList = $.map(refList, function (val) {
+ var node = keyMap[val];
+ return node.isDescendantOf(rootNode) ? node : null;
+ });
+ } else {
+ refList = $.map(refList, function (val) {
+ return keyMap[val];
+ });
+ }
+ if (refList.length < 1) {
+ refList = null;
+ }
+ }
+ return refList;
+ };
+
+ /**
+ * [ext-clones] Replace a refKey with a new one.
+ * @param {string} oldRefKey
+ * @param {string} newRefKey
+ * @alias Fancytree#changeRefKey
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.changeRefKey = function (
+ oldRefKey,
+ newRefKey
+ ) {
+ var i,
+ node,
+ keyMap = this.keyMap,
+ refList = this.refMap[oldRefKey] || null;
+
+ if (refList) {
+ for (i = 0; i < refList.length; i++) {
+ node = keyMap[refList[i]];
+ node.refKey = newRefKey;
+ }
+ delete this.refMap[oldRefKey];
+ this.refMap[newRefKey] = refList;
+ }
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "clones",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers
+ highlightClones: false, // set 'fancytree-clone' class on any node that has at least one clone
+ },
+
+ treeCreate: function (ctx) {
+ this._superApply(arguments);
+ ctx.tree.refMap = {};
+ ctx.tree.keyMap = {};
+ },
+ treeInit: function (ctx) {
+ this.$container.addClass("fancytree-ext-clones");
+ _assert(ctx.options.defaultKey == null);
+ // Generate unique / reproducible default keys
+ ctx.options.defaultKey = function (node) {
+ return calcUniqueKey(node);
+ };
+ // The default implementation loads initial data
+ this._superApply(arguments);
+ },
+ treeClear: function (ctx) {
+ ctx.tree.refMap = {};
+ ctx.tree.keyMap = {};
+ return this._superApply(arguments);
+ },
+ treeRegisterNode: function (ctx, add, node) {
+ var refList,
+ len,
+ tree = ctx.tree,
+ keyMap = tree.keyMap,
+ refMap = tree.refMap,
+ key = node.key,
+ refKey = node && node.refKey != null ? "" + node.refKey : null;
+
+ // ctx.tree.debug("clones.treeRegisterNode", add, node);
+
+ if (node.isStatusNode()) {
+ return this._super(ctx, add, node);
+ }
+
+ if (add) {
+ if (keyMap[node.key] != null) {
+ var other = keyMap[node.key],
+ msg =
+ "clones.treeRegisterNode: duplicate key '" +
+ node.key +
+ "': /" +
+ node.getPath(true) +
+ " => " +
+ other.getPath(true);
+ // Sometimes this exception is not visible in the console,
+ // so we also write it:
+ tree.error(msg);
+ $.error(msg);
+ }
+ keyMap[key] = node;
+
+ if (refKey) {
+ refList = refMap[refKey];
+ if (refList) {
+ refList.push(key);
+ if (
+ refList.length === 2 &&
+ ctx.options.clones.highlightClones
+ ) {
+ // Mark peer node, if it just became a clone (no need to
+ // mark current node, since it will be rendered later anyway)
+ keyMap[refList[0]].renderStatus();
+ }
+ } else {
+ refMap[refKey] = [key];
+ }
+ // node.debug("clones.treeRegisterNode: add clone =>", refMap[refKey]);
+ }
+ } else {
+ if (keyMap[key] == null) {
+ $.error(
+ "clones.treeRegisterNode: node.key not registered: " +
+ node.key
+ );
+ }
+ delete keyMap[key];
+ if (refKey) {
+ refList = refMap[refKey];
+ // node.debug("clones.treeRegisterNode: remove clone BEFORE =>", refMap[refKey]);
+ if (refList) {
+ len = refList.length;
+ if (len <= 1) {
+ _assert(len === 1);
+ _assert(refList[0] === key);
+ delete refMap[refKey];
+ } else {
+ _removeArrayMember(refList, key);
+ // Unmark peer node, if this was the only clone
+ if (
+ len === 2 &&
+ ctx.options.clones.highlightClones
+ ) {
+ // node.debug("clones.treeRegisterNode: last =>", node.getCloneList());
+ keyMap[refList[0]].renderStatus();
+ }
+ }
+ // node.debug("clones.treeRegisterNode: remove clone =>", refMap[refKey]);
+ }
+ }
+ }
+ return this._super(ctx, add, node);
+ },
+ nodeRenderStatus: function (ctx) {
+ var $span,
+ res,
+ node = ctx.node;
+
+ res = this._super(ctx);
+
+ if (ctx.options.clones.highlightClones) {
+ $span = $(node[ctx.tree.statusClassPropName]);
+ // Only if span already exists
+ if ($span.length && node.isClone()) {
+ // node.debug("clones.nodeRenderStatus: ", ctx.options.clones.highlightClones);
+ $span.addClass("fancytree-clone");
+ }
+ }
+ return res;
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var res,
+ scpn = ctx.tree.statusClassPropName,
+ node = ctx.node;
+
+ res = this._superApply(arguments);
+
+ if (ctx.options.clones.highlightActiveClones && node.isClone()) {
+ $.each(node.getCloneList(true), function (idx, n) {
+ // n.debug("clones.nodeSetActive: ", flag !== false);
+ $(n[scpn]).toggleClass(
+ "fancytree-active-clone",
+ flag !== false
+ );
+ });
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.dnd.js
+ *
+ * Drag-and-drop support (jQuery UI draggable/droppable).
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([
+ "jquery",
+ "jquery-ui/ui/widgets/draggable",
+ "jquery-ui/ui/widgets/droppable",
+ "./jquery.fancytree",
+ ], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var didRegisterDnd = false,
+ classDropAccept = "fancytree-drop-accept",
+ classDropAfter = "fancytree-drop-after",
+ classDropBefore = "fancytree-drop-before",
+ classDropOver = "fancytree-drop-over",
+ classDropReject = "fancytree-drop-reject",
+ classDropTarget = "fancytree-drop-target";
+
+ /* Convert number to string and prepend +/-; return empty string for 0.*/
+ function offsetString(n) {
+ // eslint-disable-next-line no-nested-ternary
+ return n === 0 ? "" : n > 0 ? "+" + n : "" + n;
+ }
+
+ //--- Extend ui.draggable event handling --------------------------------------
+
+ function _registerDnd() {
+ if (didRegisterDnd) {
+ return;
+ }
+
+ // Register proxy-functions for draggable.start/drag/stop
+
+ $.ui.plugin.add("draggable", "connectToFancytree", {
+ start: function (event, ui) {
+ // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
+ var draggable =
+ $(this).data("ui-draggable") ||
+ $(this).data("draggable"),
+ sourceNode = ui.helper.data("ftSourceNode") || null;
+
+ if (sourceNode) {
+ // Adjust helper offset, so cursor is slightly outside top/left corner
+ draggable.offset.click.top = -2;
+ draggable.offset.click.left = +16;
+ // Trigger dragStart event
+ // TODO: when called as connectTo..., the return value is ignored(?)
+ return sourceNode.tree.ext.dnd._onDragEvent(
+ "start",
+ sourceNode,
+ null,
+ event,
+ ui,
+ draggable
+ );
+ }
+ },
+ drag: function (event, ui) {
+ var ctx,
+ isHelper,
+ logObject,
+ // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
+ draggable =
+ $(this).data("ui-draggable") ||
+ $(this).data("draggable"),
+ sourceNode = ui.helper.data("ftSourceNode") || null,
+ prevTargetNode = ui.helper.data("ftTargetNode") || null,
+ targetNode = $.ui.fancytree.getNode(event.target),
+ dndOpts = sourceNode && sourceNode.tree.options.dnd;
+
+ // logObject = sourceNode || prevTargetNode || $.ui.fancytree;
+ // logObject.debug("Drag event:", event, event.shiftKey);
+ if (event.target && !targetNode) {
+ // We got a drag event, but the targetNode could not be found
+ // at the event location. This may happen,
+ // 1. if the mouse jumped over the drag helper,
+ // 2. or if a non-fancytree element is dragged
+ // We ignore it:
+ isHelper =
+ $(event.target).closest(
+ "div.fancytree-drag-helper,#fancytree-drop-marker"
+ ).length > 0;
+ if (isHelper) {
+ logObject =
+ sourceNode || prevTargetNode || $.ui.fancytree;
+ logObject.debug("Drag event over helper: ignored.");
+ return;
+ }
+ }
+ ui.helper.data("ftTargetNode", targetNode);
+
+ if (dndOpts && dndOpts.updateHelper) {
+ ctx = sourceNode.tree._makeHookContext(sourceNode, event, {
+ otherNode: targetNode,
+ ui: ui,
+ draggable: draggable,
+ dropMarker: $("#fancytree-drop-marker"),
+ });
+ dndOpts.updateHelper.call(sourceNode.tree, sourceNode, ctx);
+ }
+
+ // Leaving a tree node
+ if (prevTargetNode && prevTargetNode !== targetNode) {
+ prevTargetNode.tree.ext.dnd._onDragEvent(
+ "leave",
+ prevTargetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ }
+ if (targetNode) {
+ if (!targetNode.tree.options.dnd.dragDrop) {
+ // not enabled as drop target
+ } else if (targetNode === prevTargetNode) {
+ // Moving over same node
+ targetNode.tree.ext.dnd._onDragEvent(
+ "over",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ } else {
+ // Entering this node first time
+ targetNode.tree.ext.dnd._onDragEvent(
+ "enter",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ targetNode.tree.ext.dnd._onDragEvent(
+ "over",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ }
+ }
+ // else go ahead with standard event handling
+ },
+ stop: function (event, ui) {
+ var logObject,
+ // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10:
+ draggable =
+ $(this).data("ui-draggable") ||
+ $(this).data("draggable"),
+ sourceNode = ui.helper.data("ftSourceNode") || null,
+ targetNode = ui.helper.data("ftTargetNode") || null,
+ dropped = event.type === "mouseup" && event.which === 1;
+
+ if (!dropped) {
+ logObject = sourceNode || targetNode || $.ui.fancytree;
+ logObject.debug("Drag was cancelled");
+ }
+ if (targetNode) {
+ if (dropped) {
+ targetNode.tree.ext.dnd._onDragEvent(
+ "drop",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ }
+ targetNode.tree.ext.dnd._onDragEvent(
+ "leave",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ }
+ if (sourceNode) {
+ sourceNode.tree.ext.dnd._onDragEvent(
+ "stop",
+ sourceNode,
+ null,
+ event,
+ ui,
+ draggable
+ );
+ }
+ },
+ });
+
+ didRegisterDnd = true;
+ }
+
+ /******************************************************************************
+ * Drag and drop support
+ */
+ function _initDragAndDrop(tree) {
+ var dnd = tree.options.dnd || null,
+ glyph = tree.options.glyph || null;
+
+ // Register 'connectToFancytree' option with ui.draggable
+ if (dnd) {
+ _registerDnd();
+ }
+ // Attach ui.draggable to this Fancytree instance
+ if (dnd && dnd.dragStart) {
+ tree.widget.element.draggable(
+ $.extend(
+ {
+ addClasses: false,
+ // DT issue 244: helper should be child of scrollParent:
+ appendTo: tree.$container,
+ // appendTo: "body",
+ containment: false,
+ // containment: "parent",
+ delay: 0,
+ distance: 4,
+ revert: false,
+ scroll: true, // to disable, also set css 'position: inherit' on ul.fancytree-container
+ scrollSpeed: 7,
+ scrollSensitivity: 10,
+ // Delegate draggable.start, drag, and stop events to our handler
+ connectToFancytree: true,
+ // Let source tree create the helper element
+ helper: function (event) {
+ var $helper,
+ $nodeTag,
+ opts,
+ sourceNode = $.ui.fancytree.getNode(
+ event.target
+ );
+
+ if (!sourceNode) {
+ // #405, DT issue 211: might happen, if dragging a table *header*
+ return "<div>ERROR?: helper requested but sourceNode not found</div>";
+ }
+ opts = sourceNode.tree.options.dnd;
+ $nodeTag = $(sourceNode.span);
+ // Only event and node argument is available
+ $helper = $(
+ "<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>"
+ )
+ .css({ zIndex: 3, position: "relative" }) // so it appears above ext-wide selection bar
+ .append(
+ $nodeTag
+ .find("span.fancytree-title")
+ .clone()
+ );
+
+ // Attach node reference to helper object
+ $helper.data("ftSourceNode", sourceNode);
+
+ // Support glyph symbols instead of icons
+ if (glyph) {
+ $helper
+ .find(".fancytree-drag-helper-img")
+ .addClass(
+ glyph.map._addClass +
+ " " +
+ glyph.map.dragHelper
+ );
+ }
+ // Allow to modify the helper, e.g. to add multi-node-drag feedback
+ if (opts.initHelper) {
+ opts.initHelper.call(
+ sourceNode.tree,
+ sourceNode,
+ {
+ node: sourceNode,
+ tree: sourceNode.tree,
+ originalEvent: event,
+ ui: { helper: $helper },
+ }
+ );
+ }
+ // We return an unconnected element, so `draggable` will add this
+ // to the parent specified as `appendTo` option
+ return $helper;
+ },
+ start: function (event, ui) {
+ var sourceNode = ui.helper.data("ftSourceNode");
+ return !!sourceNode; // Abort dragging if no node could be found
+ },
+ },
+ tree.options.dnd.draggable
+ )
+ );
+ }
+ // Attach ui.droppable to this Fancytree instance
+ if (dnd && dnd.dragDrop) {
+ tree.widget.element.droppable(
+ $.extend(
+ {
+ addClasses: false,
+ tolerance: "intersect",
+ greedy: false,
+ /*
+ activate: function(event, ui) {
+ tree.debug("droppable - activate", event, ui, this);
+ },
+ create: function(event, ui) {
+ tree.debug("droppable - create", event, ui);
+ },
+ deactivate: function(event, ui) {
+ tree.debug("droppable - deactivate", event, ui);
+ },
+ drop: function(event, ui) {
+ tree.debug("droppable - drop", event, ui);
+ },
+ out: function(event, ui) {
+ tree.debug("droppable - out", event, ui);
+ },
+ over: function(event, ui) {
+ tree.debug("droppable - over", event, ui);
+ }
+*/
+ },
+ tree.options.dnd.droppable
+ )
+ );
+ }
+ }
+
+ /******************************************************************************
+ *
+ */
+
+ $.ui.fancytree.registerExtension({
+ name: "dnd",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ // Make tree nodes accept draggables
+ autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
+ draggable: null, // Additional options passed to jQuery draggable
+ droppable: null, // Additional options passed to jQuery droppable
+ focusOnClick: false, // Focus, although draggable cancels mousedown event (#270)
+ preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
+ preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
+ smartRevert: true, // set draggable.revert = true if drop was rejected
+ dropMarkerOffsetX: -24, // absolute position offset for .fancytree-drop-marker relatively to ..fancytree-title (icon/img near a node accepting drop)
+ dropMarkerInsertOffsetX: -16, // additional offset for drop-marker with hitMode = "before"/"after"
+ // Events (drag support)
+ dragStart: null, // Callback(sourceNode, data), return true, to enable dnd
+ dragStop: null, // Callback(sourceNode, data)
+ initHelper: null, // Callback(sourceNode, data)
+ updateHelper: null, // Callback(sourceNode, data)
+ // Events (drop support)
+ dragEnter: null, // Callback(targetNode, data)
+ dragOver: null, // Callback(targetNode, data)
+ dragExpand: null, // Callback(targetNode, data), return false to prevent autoExpand
+ dragDrop: null, // Callback(targetNode, data)
+ dragLeave: null, // Callback(targetNode, data)
+ },
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree;
+ this._superApply(arguments);
+ // issue #270: draggable eats mousedown events
+ if (tree.options.dnd.dragStart) {
+ tree.$container.on("mousedown", function (event) {
+ // if( !tree.hasFocus() && ctx.options.dnd.focusOnClick ) {
+ if (ctx.options.dnd.focusOnClick) {
+ // #270
+ var node = $.ui.fancytree.getNode(event);
+ if (node) {
+ node.debug(
+ "Re-enable focus that was prevented by jQuery UI draggable."
+ );
+ // node.setFocus();
+ // $(node.span).closest(":tabbable").focus();
+ // $(event.target).trigger("focus");
+ // $(event.target).closest(":tabbable").trigger("focus");
+ }
+ setTimeout(function () {
+ // #300
+ $(event.target).closest(":tabbable").focus();
+ }, 10);
+ }
+ });
+ }
+ _initDragAndDrop(tree);
+ },
+ /* Display drop marker according to hitMode ('after', 'before', 'over'). */
+ _setDndStatus: function (
+ sourceNode,
+ targetNode,
+ helper,
+ hitMode,
+ accept
+ ) {
+ var markerOffsetX,
+ pos,
+ markerAt = "center",
+ instData = this._local,
+ dndOpt = this.options.dnd,
+ glyphOpt = this.options.glyph,
+ $source = sourceNode ? $(sourceNode.span) : null,
+ $target = $(targetNode.span),
+ $targetTitle = $target.find("span.fancytree-title");
+
+ if (!instData.$dropMarker) {
+ instData.$dropMarker = $(
+ "<div id='fancytree-drop-marker'></div>"
+ )
+ .hide()
+ .css({ "z-index": 1000 })
+ .prependTo($(this.$div).parent());
+ // .prependTo("body");
+
+ if (glyphOpt) {
+ instData.$dropMarker.addClass(
+ glyphOpt.map._addClass + " " + glyphOpt.map.dropMarker
+ );
+ }
+ }
+ if (
+ hitMode === "after" ||
+ hitMode === "before" ||
+ hitMode === "over"
+ ) {
+ markerOffsetX = dndOpt.dropMarkerOffsetX || 0;
+ switch (hitMode) {
+ case "before":
+ markerAt = "top";
+ markerOffsetX += dndOpt.dropMarkerInsertOffsetX || 0;
+ break;
+ case "after":
+ markerAt = "bottom";
+ markerOffsetX += dndOpt.dropMarkerInsertOffsetX || 0;
+ break;
+ }
+
+ pos = {
+ my: "left" + offsetString(markerOffsetX) + " center",
+ at: "left " + markerAt,
+ of: $targetTitle,
+ };
+ if (this.options.rtl) {
+ pos.my = "right" + offsetString(-markerOffsetX) + " center";
+ pos.at = "right " + markerAt;
+ }
+ instData.$dropMarker
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropOver, hitMode === "over")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .toggleClass("fancytree-rtl", !!this.options.rtl)
+ .show()
+ .position($.ui.fancytree.fixPositionOptions(pos));
+ } else {
+ instData.$dropMarker.hide();
+ }
+ if ($source) {
+ $source
+ .toggleClass(classDropAccept, accept === true)
+ .toggleClass(classDropReject, accept === false);
+ }
+ $target
+ .toggleClass(
+ classDropTarget,
+ hitMode === "after" ||
+ hitMode === "before" ||
+ hitMode === "over"
+ )
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .toggleClass(classDropAccept, accept === true)
+ .toggleClass(classDropReject, accept === false);
+
+ helper
+ .toggleClass(classDropAccept, accept === true)
+ .toggleClass(classDropReject, accept === false);
+ },
+
+ /*
+ * Handles drag'n'drop functionality.
+ *
+ * A standard jQuery drag-and-drop process may generate these calls:
+ *
+ * start:
+ * _onDragEvent("start", sourceNode, null, event, ui, draggable);
+ * drag:
+ * _onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
+ * _onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
+ * _onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
+ * stop:
+ * _onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
+ * _onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
+ * _onDragEvent("stop", sourceNode, null, event, ui, draggable);
+ */
+ _onDragEvent: function (
+ eventName,
+ node,
+ otherNode,
+ event,
+ ui,
+ draggable
+ ) {
+ // if(eventName !== "over"){
+ // this.debug("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o", eventName, node, otherNode, this);
+ // }
+ var accept,
+ nodeOfs,
+ parentRect,
+ rect,
+ relPos,
+ relPos2,
+ enterResponse,
+ hitMode,
+ r,
+ opts = this.options,
+ dnd = opts.dnd,
+ ctx = this._makeHookContext(node, event, {
+ otherNode: otherNode,
+ ui: ui,
+ draggable: draggable,
+ }),
+ res = null,
+ self = this,
+ $nodeTag = $(node.span);
+
+ if (dnd.smartRevert) {
+ draggable.options.revert = "invalid";
+ }
+
+ switch (eventName) {
+ case "start":
+ if (node.isStatusNode()) {
+ res = false;
+ } else if (dnd.dragStart) {
+ res = dnd.dragStart(node, ctx);
+ }
+ if (res === false) {
+ this.debug("tree.dragStart() cancelled");
+ //draggable._clear();
+ // NOTE: the return value seems to be ignored (drag is not cancelled, when false is returned)
+ // TODO: call this._cancelDrag()?
+ ui.helper.trigger("mouseup").hide();
+ } else {
+ if (dnd.smartRevert) {
+ // #567, #593: fix revert position
+ // rect = node.li.getBoundingClientRect();
+ rect =
+ node[
+ ctx.tree.nodeContainerAttrName
+ ].getBoundingClientRect();
+ parentRect = $(
+ draggable.options.appendTo
+ )[0].getBoundingClientRect();
+ draggable.originalPosition.left = Math.max(
+ 0,
+ rect.left - parentRect.left
+ );
+ draggable.originalPosition.top = Math.max(
+ 0,
+ rect.top - parentRect.top
+ );
+ }
+ $nodeTag.addClass("fancytree-drag-source");
+ // Register global handlers to allow cancel
+ $(document).on(
+ "keydown.fancytree-dnd,mousedown.fancytree-dnd",
+ function (event) {
+ // node.tree.debug("dnd global event", event.type, event.which);
+ if (
+ event.type === "keydown" &&
+ event.which === $.ui.keyCode.ESCAPE
+ ) {
+ self.ext.dnd._cancelDrag();
+ } else if (event.type === "mousedown") {
+ self.ext.dnd._cancelDrag();
+ }
+ }
+ );
+ }
+ break;
+
+ case "enter":
+ if (
+ dnd.preventRecursiveMoves &&
+ node.isDescendantOf(otherNode)
+ ) {
+ r = false;
+ } else {
+ r = dnd.dragEnter ? dnd.dragEnter(node, ctx) : null;
+ }
+ if (!r) {
+ // convert null, undefined, false to false
+ res = false;
+ } else if (Array.isArray(r)) {
+ // TODO: also accept passing an object of this format directly
+ res = {
+ over: $.inArray("over", r) >= 0,
+ before: $.inArray("before", r) >= 0,
+ after: $.inArray("after", r) >= 0,
+ };
+ } else {
+ res = {
+ over: r === true || r === "over",
+ before: r === true || r === "before",
+ after: r === true || r === "after",
+ };
+ }
+ ui.helper.data("enterResponse", res);
+ // this.debug("helper.enterResponse: %o", res);
+ break;
+
+ case "over":
+ enterResponse = ui.helper.data("enterResponse");
+ hitMode = null;
+ if (enterResponse === false) {
+ // Don't call dragOver if onEnter returned false.
+ // break;
+ } else if (typeof enterResponse === "string") {
+ // Use hitMode from onEnter if provided.
+ hitMode = enterResponse;
+ } else {
+ // Calculate hitMode from relative cursor position.
+ nodeOfs = $nodeTag.offset();
+ relPos = {
+ x: event.pageX - nodeOfs.left,
+ y: event.pageY - nodeOfs.top,
+ };
+ relPos2 = {
+ x: relPos.x / $nodeTag.width(),
+ y: relPos.y / $nodeTag.height(),
+ };
+
+ if (enterResponse.after && relPos2.y > 0.75) {
+ hitMode = "after";
+ } else if (
+ !enterResponse.over &&
+ enterResponse.after &&
+ relPos2.y > 0.5
+ ) {
+ hitMode = "after";
+ } else if (enterResponse.before && relPos2.y <= 0.25) {
+ hitMode = "before";
+ } else if (
+ !enterResponse.over &&
+ enterResponse.before &&
+ relPos2.y <= 0.5
+ ) {
+ hitMode = "before";
+ } else if (enterResponse.over) {
+ hitMode = "over";
+ }
+ // Prevent no-ops like 'before source node'
+ // TODO: these are no-ops when moving nodes, but not in copy mode
+ if (dnd.preventVoidMoves) {
+ if (node === otherNode) {
+ this.debug(
+ " drop over source node prevented"
+ );
+ hitMode = null;
+ } else if (
+ hitMode === "before" &&
+ otherNode &&
+ node === otherNode.getNextSibling()
+ ) {
+ this.debug(
+ " drop after source node prevented"
+ );
+ hitMode = null;
+ } else if (
+ hitMode === "after" &&
+ otherNode &&
+ node === otherNode.getPrevSibling()
+ ) {
+ this.debug(
+ " drop before source node prevented"
+ );
+ hitMode = null;
+ } else if (
+ hitMode === "over" &&
+ otherNode &&
+ otherNode.parent === node &&
+ otherNode.isLastSibling()
+ ) {
+ this.debug(
+ " drop last child over own parent prevented"
+ );
+ hitMode = null;
+ }
+ }
+ // this.debug("hitMode: %s - %s - %s", hitMode, (node.parent === otherNode), node.isLastSibling());
+ ui.helper.data("hitMode", hitMode);
+ }
+ // Auto-expand node (only when 'over' the node, not 'before', or 'after')
+ if (
+ hitMode !== "before" &&
+ hitMode !== "after" &&
+ dnd.autoExpandMS &&
+ node.hasChildren() !== false &&
+ !node.expanded &&
+ (!dnd.dragExpand || dnd.dragExpand(node, ctx) !== false)
+ ) {
+ node.scheduleAction("expand", dnd.autoExpandMS);
+ }
+ if (hitMode && dnd.dragOver) {
+ // TODO: http://code.google.com/p/dynatree/source/detail?r=625
+ ctx.hitMode = hitMode;
+ res = dnd.dragOver(node, ctx);
+ }
+ accept = res !== false && hitMode !== null;
+ if (dnd.smartRevert) {
+ draggable.options.revert = !accept;
+ }
+ this._local._setDndStatus(
+ otherNode,
+ node,
+ ui.helper,
+ hitMode,
+ accept
+ );
+ break;
+
+ case "drop":
+ hitMode = ui.helper.data("hitMode");
+ if (hitMode && dnd.dragDrop) {
+ ctx.hitMode = hitMode;
+ dnd.dragDrop(node, ctx);
+ }
+ break;
+
+ case "leave":
+ // Cancel pending expand request
+ node.scheduleAction("cancel");
+ ui.helper.data("enterResponse", null);
+ ui.helper.data("hitMode", null);
+ this._local._setDndStatus(
+ otherNode,
+ node,
+ ui.helper,
+ "out",
+ undefined
+ );
+ if (dnd.dragLeave) {
+ dnd.dragLeave(node, ctx);
+ }
+ break;
+
+ case "stop":
+ $nodeTag.removeClass("fancytree-drag-source");
+ $(document).off(".fancytree-dnd");
+ if (dnd.dragStop) {
+ dnd.dragStop(node, ctx);
+ }
+ break;
+
+ default:
+ $.error("Unsupported drag event: " + eventName);
+ }
+ return res;
+ },
+
+ _cancelDrag: function () {
+ var dd = $.ui.ddmanager.current;
+ if (dd) {
+ dd.cancel();
+ }
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.dnd5.js
+ *
+ * Drag-and-drop support (native HTML5).
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+/*
+ #TODO
+ Compatiblity when dragging between *separate* windows:
+
+ Drag from Chrome Edge FF IE11 Safari
+ To Chrome ok ok ok NO ?
+ Edge ok ok ok NO ?
+ FF ok ok ok NO ?
+ IE 11 ok ok ok ok ?
+ Safari ? ? ? ? ok
+
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var FT = $.ui.fancytree,
+ isMac = /Mac/.test(navigator.platform),
+ classDragSource = "fancytree-drag-source",
+ classDragRemove = "fancytree-drag-remove",
+ classDropAccept = "fancytree-drop-accept",
+ classDropAfter = "fancytree-drop-after",
+ classDropBefore = "fancytree-drop-before",
+ classDropOver = "fancytree-drop-over",
+ classDropReject = "fancytree-drop-reject",
+ classDropTarget = "fancytree-drop-target",
+ nodeMimeType = "application/x-fancytree-node",
+ $dropMarker = null,
+ $dragImage,
+ $extraHelper,
+ SOURCE_NODE = null,
+ SOURCE_NODE_LIST = null,
+ $sourceList = null,
+ DRAG_ENTER_RESPONSE = null,
+ // SESSION_DATA = null, // plain object passed to events as `data`
+ SUGGESTED_DROP_EFFECT = null,
+ REQUESTED_DROP_EFFECT = null,
+ REQUESTED_EFFECT_ALLOWED = null,
+ LAST_HIT_MODE = null,
+ DRAG_OVER_STAMP = null; // Time when a node entered the 'over' hitmode
+
+ /* */
+ function _clearGlobals() {
+ DRAG_ENTER_RESPONSE = null;
+ DRAG_OVER_STAMP = null;
+ REQUESTED_DROP_EFFECT = null;
+ REQUESTED_EFFECT_ALLOWED = null;
+ SUGGESTED_DROP_EFFECT = null;
+ SOURCE_NODE = null;
+ SOURCE_NODE_LIST = null;
+ if ($sourceList) {
+ $sourceList.removeClass(classDragSource + " " + classDragRemove);
+ }
+ $sourceList = null;
+ if ($dropMarker) {
+ $dropMarker.hide();
+ }
+ // Take this badge off of me - I can't use it anymore:
+ if ($extraHelper) {
+ $extraHelper.remove();
+ $extraHelper = null;
+ }
+ }
+
+ /* Convert number to string and prepend +/-; return empty string for 0.*/
+ function offsetString(n) {
+ // eslint-disable-next-line no-nested-ternary
+ return n === 0 ? "" : n > 0 ? "+" + n : "" + n;
+ }
+
+ /* Convert a dragEnter() or dragOver() response to a canonical form.
+ * Return false or plain object
+ * @param {string|object|boolean} r
+ * @return {object|false}
+ */
+ function normalizeDragEnterResponse(r) {
+ var res;
+
+ if (!r) {
+ return false;
+ }
+ if ($.isPlainObject(r)) {
+ res = {
+ over: !!r.over,
+ before: !!r.before,
+ after: !!r.after,
+ };
+ } else if (Array.isArray(r)) {
+ res = {
+ over: $.inArray("over", r) >= 0,
+ before: $.inArray("before", r) >= 0,
+ after: $.inArray("after", r) >= 0,
+ };
+ } else {
+ res = {
+ over: r === true || r === "over",
+ before: r === true || r === "before",
+ after: r === true || r === "after",
+ };
+ }
+ if (Object.keys(res).length === 0) {
+ return false;
+ }
+ // if( Object.keys(res).length === 1 ) {
+ // res.unique = res[0];
+ // }
+ return res;
+ }
+
+ /* Convert a dataTransfer.effectAllowed to a canonical form.
+ * Return false or plain object
+ * @param {string|boolean} r
+ * @return {object|false}
+ */
+ // function normalizeEffectAllowed(r) {
+ // if (!r || r === "none") {
+ // return false;
+ // }
+ // var all = r === "all",
+ // res = {
+ // copy: all || /copy/i.test(r),
+ // link: all || /link/i.test(r),
+ // move: all || /move/i.test(r),
+ // };
+
+ // return res;
+ // }
+
+ /* Implement auto scrolling when drag cursor is in top/bottom area of scroll parent. */
+ function autoScroll(tree, event) {
+ var spOfs,
+ scrollTop,
+ delta,
+ dndOpts = tree.options.dnd5,
+ sp = tree.$scrollParent[0],
+ sensitivity = dndOpts.scrollSensitivity,
+ speed = dndOpts.scrollSpeed,
+ scrolled = 0;
+
+ if (sp !== document && sp.tagName !== "HTML") {
+ spOfs = tree.$scrollParent.offset();
+ scrollTop = sp.scrollTop;
+ if (spOfs.top + sp.offsetHeight - event.pageY < sensitivity) {
+ delta =
+ sp.scrollHeight -
+ tree.$scrollParent.innerHeight() -
+ scrollTop;
+ // console.log ("sp.offsetHeight: " + sp.offsetHeight
+ // + ", spOfs.top: " + spOfs.top
+ // + ", scrollTop: " + scrollTop
+ // + ", innerHeight: " + tree.$scrollParent.innerHeight()
+ // + ", scrollHeight: " + sp.scrollHeight
+ // + ", delta: " + delta
+ // );
+ if (delta > 0) {
+ sp.scrollTop = scrolled = scrollTop + speed;
+ }
+ } else if (scrollTop > 0 && event.pageY - spOfs.top < sensitivity) {
+ sp.scrollTop = scrolled = scrollTop - speed;
+ }
+ } else {
+ scrollTop = $(document).scrollTop();
+ if (scrollTop > 0 && event.pageY - scrollTop < sensitivity) {
+ scrolled = scrollTop - speed;
+ $(document).scrollTop(scrolled);
+ } else if (
+ $(window).height() - (event.pageY - scrollTop) <
+ sensitivity
+ ) {
+ scrolled = scrollTop + speed;
+ $(document).scrollTop(scrolled);
+ }
+ }
+ if (scrolled) {
+ tree.debug("autoScroll: " + scrolled + "px");
+ }
+ return scrolled;
+ }
+
+ /* Guess dropEffect from modifier keys.
+ * Using rules suggested here:
+ * https://ux.stackexchange.com/a/83769
+ * @returns
+ * 'copy', 'link', 'move', or 'none'
+ */
+ function evalEffectModifiers(tree, event, effectDefault) {
+ var res = effectDefault;
+
+ if (isMac) {
+ if (event.metaKey && event.altKey) {
+ // Mac: [Control] + [Option]
+ res = "link";
+ } else if (event.ctrlKey) {
+ // Chrome on Mac: [Control]
+ res = "link";
+ } else if (event.metaKey) {
+ // Mac: [Command]
+ res = "move";
+ } else if (event.altKey) {
+ // Mac: [Option]
+ res = "copy";
+ }
+ } else {
+ if (event.ctrlKey) {
+ // Windows: [Ctrl]
+ res = "copy";
+ } else if (event.shiftKey) {
+ // Windows: [Shift]
+ res = "move";
+ } else if (event.altKey) {
+ // Windows: [Alt]
+ res = "link";
+ }
+ }
+ if (res !== SUGGESTED_DROP_EFFECT) {
+ tree.info(
+ "evalEffectModifiers: " +
+ event.type +
+ " - evalEffectModifiers(): " +
+ SUGGESTED_DROP_EFFECT +
+ " -> " +
+ res
+ );
+ }
+ SUGGESTED_DROP_EFFECT = res;
+ // tree.debug("evalEffectModifiers: " + res);
+ return res;
+ }
+ /*
+ * Check if the previous callback (dragEnter, dragOver, ...) has changed
+ * the `data` object and apply those settings.
+ *
+ * Safari:
+ * It seems that `dataTransfer.dropEffect` can only be set on dragStart, and will remain
+ * even if the cursor changes when [Alt] or [Ctrl] are pressed (?)
+ * Using rules suggested here:
+ * https://ux.stackexchange.com/a/83769
+ * @returns
+ * 'copy', 'link', 'move', or 'none'
+ */
+ function prepareDropEffectCallback(event, data) {
+ var tree = data.tree,
+ dataTransfer = data.dataTransfer;
+
+ if (event.type === "dragstart") {
+ data.effectAllowed = tree.options.dnd5.effectAllowed;
+ data.dropEffect = tree.options.dnd5.dropEffectDefault;
+ } else {
+ data.effectAllowed = REQUESTED_EFFECT_ALLOWED;
+ data.dropEffect = REQUESTED_DROP_EFFECT;
+ }
+ data.dropEffectSuggested = evalEffectModifiers(
+ tree,
+ event,
+ tree.options.dnd5.dropEffectDefault
+ );
+ data.isMove = data.dropEffect === "move";
+ data.files = dataTransfer.files || [];
+
+ // if (REQUESTED_EFFECT_ALLOWED !== dataTransfer.effectAllowed) {
+ // tree.warn(
+ // "prepareDropEffectCallback(" +
+ // event.type +
+ // "): dataTransfer.effectAllowed changed from " +
+ // REQUESTED_EFFECT_ALLOWED +
+ // " -> " +
+ // dataTransfer.effectAllowed
+ // );
+ // }
+ // if (REQUESTED_DROP_EFFECT !== dataTransfer.dropEffect) {
+ // tree.warn(
+ // "prepareDropEffectCallback(" +
+ // event.type +
+ // "): dataTransfer.dropEffect changed from requested " +
+ // REQUESTED_DROP_EFFECT +
+ // " to " +
+ // dataTransfer.dropEffect
+ // );
+ // }
+ }
+
+ function applyDropEffectCallback(event, data, allowDrop) {
+ var tree = data.tree,
+ dataTransfer = data.dataTransfer;
+
+ if (
+ event.type !== "dragstart" &&
+ REQUESTED_EFFECT_ALLOWED !== data.effectAllowed
+ ) {
+ tree.warn(
+ "effectAllowed should only be changed in dragstart event: " +
+ event.type +
+ ": data.effectAllowed changed from " +
+ REQUESTED_EFFECT_ALLOWED +
+ " -> " +
+ data.effectAllowed
+ );
+ }
+
+ if (allowDrop === false) {
+ tree.info("applyDropEffectCallback: allowDrop === false");
+ data.effectAllowed = "none";
+ data.dropEffect = "none";
+ }
+ // if (REQUESTED_DROP_EFFECT !== data.dropEffect) {
+ // tree.debug(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): data.dropEffect changed from previous " +
+ // REQUESTED_DROP_EFFECT +
+ // " to " +
+ // data.dropEffect
+ // );
+ // }
+
+ data.isMove = data.dropEffect === "move";
+ // data.isMove = data.dropEffectSuggested === "move";
+
+ // `effectAllowed` must only be defined in dragstart event, so we
+ // store it in a global variable for reference
+ if (event.type === "dragstart") {
+ REQUESTED_EFFECT_ALLOWED = data.effectAllowed;
+ REQUESTED_DROP_EFFECT = data.dropEffect;
+ }
+
+ // if (REQUESTED_DROP_EFFECT !== dataTransfer.dropEffect) {
+ // data.tree.info(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): dataTransfer.dropEffect changed from " +
+ // REQUESTED_DROP_EFFECT +
+ // " -> " +
+ // dataTransfer.dropEffect
+ // );
+ // }
+ dataTransfer.effectAllowed = REQUESTED_EFFECT_ALLOWED;
+ dataTransfer.dropEffect = REQUESTED_DROP_EFFECT;
+
+ // tree.debug(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): set " +
+ // dataTransfer.dropEffect +
+ // "/" +
+ // dataTransfer.effectAllowed
+ // );
+ // if (REQUESTED_DROP_EFFECT !== dataTransfer.dropEffect) {
+ // data.tree.warn(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): could not set dataTransfer.dropEffect to " +
+ // REQUESTED_DROP_EFFECT +
+ // ": got " +
+ // dataTransfer.dropEffect
+ // );
+ // }
+ return REQUESTED_DROP_EFFECT;
+ }
+
+ /* Handle dragover event (fired every x ms) on valid drop targets.
+ *
+ * - Auto-scroll when cursor is in border regions
+ * - Apply restrictioan like 'preventVoidMoves'
+ * - Calculate hit mode
+ * - Calculate drop effect
+ * - Trigger dragOver() callback to let user modify hit mode and drop effect
+ * - Adjust the drop marker accordingly
+ *
+ * @returns hitMode
+ */
+ function handleDragOver(event, data) {
+ // Implement auto-scrolling
+ if (data.options.dnd5.scroll) {
+ autoScroll(data.tree, event);
+ }
+ // Bail out with previous response if we get an invalid dragover
+ if (!data.node) {
+ data.tree.warn("Ignored dragover for non-node"); //, event, data);
+ return LAST_HIT_MODE;
+ }
+
+ var markerOffsetX,
+ nodeOfs,
+ pos,
+ relPosY,
+ hitMode = null,
+ tree = data.tree,
+ options = tree.options,
+ dndOpts = options.dnd5,
+ targetNode = data.node,
+ sourceNode = data.otherNode,
+ markerAt = "center",
+ $target = $(targetNode.span),
+ $targetTitle = $target.find("span.fancytree-title");
+
+ if (DRAG_ENTER_RESPONSE === false) {
+ tree.debug("Ignored dragover, since dragenter returned false.");
+ return false;
+ } else if (typeof DRAG_ENTER_RESPONSE === "string") {
+ $.error("assert failed: dragenter returned string");
+ }
+ // Calculate hitMode from relative cursor position.
+ nodeOfs = $target.offset();
+ relPosY = (event.pageY - nodeOfs.top) / $target.height();
+ if (event.pageY === undefined) {
+ tree.warn("event.pageY is undefined: see issue #1013.");
+ }
+
+ if (DRAG_ENTER_RESPONSE.after && relPosY > 0.75) {
+ hitMode = "after";
+ } else if (
+ !DRAG_ENTER_RESPONSE.over &&
+ DRAG_ENTER_RESPONSE.after &&
+ relPosY > 0.5
+ ) {
+ hitMode = "after";
+ } else if (DRAG_ENTER_RESPONSE.before && relPosY <= 0.25) {
+ hitMode = "before";
+ } else if (
+ !DRAG_ENTER_RESPONSE.over &&
+ DRAG_ENTER_RESPONSE.before &&
+ relPosY <= 0.5
+ ) {
+ hitMode = "before";
+ } else if (DRAG_ENTER_RESPONSE.over) {
+ hitMode = "over";
+ }
+ // Prevent no-ops like 'before source node'
+ // TODO: these are no-ops when moving nodes, but not in copy mode
+ if (dndOpts.preventVoidMoves && data.dropEffect === "move") {
+ if (targetNode === sourceNode) {
+ targetNode.debug("Drop over source node prevented.");
+ hitMode = null;
+ } else if (
+ hitMode === "before" &&
+ sourceNode &&
+ targetNode === sourceNode.getNextSibling()
+ ) {
+ targetNode.debug("Drop after source node prevented.");
+ hitMode = null;
+ } else if (
+ hitMode === "after" &&
+ sourceNode &&
+ targetNode === sourceNode.getPrevSibling()
+ ) {
+ targetNode.debug("Drop before source node prevented.");
+ hitMode = null;
+ } else if (
+ hitMode === "over" &&
+ sourceNode &&
+ sourceNode.parent === targetNode &&
+ sourceNode.isLastSibling()
+ ) {
+ targetNode.debug("Drop last child over own parent prevented.");
+ hitMode = null;
+ }
+ }
+ // Let callback modify the calculated hitMode
+ data.hitMode = hitMode;
+ if (hitMode && dndOpts.dragOver) {
+ prepareDropEffectCallback(event, data);
+ dndOpts.dragOver(targetNode, data);
+ var allowDrop = !!hitMode;
+ applyDropEffectCallback(event, data, allowDrop);
+ hitMode = data.hitMode;
+ }
+ LAST_HIT_MODE = hitMode;
+ //
+ if (hitMode === "after" || hitMode === "before" || hitMode === "over") {
+ markerOffsetX = dndOpts.dropMarkerOffsetX || 0;
+ switch (hitMode) {
+ case "before":
+ markerAt = "top";
+ markerOffsetX += dndOpts.dropMarkerInsertOffsetX || 0;
+ break;
+ case "after":
+ markerAt = "bottom";
+ markerOffsetX += dndOpts.dropMarkerInsertOffsetX || 0;
+ break;
+ }
+
+ pos = {
+ my: "left" + offsetString(markerOffsetX) + " center",
+ at: "left " + markerAt,
+ of: $targetTitle,
+ };
+ if (options.rtl) {
+ pos.my = "right" + offsetString(-markerOffsetX) + " center";
+ pos.at = "right " + markerAt;
+ // console.log("rtl", pos);
+ }
+ $dropMarker
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropOver, hitMode === "over")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .show()
+ .position(FT.fixPositionOptions(pos));
+ } else {
+ $dropMarker.hide();
+ // console.log("hide dropmarker")
+ }
+
+ $(targetNode.span)
+ .toggleClass(
+ classDropTarget,
+ hitMode === "after" ||
+ hitMode === "before" ||
+ hitMode === "over"
+ )
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .toggleClass(classDropAccept, hitMode === "over")
+ .toggleClass(classDropReject, hitMode === false);
+
+ return hitMode;
+ }
+
+ /*
+ * Handle dragstart drag dragend events on the container
+ */
+ function onDragEvent(event) {
+ var json,
+ tree = this,
+ dndOpts = tree.options.dnd5,
+ node = FT.getNode(event),
+ dataTransfer =
+ event.dataTransfer || event.originalEvent.dataTransfer,
+ data = {
+ tree: tree,
+ node: node,
+ options: tree.options,
+ originalEvent: event.originalEvent,
+ widget: tree.widget,
+ dataTransfer: dataTransfer,
+ useDefaultImage: true,
+ dropEffect: undefined,
+ dropEffectSuggested: undefined,
+ effectAllowed: undefined, // set by dragstart
+ files: undefined, // only for drop events
+ isCancelled: undefined, // set by dragend
+ isMove: undefined,
+ };
+
+ switch (event.type) {
+ case "dragstart":
+ if (!node) {
+ tree.info("Ignored dragstart on a non-node.");
+ return false;
+ }
+ // Store current source node in different formats
+ SOURCE_NODE = node;
+
+ // Also optionally store selected nodes
+ if (dndOpts.multiSource === false) {
+ SOURCE_NODE_LIST = [node];
+ } else if (dndOpts.multiSource === true) {
+ if (node.isSelected()) {
+ SOURCE_NODE_LIST = tree.getSelectedNodes();
+ } else {
+ SOURCE_NODE_LIST = [node];
+ }
+ } else {
+ SOURCE_NODE_LIST = dndOpts.multiSource(node, data);
+ }
+ // Cache as array of jQuery objects for faster access:
+ $sourceList = $(
+ $.map(SOURCE_NODE_LIST, function (n) {
+ return n.span;
+ })
+ );
+ // Set visual feedback
+ $sourceList.addClass(classDragSource);
+
+ // Set payload
+ // Note:
+ // Transfer data is only accessible on dragstart and drop!
+ // For all other events the formats and kinds in the drag
+ // data store list of items representing dragged data can be
+ // enumerated, but the data itself is unavailable and no new
+ // data can be added.
+ var nodeData = node.toDict(true, dndOpts.sourceCopyHook);
+ nodeData.treeId = node.tree._id;
+ json = JSON.stringify(nodeData);
+ try {
+ dataTransfer.setData(nodeMimeType, json);
+ dataTransfer.setData("text/html", $(node.span).html());
+ dataTransfer.setData("text/plain", node.title);
+ } catch (ex) {
+ // IE only accepts 'text' type
+ tree.warn(
+ "Could not set data (IE only accepts 'text') - " + ex
+ );
+ }
+ // We always need to set the 'text' type if we want to drag
+ // Because IE 11 only accepts this single type.
+ // If we pass JSON here, IE can can access all node properties,
+ // even when the source lives in another window. (D'n'd inside
+ // the same window will always work.)
+ // The drawback is, that in this case ALL browsers will see
+ // the JSON representation as 'text', so dragging
+ // to a text field will insert the JSON string instead of
+ // the node title.
+ if (dndOpts.setTextTypeJson) {
+ dataTransfer.setData("text", json);
+ } else {
+ dataTransfer.setData("text", node.title);
+ }
+
+ // Set the allowed drag modes (combinations of move, copy, and link)
+ // (effectAllowed can only be set in the dragstart event.)
+ // This can be overridden in the dragStart() callback
+ prepareDropEffectCallback(event, data);
+
+ // Let user cancel or modify above settings
+ // Realize potential changes by previous callback
+ if (dndOpts.dragStart(node, data) === false) {
+ // Cancel dragging
+ // dataTransfer.dropEffect = "none";
+ _clearGlobals();
+ return false;
+ }
+ applyDropEffectCallback(event, data);
+
+ // Unless user set `data.useDefaultImage` to false in dragStart,
+ // generata a default drag image now:
+ $extraHelper = null;
+
+ if (data.useDefaultImage) {
+ // Set the title as drag image (otherwise it would contain the expander)
+ $dragImage = $(node.span).find(".fancytree-title");
+
+ if (SOURCE_NODE_LIST && SOURCE_NODE_LIST.length > 1) {
+ // Add a counter badge to node title if dragging more than one node.
+ // We want this, because the element that is used as drag image
+ // must be *visible* in the DOM, so we cannot create some hidden
+ // custom markup.
+ // See https://kryogenix.org/code/browser/custom-drag-image.html
+ // Also, since IE 11 and Edge don't support setDragImage() alltogether,
+ // it gives som feedback to the user.
+ // The badge will be removed later on drag end.
+ $extraHelper = $(
+ "<span class='fancytree-childcounter'/>"
+ )
+ .text("+" + (SOURCE_NODE_LIST.length - 1))
+ .appendTo($dragImage);
+ }
+ if (dataTransfer.setDragImage) {
+ // IE 11 and Edge do not support this
+ dataTransfer.setDragImage($dragImage[0], -10, -10);
+ }
+ }
+ return true;
+
+ case "drag":
+ // Called every few milliseconds (no matter if the
+ // cursor is over a valid drop target)
+ // data.tree.info("drag", SOURCE_NODE)
+ prepareDropEffectCallback(event, data);
+ dndOpts.dragDrag(node, data);
+ applyDropEffectCallback(event, data);
+
+ $sourceList.toggleClass(classDragRemove, data.isMove);
+ break;
+
+ case "dragend":
+ // Called at the end of a d'n'd process (after drop)
+ // Note caveat: If drop removed the dragged source element,
+ // we may not get this event, since the target does not exist
+ // anymore
+ prepareDropEffectCallback(event, data);
+
+ _clearGlobals();
+
+ data.isCancelled = !LAST_HIT_MODE;
+ dndOpts.dragEnd(node, data, !LAST_HIT_MODE);
+ // applyDropEffectCallback(event, data);
+ break;
+ }
+ }
+ /*
+ * Handle dragenter dragover dragleave drop events on the container
+ */
+ function onDropEvent(event) {
+ var json,
+ allowAutoExpand,
+ nodeData,
+ isSourceFtNode,
+ r,
+ res,
+ tree = this,
+ dndOpts = tree.options.dnd5,
+ allowDrop = null,
+ node = FT.getNode(event),
+ dataTransfer =
+ event.dataTransfer || event.originalEvent.dataTransfer,
+ data = {
+ tree: tree,
+ node: node,
+ options: tree.options,
+ originalEvent: event.originalEvent,
+ widget: tree.widget,
+ hitMode: DRAG_ENTER_RESPONSE,
+ dataTransfer: dataTransfer,
+ otherNode: SOURCE_NODE || null,
+ otherNodeList: SOURCE_NODE_LIST || null,
+ otherNodeData: null, // set by drop event
+ useDefaultImage: true,
+ dropEffect: undefined,
+ dropEffectSuggested: undefined,
+ effectAllowed: undefined, // set by dragstart
+ files: null, // list of File objects (may be [])
+ isCancelled: undefined, // set by drop event
+ isMove: undefined,
+ };
+
+ // data.isMove = dropEffect === "move";
+
+ switch (event.type) {
+ case "dragenter":
+ // The dragenter event is fired when a dragged element or
+ // text selection enters a valid drop target.
+
+ DRAG_OVER_STAMP = null;
+ if (!node) {
+ // Sometimes we get dragenter for the container element
+ tree.debug(
+ "Ignore non-node " +
+ event.type +
+ ": " +
+ event.target.tagName +
+ "." +
+ event.target.className
+ );
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ }
+
+ $(node.span)
+ .addClass(classDropOver)
+ .removeClass(classDropAccept + " " + classDropReject);
+
+ // Data is only readable in the dragstart and drop event,
+ // but we can check for the type:
+ isSourceFtNode =
+ $.inArray(nodeMimeType, dataTransfer.types) >= 0;
+
+ if (dndOpts.preventNonNodes && !isSourceFtNode) {
+ node.debug("Reject dropping a non-node.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (
+ dndOpts.preventForeignNodes &&
+ (!SOURCE_NODE || SOURCE_NODE.tree !== node.tree)
+ ) {
+ node.debug("Reject dropping a foreign node.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (
+ dndOpts.preventSameParent &&
+ data.otherNode &&
+ data.otherNode.tree === node.tree &&
+ node.parent === data.otherNode.parent
+ ) {
+ node.debug("Reject dropping as sibling (same parent).");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (
+ dndOpts.preventRecursion &&
+ data.otherNode &&
+ data.otherNode.tree === node.tree &&
+ node.isDescendantOf(data.otherNode)
+ ) {
+ node.debug("Reject dropping below own ancestor.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (dndOpts.preventLazyParents && !node.isLoaded()) {
+ node.warn("Drop over unloaded target node prevented.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ }
+ $dropMarker.show();
+
+ // Call dragEnter() to figure out if (and where) dropping is allowed
+ prepareDropEffectCallback(event, data);
+ r = dndOpts.dragEnter(node, data);
+
+ res = normalizeDragEnterResponse(r);
+ // alert("res:" + JSON.stringify(res))
+ DRAG_ENTER_RESPONSE = res;
+
+ allowDrop = res && (res.over || res.before || res.after);
+
+ applyDropEffectCallback(event, data, allowDrop);
+ break;
+
+ case "dragover":
+ if (!node) {
+ tree.debug(
+ "Ignore non-node " +
+ event.type +
+ ": " +
+ event.target.tagName +
+ "." +
+ event.target.className
+ );
+ break;
+ }
+ // The dragover event is fired when an element or text
+ // selection is being dragged over a valid drop target
+ // (every few hundred milliseconds).
+ // tree.debug(
+ // event.type +
+ // ": dropEffect: " +
+ // dataTransfer.dropEffect
+ // );
+ prepareDropEffectCallback(event, data);
+ LAST_HIT_MODE = handleDragOver(event, data);
+
+ // The flag controls the preventDefault() below:
+ allowDrop = !!LAST_HIT_MODE;
+ allowAutoExpand =
+ LAST_HIT_MODE === "over" || LAST_HIT_MODE === false;
+
+ if (
+ allowAutoExpand &&
+ !node.expanded &&
+ node.hasChildren() !== false
+ ) {
+ if (!DRAG_OVER_STAMP) {
+ DRAG_OVER_STAMP = Date.now();
+ } else if (
+ dndOpts.autoExpandMS &&
+ Date.now() - DRAG_OVER_STAMP > dndOpts.autoExpandMS &&
+ !node.isLoading() &&
+ (!dndOpts.dragExpand ||
+ dndOpts.dragExpand(node, data) !== false)
+ ) {
+ node.setExpanded();
+ }
+ } else {
+ DRAG_OVER_STAMP = null;
+ }
+ break;
+
+ case "dragleave":
+ // NOTE: dragleave is fired AFTER the dragenter event of the
+ // FOLLOWING element.
+ if (!node) {
+ tree.debug(
+ "Ignore non-node " +
+ event.type +
+ ": " +
+ event.target.tagName +
+ "." +
+ event.target.className
+ );
+ break;
+ }
+ if (!$(node.span).hasClass(classDropOver)) {
+ node.debug("Ignore dragleave (multi).");
+ break;
+ }
+ $(node.span).removeClass(
+ classDropOver +
+ " " +
+ classDropAccept +
+ " " +
+ classDropReject
+ );
+ node.scheduleAction("cancel");
+ dndOpts.dragLeave(node, data);
+ $dropMarker.hide();
+ break;
+
+ case "drop":
+ // Data is only readable in the (dragstart and) drop event:
+
+ if ($.inArray(nodeMimeType, dataTransfer.types) >= 0) {
+ nodeData = dataTransfer.getData(nodeMimeType);
+ tree.info(
+ event.type +
+ ": getData('application/x-fancytree-node'): '" +
+ nodeData +
+ "'"
+ );
+ }
+ if (!nodeData) {
+ // 1. Source is not a Fancytree node, or
+ // 2. If the FT mime type was set, but returns '', this
+ // is probably IE 11 (which only supports 'text')
+ nodeData = dataTransfer.getData("text");
+ tree.info(
+ event.type + ": getData('text'): '" + nodeData + "'"
+ );
+ }
+ if (nodeData) {
+ try {
+ // 'text' type may contain JSON if IE is involved
+ // and setTextTypeJson option was set
+ json = JSON.parse(nodeData);
+ if (json.title !== undefined) {
+ data.otherNodeData = json;
+ }
+ } catch (ex) {
+ // assume 'text' type contains plain text, so `otherNodeData`
+ // should not be set
+ }
+ }
+ tree.debug(
+ event.type +
+ ": nodeData: '" +
+ nodeData +
+ "', otherNodeData: ",
+ data.otherNodeData
+ );
+
+ $(node.span).removeClass(
+ classDropOver +
+ " " +
+ classDropAccept +
+ " " +
+ classDropReject
+ );
+
+ // Let user implement the actual drop operation
+ data.hitMode = LAST_HIT_MODE;
+ prepareDropEffectCallback(event, data, !LAST_HIT_MODE);
+ data.isCancelled = !LAST_HIT_MODE;
+
+ var orgSourceElem = SOURCE_NODE && SOURCE_NODE.span,
+ orgSourceTree = SOURCE_NODE && SOURCE_NODE.tree;
+
+ dndOpts.dragDrop(node, data);
+ // applyDropEffectCallback(event, data);
+
+ // Prevent browser's default drop handling, i.e. open as link, ...
+ event.preventDefault();
+
+ if (orgSourceElem && !document.body.contains(orgSourceElem)) {
+ // The drop handler removed the original drag source from
+ // the DOM, so the dragend event will probaly not fire.
+ if (orgSourceTree === tree) {
+ tree.debug(
+ "Drop handler removed source element: generating dragEnd."
+ );
+ dndOpts.dragEnd(SOURCE_NODE, data);
+ } else {
+ tree.warn(
+ "Drop handler removed source element: dragend event may be lost."
+ );
+ }
+ }
+
+ _clearGlobals();
+
+ break;
+ }
+ // Dnd API madness: we must PREVENT default handling to enable dropping
+ if (allowDrop) {
+ event.preventDefault();
+ return false;
+ }
+ }
+
+ /** [ext-dnd5] Return a Fancytree instance, from element, index, event, or jQueryObject.
+ *
+ * @returns {FancytreeNode[]} List of nodes (empty if no drag operation)
+ * @example
+ * $.ui.fancytree.getDragNodeList();
+ *
+ * @alias Fancytree_Static#getDragNodeList
+ * @requires jquery.fancytree.dnd5.js
+ * @since 2.31
+ */
+ $.ui.fancytree.getDragNodeList = function () {
+ return SOURCE_NODE_LIST || [];
+ };
+
+ /** [ext-dnd5] Return the FancytreeNode that is currently being dragged.
+ *
+ * If multiple nodes are dragged, only the first is returned.
+ *
+ * @returns {FancytreeNode | null} dragged nodes or null if no drag operation
+ * @example
+ * $.ui.fancytree.getDragNode();
+ *
+ * @alias Fancytree_Static#getDragNode
+ * @requires jquery.fancytree.dnd5.js
+ * @since 2.31
+ */
+ $.ui.fancytree.getDragNode = function () {
+ return SOURCE_NODE;
+ };
+
+ /******************************************************************************
+ *
+ */
+
+ $.ui.fancytree.registerExtension({
+ name: "dnd5",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ autoExpandMS: 1500, // Expand nodes after n milliseconds of hovering
+ dropMarkerInsertOffsetX: -16, // Additional offset for drop-marker with hitMode = "before"/"after"
+ dropMarkerOffsetX: -24, // Absolute position offset for .fancytree-drop-marker relatively to ..fancytree-title (icon/img near a node accepting drop)
+ // #1021 `document.body` is not available yet
+ dropMarkerParent: "body", // Root Container used for drop marker (could be a shadow root)
+ multiSource: false, // true: Drag multiple (i.e. selected) nodes. Also a callback() is allowed
+ effectAllowed: "all", // Restrict the possible cursor shapes and modifier operations (can also be set in the dragStart event)
+ // dropEffect: "auto", // 'copy'|'link'|'move'|'auto'(calculate from `effectAllowed`+modifier keys) or callback(node, data) that returns such string.
+ dropEffectDefault: "move", // Default dropEffect ('copy', 'link', or 'move') when no modifier is pressed (overide in dragDrag, dragOver).
+ preventForeignNodes: false, // Prevent dropping nodes from different Fancytrees
+ preventLazyParents: true, // Prevent dropping items on unloaded lazy Fancytree nodes
+ preventNonNodes: false, // Prevent dropping items other than Fancytree nodes
+ preventRecursion: true, // Prevent dropping nodes on own descendants
+ preventSameParent: false, // Prevent dropping nodes under same direct parent
+ preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
+ scroll: true, // Enable auto-scrolling while dragging
+ scrollSensitivity: 20, // Active top/bottom margin in pixel
+ scrollSpeed: 5, // Pixel per event
+ setTextTypeJson: false, // Allow dragging of nodes to different IE windows
+ sourceCopyHook: null, // Optional callback passed to `toDict` on dragStart @since 2.38
+ // Events (drag support)
+ dragStart: null, // Callback(sourceNode, data), return true, to enable dnd drag
+ dragDrag: $.noop, // Callback(sourceNode, data)
+ dragEnd: $.noop, // Callback(sourceNode, data)
+ // Events (drop support)
+ dragEnter: null, // Callback(targetNode, data), return true, to enable dnd drop
+ dragOver: $.noop, // Callback(targetNode, data)
+ dragExpand: $.noop, // Callback(targetNode, data), return false to prevent autoExpand
+ dragDrop: $.noop, // Callback(targetNode, data)
+ dragLeave: $.noop, // Callback(targetNode, data)
+ },
+
+ treeInit: function (ctx) {
+ var $temp,
+ tree = ctx.tree,
+ opts = ctx.options,
+ glyph = opts.glyph || null,
+ dndOpts = opts.dnd5;
+
+ if ($.inArray("dnd", opts.extensions) >= 0) {
+ $.error("Extensions 'dnd' and 'dnd5' are mutually exclusive.");
+ }
+ if (dndOpts.dragStop) {
+ $.error(
+ "dragStop is not used by ext-dnd5. Use dragEnd instead."
+ );
+ }
+ if (dndOpts.preventRecursiveMoves != null) {
+ $.error(
+ "preventRecursiveMoves was renamed to preventRecursion."
+ );
+ }
+
+ // Implement `opts.createNode` event to add the 'draggable' attribute
+ // #680: this must happen before calling super.treeInit()
+ if (dndOpts.dragStart) {
+ FT.overrideMethod(
+ ctx.options,
+ "createNode",
+ function (event, data) {
+ // Default processing if any
+ this._super.apply(this, arguments);
+ if (data.node.span) {
+ data.node.span.draggable = true;
+ } else {
+ data.node.warn(
+ "Cannot add `draggable`: no span tag"
+ );
+ }
+ }
+ );
+ }
+ this._superApply(arguments);
+
+ this.$container.addClass("fancytree-ext-dnd5");
+
+ // Store the current scroll parent, which may be the tree
+ // container, any enclosing div, or the document.
+ // #761: scrollParent() always needs a container child
+ $temp = $("<span>").appendTo(this.$container);
+ this.$scrollParent = $temp.scrollParent();
+ $temp.remove();
+
+ $dropMarker = $("#fancytree-drop-marker");
+ if (!$dropMarker.length) {
+ $dropMarker = $("<div id='fancytree-drop-marker'></div>")
+ .hide()
+ .css({
+ "z-index": 1000,
+ // Drop marker should not steal dragenter/dragover events:
+ "pointer-events": "none",
+ })
+ .prependTo(dndOpts.dropMarkerParent);
+ if (glyph) {
+ FT.setSpanIcon(
+ $dropMarker[0],
+ glyph.map._addClass,
+ glyph.map.dropMarker
+ );
+ }
+ }
+ $dropMarker.toggleClass("fancytree-rtl", !!opts.rtl);
+
+ // Enable drag support if dragStart() is specified:
+ if (dndOpts.dragStart) {
+ // Bind drag event handlers
+ tree.$container.on(
+ "dragstart drag dragend",
+ onDragEvent.bind(tree)
+ );
+ }
+ // Enable drop support if dragEnter() is specified:
+ if (dndOpts.dragEnter) {
+ // Bind drop event handlers
+ tree.$container.on(
+ "dragenter dragover dragleave drop",
+ onDropEvent.bind(tree)
+ );
+ }
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.edit.js
+ *
+ * Make node titles editable.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ var isMac = /Mac/.test(navigator.platform),
+ escapeHtml = $.ui.fancytree.escapeHtml,
+ trim = $.ui.fancytree.trim,
+ unescapeHtml = $.ui.fancytree.unescapeHtml;
+
+ /**
+ * [ext-edit] Start inline editing of current node title.
+ *
+ * @alias FancytreeNode#editStart
+ * @requires Fancytree
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.editStart = function () {
+ var $input,
+ node = this,
+ tree = this.tree,
+ local = tree.ext.edit,
+ instOpts = tree.options.edit,
+ $title = $(".fancytree-title", node.span),
+ eventData = {
+ node: node,
+ tree: tree,
+ options: tree.options,
+ isNew: $(node[tree.statusClassPropName]).hasClass(
+ "fancytree-edit-new"
+ ),
+ orgTitle: node.title,
+ input: null,
+ dirty: false,
+ };
+
+ // beforeEdit may want to modify the title before editing
+ if (
+ instOpts.beforeEdit.call(
+ node,
+ { type: "beforeEdit" },
+ eventData
+ ) === false
+ ) {
+ return false;
+ }
+ $.ui.fancytree.assert(!local.currentNode, "recursive edit");
+ local.currentNode = this;
+ local.eventData = eventData;
+
+ // Disable standard Fancytree mouse- and key handling
+ tree.widget._unbind();
+
+ local.lastDraggableAttrValue = node.span.draggable;
+ if (local.lastDraggableAttrValue) {
+ node.span.draggable = false;
+ }
+
+ // #116: ext-dnd prevents the blur event, so we have to catch outer clicks
+ $(document).on("mousedown.fancytree-edit", function (event) {
+ if (!$(event.target).hasClass("fancytree-edit-input")) {
+ node.editEnd(true, event);
+ }
+ });
+
+ // Replace node with <input>
+ $input = $("<input />", {
+ class: "fancytree-edit-input",
+ type: "text",
+ value: tree.options.escapeTitles
+ ? eventData.orgTitle
+ : unescapeHtml(eventData.orgTitle),
+ });
+ local.eventData.input = $input;
+ if (instOpts.adjustWidthOfs != null) {
+ $input.width($title.width() + instOpts.adjustWidthOfs);
+ }
+ if (instOpts.inputCss != null) {
+ $input.css(instOpts.inputCss);
+ }
+
+ $title.html($input);
+
+ // Focus <input> and bind keyboard handler
+ $input
+ .focus()
+ .change(function (event) {
+ $input.addClass("fancytree-edit-dirty");
+ })
+ .on("keydown", function (event) {
+ switch (event.which) {
+ case $.ui.keyCode.ESCAPE:
+ node.editEnd(false, event);
+ break;
+ case $.ui.keyCode.ENTER:
+ node.editEnd(true, event);
+ return false; // so we don't start editmode on Mac
+ }
+ event.stopPropagation();
+ })
+ .blur(function (event) {
+ return node.editEnd(true, event);
+ });
+
+ instOpts.edit.call(node, { type: "edit" }, eventData);
+ };
+
+ /**
+ * [ext-edit] Stop inline editing.
+ * @param {Boolean} [applyChanges=false] false: cancel edit, true: save (if modified)
+ * @alias FancytreeNode#editEnd
+ * @requires jquery.fancytree.edit.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.editEnd = function (
+ applyChanges,
+ _event
+ ) {
+ var newVal,
+ node = this,
+ tree = this.tree,
+ local = tree.ext.edit,
+ eventData = local.eventData,
+ instOpts = tree.options.edit,
+ $title = $(".fancytree-title", node.span),
+ $input = $title.find("input.fancytree-edit-input");
+
+ if (instOpts.trim) {
+ $input.val(trim($input.val()));
+ }
+ newVal = $input.val();
+
+ eventData.dirty = newVal !== node.title;
+ eventData.originalEvent = _event;
+
+ // Find out, if saving is required
+ if (applyChanges === false) {
+ // If true/false was passed, honor this (except in rename mode, if unchanged)
+ eventData.save = false;
+ } else if (eventData.isNew) {
+ // In create mode, we save everything, except for empty text
+ eventData.save = newVal !== "";
+ } else {
+ // In rename mode, we save everyting, except for empty or unchanged text
+ eventData.save = eventData.dirty && newVal !== "";
+ }
+ // Allow to break (keep editor open), modify input, or re-define data.save
+ if (
+ instOpts.beforeClose.call(
+ node,
+ { type: "beforeClose" },
+ eventData
+ ) === false
+ ) {
+ return false;
+ }
+ if (
+ eventData.save &&
+ instOpts.save.call(node, { type: "save" }, eventData) === false
+ ) {
+ return false;
+ }
+ $input.removeClass("fancytree-edit-dirty").off();
+ // Unbind outer-click handler
+ $(document).off(".fancytree-edit");
+
+ if (eventData.save) {
+ // # 171: escape user input (not required if global escaping is on)
+ node.setTitle(
+ tree.options.escapeTitles ? newVal : escapeHtml(newVal)
+ );
+ node.setFocus();
+ } else {
+ if (eventData.isNew) {
+ node.remove();
+ node = eventData.node = null;
+ local.relatedNode.setFocus();
+ } else {
+ node.renderTitle();
+ node.setFocus();
+ }
+ }
+ local.eventData = null;
+ local.currentNode = null;
+ local.relatedNode = null;
+ // Re-enable mouse and keyboard handling
+ tree.widget._bind();
+
+ if (node && local.lastDraggableAttrValue) {
+ node.span.draggable = true;
+ }
+
+ // Set keyboard focus, even if setFocus() claims 'nothing to do'
+ tree.$container.get(0).focus({ preventScroll: true });
+ eventData.input = null;
+ instOpts.close.call(node, { type: "close" }, eventData);
+ return true;
+ };
+
+ /**
+ * [ext-edit] Create a new child or sibling node and start edit mode.
+ *
+ * @param {String} [mode='child'] 'before', 'after', or 'child'
+ * @param {Object} [init] NodeData (or simple title string)
+ * @alias FancytreeNode#editCreateNode
+ * @requires jquery.fancytree.edit.js
+ * @since 2.4
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode = function (
+ mode,
+ init
+ ) {
+ var newNode,
+ tree = this.tree,
+ self = this;
+
+ mode = mode || "child";
+ if (init == null) {
+ init = { title: "" };
+ } else if (typeof init === "string") {
+ init = { title: init };
+ } else {
+ $.ui.fancytree.assert($.isPlainObject(init));
+ }
+ // Make sure node is expanded (and loaded) in 'child' mode
+ if (
+ mode === "child" &&
+ !this.isExpanded() &&
+ this.hasChildren() !== false
+ ) {
+ this.setExpanded().done(function () {
+ self.editCreateNode(mode, init);
+ });
+ return;
+ }
+ newNode = this.addNode(init, mode);
+
+ // #644: Don't filter new nodes.
+ newNode.match = true;
+ $(newNode[tree.statusClassPropName])
+ .removeClass("fancytree-hide")
+ .addClass("fancytree-match");
+
+ newNode.makeVisible(/*{noAnimation: true}*/).done(function () {
+ $(newNode[tree.statusClassPropName]).addClass("fancytree-edit-new");
+ self.tree.ext.edit.relatedNode = self;
+ newNode.editStart();
+ });
+ };
+
+ /**
+ * [ext-edit] Check if any node in this tree in edit mode.
+ *
+ * @returns {FancytreeNode | null}
+ * @alias Fancytree#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.isEditing = function () {
+ return this.ext.edit ? this.ext.edit.currentNode : null;
+ };
+
+ /**
+ * [ext-edit] Check if this node is in edit mode.
+ * @returns {Boolean} true if node is currently beeing edited
+ * @alias FancytreeNode#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.isEditing = function () {
+ return this.tree.ext.edit
+ ? this.tree.ext.edit.currentNode === this
+ : false;
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "edit",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ adjustWidthOfs: 4, // null: don't adjust input size to content
+ allowEmpty: false, // Prevent empty input
+ inputCss: { minWidth: "3em" },
+ // triggerCancel: ["esc", "tab", "click"],
+ triggerStart: ["f2", "mac+enter", "shift+click"],
+ trim: true, // Trim whitespace before save
+ // Events:
+ beforeClose: $.noop, // Return false to prevent cancel/save (data.input is available)
+ beforeEdit: $.noop, // Return false to prevent edit mode
+ close: $.noop, // Editor was removed
+ edit: $.noop, // Editor was opened (available as data.input)
+ // keypress: $.noop, // Not yet implemented
+ save: $.noop, // Save data.input.val() or return false to keep editor open
+ },
+ // Local attributes
+ currentNode: null,
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree;
+
+ this._superApply(arguments);
+
+ this.$container
+ .addClass("fancytree-ext-edit")
+ .on("fancytreebeforeupdateviewport", function (event, data) {
+ var editNode = tree.isEditing();
+ // When scrolling, the TR may be re-used by another node, so the
+ // active cell marker an
+ if (editNode) {
+ editNode.info("Cancel edit due to scroll event.");
+ editNode.editEnd(false, event);
+ }
+ });
+ },
+ nodeClick: function (ctx) {
+ var eventStr = $.ui.fancytree.eventToString(ctx.originalEvent),
+ triggerStart = ctx.options.edit.triggerStart;
+
+ if (
+ eventStr === "shift+click" &&
+ $.inArray("shift+click", triggerStart) >= 0
+ ) {
+ if (ctx.originalEvent.shiftKey) {
+ ctx.node.editStart();
+ return false;
+ }
+ }
+ if (
+ eventStr === "click" &&
+ $.inArray("clickActive", triggerStart) >= 0
+ ) {
+ // Only when click was inside title text (not aynwhere else in the row)
+ if (
+ ctx.node.isActive() &&
+ !ctx.node.isEditing() &&
+ $(ctx.originalEvent.target).hasClass("fancytree-title")
+ ) {
+ ctx.node.editStart();
+ return false;
+ }
+ }
+ return this._superApply(arguments);
+ },
+ nodeDblclick: function (ctx) {
+ if ($.inArray("dblclick", ctx.options.edit.triggerStart) >= 0) {
+ ctx.node.editStart();
+ return false;
+ }
+ return this._superApply(arguments);
+ },
+ nodeKeydown: function (ctx) {
+ switch (ctx.originalEvent.which) {
+ case 113: // [F2]
+ if ($.inArray("f2", ctx.options.edit.triggerStart) >= 0) {
+ ctx.node.editStart();
+ return false;
+ }
+ break;
+ case $.ui.keyCode.ENTER:
+ if (
+ $.inArray("mac+enter", ctx.options.edit.triggerStart) >=
+ 0 &&
+ isMac
+ ) {
+ ctx.node.editStart();
+ return false;
+ }
+ break;
+ }
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.filter.js
+ *
+ * Remove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ var KeyNoData = "__not_found__",
+ escapeHtml = $.ui.fancytree.escapeHtml,
+ exoticStartChar = "\uFFF7",
+ exoticEndChar = "\uFFF8";
+ function _escapeRegex(str) {
+ return (str + "").replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
+ }
+
+ function extractHtmlText(s) {
+ if (s.indexOf(">") >= 0) {
+ return $("<div/>").html(s).text();
+ }
+ return s;
+ }
+
+ /**
+ * @description Marks the matching charecters of `text` either by `mark` or
+ * by exotic*Chars (if `escapeTitles` is `true`) based on `regexMatchArray`
+ * which is an array of matching groups.
+ * @param {string} text
+ * @param {RegExpMatchArray} regexMatchArray
+ */
+ function _markFuzzyMatchedChars(text, regexMatchArray, escapeTitles) {
+ // It is extremely infuriating that we can not use `let` or `const` or arrow functions.
+ // Damn you IE!!!
+ var matchingIndices = [];
+ // get the indices of matched characters (Iterate through `RegExpMatchArray`)
+ for (
+ var _matchingArrIdx = 1;
+ _matchingArrIdx < regexMatchArray.length;
+ _matchingArrIdx++
+ ) {
+ var _mIdx =
+ // get matching char index by cumulatively adding
+ // the matched group length
+ regexMatchArray[_matchingArrIdx].length +
+ (_matchingArrIdx === 1 ? 0 : 1) +
+ (matchingIndices[matchingIndices.length - 1] || 0);
+ matchingIndices.push(_mIdx);
+ }
+ // Map each `text` char to its position and store in `textPoses`.
+ var textPoses = text.split("");
+ if (escapeTitles) {
+ // If escaping the title, then wrap the matchng char within exotic chars
+ matchingIndices.forEach(function (v) {
+ textPoses[v] = exoticStartChar + textPoses[v] + exoticEndChar;
+ });
+ } else {
+ // Otherwise, Wrap the matching chars within `mark`.
+ matchingIndices.forEach(function (v) {
+ textPoses[v] = "<mark>" + textPoses[v] + "</mark>";
+ });
+ }
+ // Join back the modified `textPoses` to create final highlight markup.
+ return textPoses.join("");
+ }
+ $.ui.fancytree._FancytreeClass.prototype._applyFilterImpl = function (
+ filter,
+ branchMode,
+ _opts
+ ) {
+ var match,
+ statusNode,
+ re,
+ reHighlight,
+ reExoticStartChar,
+ reExoticEndChar,
+ temp,
+ prevEnableUpdate,
+ count = 0,
+ treeOpts = this.options,
+ escapeTitles = treeOpts.escapeTitles,
+ prevAutoCollapse = treeOpts.autoCollapse,
+ opts = $.extend({}, treeOpts.filter, _opts),
+ hideMode = opts.mode === "hide",
+ leavesOnly = !!opts.leavesOnly && !branchMode;
+
+ // Default to 'match title substring (not case sensitive)'
+ if (typeof filter === "string") {
+ if (filter === "") {
+ this.warn(
+ "Fancytree passing an empty string as a filter is handled as clearFilter()."
+ );
+ this.clearFilter();
+ return;
+ }
+ if (opts.fuzzy) {
+ // See https://codereview.stackexchange.com/questions/23899/faster-javascript-fuzzy-string-matching-function/23905#23905
+ // and http://www.quora.com/How-is-the-fuzzy-search-algorithm-in-Sublime-Text-designed
+ // and http://www.dustindiaz.com/autocomplete-fuzzy-matching
+ match = filter
+ .split("")
+ // Escaping the `filter` will not work because,
+ // it gets further split into individual characters. So,
+ // escape each character after splitting
+ .map(_escapeRegex)
+ .reduce(function (a, b) {
+ // create capture groups for parts that comes before
+ // the character
+ return a + "([^" + b + "]*)" + b;
+ }, "");
+ } else {
+ match = _escapeRegex(filter); // make sure a '.' is treated literally
+ }
+ re = new RegExp(match, "i");
+ reHighlight = new RegExp(_escapeRegex(filter), "gi");
+ if (escapeTitles) {
+ reExoticStartChar = new RegExp(
+ _escapeRegex(exoticStartChar),
+ "g"
+ );
+ reExoticEndChar = new RegExp(_escapeRegex(exoticEndChar), "g");
+ }
+ filter = function (node) {
+ if (!node.title) {
+ return false;
+ }
+ var text = escapeTitles
+ ? node.title
+ : extractHtmlText(node.title),
+ // `.match` instead of `.test` to get the capture groups
+ res = text.match(re);
+ if (res && opts.highlight) {
+ if (escapeTitles) {
+ if (opts.fuzzy) {
+ temp = _markFuzzyMatchedChars(
+ text,
+ res,
+ escapeTitles
+ );
+ } else {
+ // #740: we must not apply the marks to escaped entity names, e.g. `&quot;`
+ // Use some exotic characters to mark matches:
+ temp = text.replace(reHighlight, function (s) {
+ return exoticStartChar + s + exoticEndChar;
+ });
+ }
+ // now we can escape the title...
+ node.titleWithHighlight = escapeHtml(temp)
+ // ... and finally insert the desired `<mark>` tags
+ .replace(reExoticStartChar, "<mark>")
+ .replace(reExoticEndChar, "</mark>");
+ } else {
+ if (opts.fuzzy) {
+ node.titleWithHighlight = _markFuzzyMatchedChars(
+ text,
+ res
+ );
+ } else {
+ node.titleWithHighlight = text.replace(
+ reHighlight,
+ function (s) {
+ return "<mark>" + s + "</mark>";
+ }
+ );
+ }
+ }
+ // node.debug("filter", escapeTitles, text, node.titleWithHighlight);
+ }
+ return !!res;
+ };
+ }
+
+ this.enableFilter = true;
+ this.lastFilterArgs = arguments;
+
+ prevEnableUpdate = this.enableUpdate(false);
+
+ this.$div.addClass("fancytree-ext-filter");
+ if (hideMode) {
+ this.$div.addClass("fancytree-ext-filter-hide");
+ } else {
+ this.$div.addClass("fancytree-ext-filter-dimm");
+ }
+ this.$div.toggleClass(
+ "fancytree-ext-filter-hide-expanders",
+ !!opts.hideExpanders
+ );
+ // Reset current filter
+ this.rootNode.subMatchCount = 0;
+ this.visit(function (node) {
+ delete node.match;
+ delete node.titleWithHighlight;
+ node.subMatchCount = 0;
+ });
+ statusNode = this.getRootNode()._findDirectChild(KeyNoData);
+ if (statusNode) {
+ statusNode.remove();
+ }
+
+ // Adjust node.hide, .match, and .subMatchCount properties
+ treeOpts.autoCollapse = false; // #528
+
+ this.visit(function (node) {
+ if (leavesOnly && node.children != null) {
+ return;
+ }
+ var res = filter(node),
+ matchedByBranch = false;
+
+ if (res === "skip") {
+ node.visit(function (c) {
+ c.match = false;
+ }, true);
+ return "skip";
+ }
+ if (!res && (branchMode || res === "branch") && node.parent.match) {
+ res = true;
+ matchedByBranch = true;
+ }
+ if (res) {
+ count++;
+ node.match = true;
+ node.visitParents(function (p) {
+ if (p !== node) {
+ p.subMatchCount += 1;
+ }
+ // Expand match (unless this is no real match, but only a node in a matched branch)
+ if (opts.autoExpand && !matchedByBranch && !p.expanded) {
+ p.setExpanded(true, {
+ noAnimation: true,
+ noEvents: true,
+ scrollIntoView: false,
+ });
+ p._filterAutoExpanded = true;
+ }
+ }, true);
+ }
+ });
+ treeOpts.autoCollapse = prevAutoCollapse;
+
+ if (count === 0 && opts.nodata && hideMode) {
+ statusNode = opts.nodata;
+ if (typeof statusNode === "function") {
+ statusNode = statusNode();
+ }
+ if (statusNode === true) {
+ statusNode = {};
+ } else if (typeof statusNode === "string") {
+ statusNode = { title: statusNode };
+ }
+ statusNode = $.extend(
+ {
+ statusNodeType: "nodata",
+ key: KeyNoData,
+ title: this.options.strings.noData,
+ },
+ statusNode
+ );
+
+ this.getRootNode().addNode(statusNode).match = true;
+ }
+ // Redraw whole tree
+ this._callHook("treeStructureChanged", this, "applyFilter");
+ // this.render();
+ this.enableUpdate(prevEnableUpdate);
+ return count;
+ };
+
+ /**
+ * [ext-filter] Dimm or hide nodes.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false, leavesOnly: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterNodes
+ * @requires jquery.fancytree.filter.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.filterNodes = function (
+ filter,
+ opts
+ ) {
+ if (typeof opts === "boolean") {
+ opts = { leavesOnly: opts };
+ this.warn(
+ "Fancytree.filterNodes() leavesOnly option is deprecated since 2.9.0 / 2015-04-19. Use opts.leavesOnly instead."
+ );
+ }
+ return this._applyFilterImpl(filter, false, opts);
+ };
+
+ /**
+ * [ext-filter] Dimm or hide whole branches.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterBranches
+ * @requires jquery.fancytree.filter.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.filterBranches = function (
+ filter,
+ opts
+ ) {
+ return this._applyFilterImpl(filter, true, opts);
+ };
+
+ /**
+ * [ext-filter] Re-apply current filter.
+ *
+ * @returns {integer} count
+ * @alias Fancytree#updateFilter
+ * @requires jquery.fancytree.filter.js
+ * @since 2.38
+ */
+ $.ui.fancytree._FancytreeClass.prototype.updateFilter = function () {
+ if (
+ this.enableFilter &&
+ this.lastFilterArgs &&
+ this.options.filter.autoApply
+ ) {
+ this._applyFilterImpl.apply(this, this.lastFilterArgs);
+ } else {
+ this.warn("updateFilter(): no filter active.");
+ }
+ };
+
+ /**
+ * [ext-filter] Reset the filter.
+ *
+ * @alias Fancytree#clearFilter
+ * @requires jquery.fancytree.filter.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.clearFilter = function () {
+ var $title,
+ statusNode = this.getRootNode()._findDirectChild(KeyNoData),
+ escapeTitles = this.options.escapeTitles,
+ enhanceTitle = this.options.enhanceTitle,
+ prevEnableUpdate = this.enableUpdate(false);
+
+ if (statusNode) {
+ statusNode.remove();
+ }
+ // we also counted root node's subMatchCount
+ delete this.rootNode.match;
+ delete this.rootNode.subMatchCount;
+
+ this.visit(function (node) {
+ if (node.match && node.span) {
+ // #491, #601
+ $title = $(node.span).find(">span.fancytree-title");
+ if (escapeTitles) {
+ $title.text(node.title);
+ } else {
+ $title.html(node.title);
+ }
+ if (enhanceTitle) {
+ enhanceTitle(
+ { type: "enhanceTitle" },
+ { node: node, $title: $title }
+ );
+ }
+ }
+ delete node.match;
+ delete node.subMatchCount;
+ delete node.titleWithHighlight;
+ if (node.$subMatchBadge) {
+ node.$subMatchBadge.remove();
+ delete node.$subMatchBadge;
+ }
+ if (node._filterAutoExpanded && node.expanded) {
+ node.setExpanded(false, {
+ noAnimation: true,
+ noEvents: true,
+ scrollIntoView: false,
+ });
+ }
+ delete node._filterAutoExpanded;
+ });
+ this.enableFilter = false;
+ this.lastFilterArgs = null;
+ this.$div.removeClass(
+ "fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide"
+ );
+ this._callHook("treeStructureChanged", this, "clearFilter");
+ // this.render();
+ this.enableUpdate(prevEnableUpdate);
+ };
+
+ /**
+ * [ext-filter] Return true if a filter is currently applied.
+ *
+ * @returns {Boolean}
+ * @alias Fancytree#isFilterActive
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+ $.ui.fancytree._FancytreeClass.prototype.isFilterActive = function () {
+ return !!this.enableFilter;
+ };
+
+ /**
+ * [ext-filter] Return true if this node is matched by current filter (or no filter is active).
+ *
+ * @returns {Boolean}
+ * @alias FancytreeNode#isMatched
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.isMatched = function () {
+ return !(this.tree.enableFilter && !this.match);
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "filter",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ autoApply: true, // Re-apply last filter if lazy data is loaded
+ autoExpand: false, // Expand all branches that contain matches while filtered
+ counter: true, // Show a badge with number of matching child nodes near parent icons
+ fuzzy: false, // Match single characters in order, e.g. 'fb' will match 'FooBar'
+ hideExpandedCounter: true, // Hide counter badge if parent is expanded
+ hideExpanders: false, // Hide expanders if all child nodes are hidden by filter
+ highlight: true, // Highlight matches by wrapping inside <mark> tags
+ leavesOnly: false, // Match end nodes only
+ nodata: true, // Display a 'no data' status node if result is empty
+ mode: "dimm", // Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
+ },
+ nodeLoadChildren: function (ctx, source) {
+ var tree = ctx.tree;
+
+ return this._superApply(arguments).done(function () {
+ if (
+ tree.enableFilter &&
+ tree.lastFilterArgs &&
+ ctx.options.filter.autoApply
+ ) {
+ tree._applyFilterImpl.apply(tree, tree.lastFilterArgs);
+ }
+ });
+ },
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var node = ctx.node;
+
+ delete node._filterAutoExpanded;
+ // Make sure counter badge is displayed again, when node is beeing collapsed
+ if (
+ !flag &&
+ ctx.options.filter.hideExpandedCounter &&
+ node.$subMatchBadge
+ ) {
+ node.$subMatchBadge.show();
+ }
+ return this._superApply(arguments);
+ },
+ nodeRenderStatus: function (ctx) {
+ // Set classes for current status
+ var res,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options.filter,
+ $title = $(node.span).find("span.fancytree-title"),
+ $span = $(node[tree.statusClassPropName]),
+ enhanceTitle = ctx.options.enhanceTitle,
+ escapeTitles = ctx.options.escapeTitles;
+
+ res = this._super(ctx);
+ // nothing to do, if node was not yet rendered
+ if (!$span.length || !tree.enableFilter) {
+ return res;
+ }
+ $span
+ .toggleClass("fancytree-match", !!node.match)
+ .toggleClass("fancytree-submatch", !!node.subMatchCount)
+ .toggleClass(
+ "fancytree-hide",
+ !(node.match || node.subMatchCount)
+ );
+ // Add/update counter badge
+ if (
+ opts.counter &&
+ node.subMatchCount &&
+ (!node.isExpanded() || !opts.hideExpandedCounter)
+ ) {
+ if (!node.$subMatchBadge) {
+ node.$subMatchBadge = $(
+ "<span class='fancytree-childcounter'/>"
+ );
+ $(
+ "span.fancytree-icon, span.fancytree-custom-icon",
+ node.span
+ ).append(node.$subMatchBadge);
+ }
+ node.$subMatchBadge.show().text(node.subMatchCount);
+ } else if (node.$subMatchBadge) {
+ node.$subMatchBadge.hide();
+ }
+ // node.debug("nodeRenderStatus", node.titleWithHighlight, node.title)
+ // #601: also check for $title.length, because we don't need to render
+ // if node.span is null (i.e. not rendered)
+ if (node.span && (!node.isEditing || !node.isEditing.call(node))) {
+ if (node.titleWithHighlight) {
+ $title.html(node.titleWithHighlight);
+ } else if (escapeTitles) {
+ $title.text(node.title);
+ } else {
+ $title.html(node.title);
+ }
+ if (enhanceTitle) {
+ enhanceTitle(
+ { type: "enhanceTitle" },
+ { node: node, $title: $title }
+ );
+ }
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.glyph.js
+ *
+ * Use glyph-fonts, ligature-fonts, or SVG icons instead of icon sprites.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+
+ var FT = $.ui.fancytree,
+ PRESETS = {
+ awesome3: {
+ // Outdated!
+ _addClass: "",
+ checkbox: "icon-check-empty",
+ checkboxSelected: "icon-check",
+ checkboxUnknown: "icon-check icon-muted",
+ dragHelper: "icon-caret-right",
+ dropMarker: "icon-caret-right",
+ error: "icon-exclamation-sign",
+ expanderClosed: "icon-caret-right",
+ expanderLazy: "icon-angle-right",
+ expanderOpen: "icon-caret-down",
+ loading: "icon-refresh icon-spin",
+ nodata: "icon-meh",
+ noExpander: "",
+ radio: "icon-circle-blank",
+ radioSelected: "icon-circle",
+ // radioUnknown: "icon-circle icon-muted",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "icon-file-alt",
+ docOpen: "icon-file-alt",
+ folder: "icon-folder-close-alt",
+ folderOpen: "icon-folder-open-alt",
+ },
+ awesome4: {
+ _addClass: "fa",
+ checkbox: "fa-square-o",
+ checkboxSelected: "fa-check-square-o",
+ checkboxUnknown: "fa-square fancytree-helper-indeterminate-cb",
+ dragHelper: "fa-arrow-right",
+ dropMarker: "fa-long-arrow-right",
+ error: "fa-warning",
+ expanderClosed: "fa-caret-right",
+ expanderLazy: "fa-angle-right",
+ expanderOpen: "fa-caret-down",
+ // We may prevent wobbling rotations on FF by creating a separate sub element:
+ loading: { html: "<span class='fa fa-spinner fa-pulse' />" },
+ nodata: "fa-meh-o",
+ noExpander: "",
+ radio: "fa-circle-thin", // "fa-circle-o"
+ radioSelected: "fa-circle",
+ // radioUnknown: "fa-dot-circle-o",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "fa-file-o",
+ docOpen: "fa-file-o",
+ folder: "fa-folder-o",
+ folderOpen: "fa-folder-open-o",
+ },
+ awesome5: {
+ // fontawesome 5 have several different base classes
+ // "far, fas, fal and fab" The rendered svg puts that prefix
+ // in a different location so we have to keep them separate here
+ _addClass: "",
+ checkbox: "far fa-square",
+ checkboxSelected: "far fa-check-square",
+ // checkboxUnknown: "far fa-window-close",
+ checkboxUnknown:
+ "fas fa-square fancytree-helper-indeterminate-cb",
+ radio: "far fa-circle",
+ radioSelected: "fas fa-circle",
+ radioUnknown: "far fa-dot-circle",
+ dragHelper: "fas fa-arrow-right",
+ dropMarker: "fas fa-long-arrow-alt-right",
+ error: "fas fa-exclamation-triangle",
+ expanderClosed: "fas fa-caret-right",
+ expanderLazy: "fas fa-angle-right",
+ expanderOpen: "fas fa-caret-down",
+ loading: "fas fa-spinner fa-pulse",
+ nodata: "far fa-meh",
+ noExpander: "",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "far fa-file",
+ docOpen: "far fa-file",
+ folder: "far fa-folder",
+ folderOpen: "far fa-folder-open",
+ },
+ bootstrap3: {
+ _addClass: "glyphicon",
+ checkbox: "glyphicon-unchecked",
+ checkboxSelected: "glyphicon-check",
+ checkboxUnknown:
+ "glyphicon-expand fancytree-helper-indeterminate-cb", // "glyphicon-share",
+ dragHelper: "glyphicon-play",
+ dropMarker: "glyphicon-arrow-right",
+ error: "glyphicon-warning-sign",
+ expanderClosed: "glyphicon-menu-right", // glyphicon-plus-sign
+ expanderLazy: "glyphicon-menu-right", // glyphicon-plus-sign
+ expanderOpen: "glyphicon-menu-down", // glyphicon-minus-sign
+ loading: "glyphicon-refresh fancytree-helper-spin",
+ nodata: "glyphicon-info-sign",
+ noExpander: "",
+ radio: "glyphicon-remove-circle", // "glyphicon-unchecked",
+ radioSelected: "glyphicon-ok-circle", // "glyphicon-check",
+ // radioUnknown: "glyphicon-ban-circle",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "glyphicon-file",
+ docOpen: "glyphicon-file",
+ folder: "glyphicon-folder-close",
+ folderOpen: "glyphicon-folder-open",
+ },
+ material: {
+ _addClass: "material-icons",
+ checkbox: { text: "check_box_outline_blank" },
+ checkboxSelected: { text: "check_box" },
+ checkboxUnknown: { text: "indeterminate_check_box" },
+ dragHelper: { text: "play_arrow" },
+ dropMarker: { text: "arrow-forward" },
+ error: { text: "warning" },
+ expanderClosed: { text: "chevron_right" },
+ expanderLazy: { text: "last_page" },
+ expanderOpen: { text: "expand_more" },
+ loading: {
+ text: "autorenew",
+ addClass: "fancytree-helper-spin",
+ },
+ nodata: { text: "info" },
+ noExpander: { text: "" },
+ radio: { text: "radio_button_unchecked" },
+ radioSelected: { text: "radio_button_checked" },
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: { text: "insert_drive_file" },
+ docOpen: { text: "insert_drive_file" },
+ folder: { text: "folder" },
+ folderOpen: { text: "folder_open" },
+ },
+ };
+
+ function setIcon(node, span, baseClass, opts, type) {
+ var map = opts.map,
+ icon = map[type],
+ $span = $(span),
+ $counter = $span.find(".fancytree-childcounter"),
+ setClass = baseClass + " " + (map._addClass || "");
+
+ // #871 Allow a callback
+ if (typeof icon === "function") {
+ icon = icon.call(this, node, span, type);
+ }
+ // node.debug( "setIcon(" + baseClass + ", " + type + "): " + "oldIcon" + " -> " + icon );
+ // #871: propsed this, but I am not sure how robust this is, e.g.
+ // the prefix (fas, far) class changes are not considered?
+ // if (span.tagName === "svg" && opts.preset === "awesome5") {
+ // // fa5 script converts <i> to <svg> so call a specific handler.
+ // var oldIcon = "fa-" + $span.data("icon");
+ // // node.debug( "setIcon(" + baseClass + ", " + type + "): " + oldIcon + " -> " + icon );
+ // if (typeof oldIcon === "string") {
+ // $span.removeClass(oldIcon);
+ // }
+ // if (typeof icon === "string") {
+ // $span.addClass(icon);
+ // }
+ // return;
+ // }
+ if (typeof icon === "string") {
+ // #883: remove inner html that may be added by prev. mode
+ span.innerHTML = "";
+ $span.attr("class", setClass + " " + icon).append($counter);
+ } else if (icon) {
+ if (icon.text) {
+ span.textContent = "" + icon.text;
+ } else if (icon.html) {
+ span.innerHTML = icon.html;
+ } else {
+ span.innerHTML = "";
+ }
+ $span
+ .attr("class", setClass + " " + (icon.addClass || ""))
+ .append($counter);
+ }
+ }
+
+ $.ui.fancytree.registerExtension({
+ name: "glyph",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ preset: null, // 'awesome3', 'awesome4', 'bootstrap3', 'material'
+ map: {},
+ },
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ opts = ctx.options.glyph;
+
+ if (opts.preset) {
+ FT.assert(
+ !!PRESETS[opts.preset],
+ "Invalid value for `options.glyph.preset`: " + opts.preset
+ );
+ opts.map = $.extend({}, PRESETS[opts.preset], opts.map);
+ } else {
+ tree.warn("ext-glyph: missing `preset` option.");
+ }
+ this._superApply(arguments);
+ tree.$container.addClass("fancytree-ext-glyph");
+ },
+ nodeRenderStatus: function (ctx) {
+ var checkbox,
+ icon,
+ res,
+ span,
+ node = ctx.node,
+ $span = $(node.span),
+ opts = ctx.options.glyph;
+
+ res = this._super(ctx);
+
+ if (node.isRootNode()) {
+ return res;
+ }
+ span = $span.children(".fancytree-expander").get(0);
+ if (span) {
+ // if( node.isLoading() ){
+ // icon = "loading";
+ if (node.expanded && node.hasChildren()) {
+ icon = "expanderOpen";
+ } else if (node.isUndefined()) {
+ icon = "expanderLazy";
+ } else if (node.hasChildren()) {
+ icon = "expanderClosed";
+ } else {
+ icon = "noExpander";
+ }
+ // span.className = "fancytree-expander " + map[icon];
+ setIcon(node, span, "fancytree-expander", opts, icon);
+ }
+
+ if (node.tr) {
+ span = $("td", node.tr).find(".fancytree-checkbox").get(0);
+ } else {
+ span = $span.children(".fancytree-checkbox").get(0);
+ }
+ if (span) {
+ checkbox = FT.evalOption("checkbox", node, node, opts, false);
+ if (
+ (node.parent && node.parent.radiogroup) ||
+ checkbox === "radio"
+ ) {
+ icon = node.selected ? "radioSelected" : "radio";
+ setIcon(
+ node,
+ span,
+ "fancytree-checkbox fancytree-radio",
+ opts,
+ icon
+ );
+ } else {
+ // eslint-disable-next-line no-nested-ternary
+ icon = node.selected
+ ? "checkboxSelected"
+ : node.partsel
+ ? "checkboxUnknown"
+ : "checkbox";
+ // span.className = "fancytree-checkbox " + map[icon];
+ setIcon(node, span, "fancytree-checkbox", opts, icon);
+ }
+ }
+
+ // Standard icon (note that this does not match .fancytree-custom-icon,
+ // that might be set by opts.icon callbacks)
+ span = $span.children(".fancytree-icon").get(0);
+ if (span) {
+ if (node.statusNodeType) {
+ icon = node.statusNodeType; // loading, error
+ } else if (node.folder) {
+ icon =
+ node.expanded && node.hasChildren()
+ ? "folderOpen"
+ : "folder";
+ } else {
+ icon = node.expanded ? "docOpen" : "doc";
+ }
+ setIcon(node, span, "fancytree-icon", opts, icon);
+ }
+ return res;
+ },
+ nodeSetStatus: function (ctx, status, message, details) {
+ var res,
+ span,
+ opts = ctx.options.glyph,
+ node = ctx.node;
+
+ res = this._superApply(arguments);
+
+ if (
+ status === "error" ||
+ status === "loading" ||
+ status === "nodata"
+ ) {
+ if (node.parent) {
+ span = $(".fancytree-expander", node.span).get(0);
+ if (span) {
+ setIcon(node, span, "fancytree-expander", opts, status);
+ }
+ } else {
+ //
+ span = $(
+ ".fancytree-statusnode-" + status,
+ node[this.nodeContainerAttrName]
+ )
+ .find(".fancytree-icon")
+ .get(0);
+ if (span) {
+ setIcon(node, span, "fancytree-icon", opts, status);
+ }
+ }
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.gridnav.js
+ *
+ * Support keyboard navigation for trees with embedded input controls.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([
+ "jquery",
+ "./jquery.fancytree",
+ "./jquery.fancytree.table",
+ ], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree.table"); // core + table
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ // Allow these navigation keys even when input controls are focused
+
+ var KC = $.ui.keyCode,
+ // which keys are *not* handled by embedded control, but passed to tree
+ // navigation handler:
+ NAV_KEYS = {
+ text: [KC.UP, KC.DOWN],
+ checkbox: [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+ link: [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+ radiobutton: [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+ "select-one": [KC.LEFT, KC.RIGHT],
+ "select-multiple": [KC.LEFT, KC.RIGHT],
+ };
+
+ /* Calculate TD column index (considering colspans).*/
+ function getColIdx($tr, $td) {
+ var colspan,
+ td = $td.get(0),
+ idx = 0;
+
+ $tr.children().each(function () {
+ if (this === td) {
+ return false;
+ }
+ colspan = $(this).prop("colspan");
+ idx += colspan ? colspan : 1;
+ });
+ return idx;
+ }
+
+ /* Find TD at given column index (considering colspans).*/
+ function findTdAtColIdx($tr, colIdx) {
+ var colspan,
+ res = null,
+ idx = 0;
+
+ $tr.children().each(function () {
+ if (idx >= colIdx) {
+ res = $(this);
+ return false;
+ }
+ colspan = $(this).prop("colspan");
+ idx += colspan ? colspan : 1;
+ });
+ return res;
+ }
+
+ /* Find adjacent cell for a given direction. Skip empty cells and consider merged cells */
+ function findNeighbourTd($target, keyCode) {
+ var $tr,
+ colIdx,
+ $td = $target.closest("td"),
+ $tdNext = null;
+
+ switch (keyCode) {
+ case KC.LEFT:
+ $tdNext = $td.prev();
+ break;
+ case KC.RIGHT:
+ $tdNext = $td.next();
+ break;
+ case KC.UP:
+ case KC.DOWN:
+ $tr = $td.parent();
+ colIdx = getColIdx($tr, $td);
+ while (true) {
+ $tr = keyCode === KC.UP ? $tr.prev() : $tr.next();
+ if (!$tr.length) {
+ break;
+ }
+ // Skip hidden rows
+ if ($tr.is(":hidden")) {
+ continue;
+ }
+ // Find adjacent cell in the same column
+ $tdNext = findTdAtColIdx($tr, colIdx);
+ // Skip cells that don't conatain a focusable element
+ if ($tdNext && $tdNext.find(":input,a").length) {
+ break;
+ }
+ }
+ break;
+ }
+ return $tdNext;
+ }
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "gridnav",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ autofocusInput: false, // Focus first embedded input if node gets activated
+ handleCursorKeys: true, // Allow UP/DOWN in inputs to move to prev/next node
+ },
+
+ treeInit: function (ctx) {
+ // gridnav requires the table extension to be loaded before itself
+ this._requireExtension("table", true, true);
+ this._superApply(arguments);
+
+ this.$container.addClass("fancytree-ext-gridnav");
+
+ // Activate node if embedded input gets focus (due to a click)
+ this.$container.on("focusin", function (event) {
+ var ctx2,
+ node = $.ui.fancytree.getNode(event.target);
+
+ if (node && !node.isActive()) {
+ // Call node.setActive(), but also pass the event
+ ctx2 = ctx.tree._makeHookContext(node, event);
+ ctx.tree._callHook("nodeSetActive", ctx2, true);
+ }
+ });
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var $outer,
+ opts = ctx.options.gridnav,
+ node = ctx.node,
+ event = ctx.originalEvent || {},
+ triggeredByInput = $(event.target).is(":input");
+
+ flag = flag !== false;
+
+ this._superApply(arguments);
+
+ if (flag) {
+ if (ctx.options.titlesTabbable) {
+ if (!triggeredByInput) {
+ $(node.span).find("span.fancytree-title").focus();
+ node.setFocus();
+ }
+ // If one node is tabbable, the container no longer needs to be
+ ctx.tree.$container.attr("tabindex", "-1");
+ // ctx.tree.$container.removeAttr("tabindex");
+ } else if (opts.autofocusInput && !triggeredByInput) {
+ // Set focus to input sub input (if node was clicked, but not
+ // when TAB was pressed )
+ $outer = $(node.tr || node.span);
+ $outer.find(":input:enabled").first().focus();
+ }
+ }
+ },
+ nodeKeydown: function (ctx) {
+ var inputType,
+ handleKeys,
+ $td,
+ opts = ctx.options.gridnav,
+ event = ctx.originalEvent,
+ $target = $(event.target);
+
+ if ($target.is(":input:enabled")) {
+ inputType = $target.prop("type");
+ } else if ($target.is("a")) {
+ inputType = "link";
+ }
+ // ctx.tree.debug("ext-gridnav nodeKeydown", event, inputType);
+
+ if (inputType && opts.handleCursorKeys) {
+ handleKeys = NAV_KEYS[inputType];
+ if (handleKeys && $.inArray(event.which, handleKeys) >= 0) {
+ $td = findNeighbourTd($target, event.which);
+ if ($td && $td.length) {
+ // ctx.node.debug("ignore keydown in input", event.which, handleKeys);
+ $td.find(":input:enabled,a").focus();
+ // Prevent Fancytree default navigation
+ return false;
+ }
+ }
+ return true;
+ }
+ // ctx.tree.debug("ext-gridnav NOT HANDLED", event, inputType);
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.multi.js
+ *
+ * Allow multiple selection of nodes by mouse or keyboard.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ // var isMac = /Mac/.test(navigator.platform);
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "multi",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ allowNoSelect: false, //
+ mode: "sameParent", //
+ // Events:
+ // beforeSelect: $.noop // Return false to prevent cancel/save (data.input is available)
+ },
+
+ treeInit: function (ctx) {
+ this._superApply(arguments);
+ this.$container.addClass("fancytree-ext-multi");
+ if (ctx.options.selectMode === 1) {
+ $.error(
+ "Fancytree ext-multi: selectMode: 1 (single) is not compatible."
+ );
+ }
+ },
+ nodeClick: function (ctx) {
+ var //pluginOpts = ctx.options.multi,
+ tree = ctx.tree,
+ node = ctx.node,
+ activeNode = tree.getActiveNode() || tree.getFirstChild(),
+ isCbClick = ctx.targetType === "checkbox",
+ isExpanderClick = ctx.targetType === "expander",
+ eventStr = $.ui.fancytree.eventToString(ctx.originalEvent);
+
+ switch (eventStr) {
+ case "click":
+ if (isExpanderClick) {
+ break;
+ } // Default handler will expand/collapse
+ if (!isCbClick) {
+ tree.selectAll(false);
+ // Select clicked node (radio-button mode)
+ node.setSelected();
+ }
+ // Default handler will toggle checkbox clicks and activate
+ break;
+ case "shift+click":
+ // node.debug("click")
+ tree.visitRows(
+ function (n) {
+ // n.debug("click2", n===node, node)
+ n.setSelected();
+ if (n === node) {
+ return false;
+ }
+ },
+ {
+ start: activeNode,
+ reverse: activeNode.isBelowOf(node),
+ }
+ );
+ break;
+ case "ctrl+click":
+ case "meta+click": // Mac: [Command]
+ node.toggleSelected();
+ return;
+ }
+ return this._superApply(arguments);
+ },
+ nodeKeydown: function (ctx) {
+ var tree = ctx.tree,
+ node = ctx.node,
+ event = ctx.originalEvent,
+ eventStr = $.ui.fancytree.eventToString(event);
+
+ switch (eventStr) {
+ case "up":
+ case "down":
+ tree.selectAll(false);
+ node.navigate(event.which, true);
+ tree.getActiveNode().setSelected();
+ break;
+ case "shift+up":
+ case "shift+down":
+ node.navigate(event.which, true);
+ tree.getActiveNode().setSelected();
+ break;
+ }
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.persist.js
+ *
+ * Persist tree status in cookiesRemove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @depends: js-cookie or jquery-cookie
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+ /* global Cookies:false */
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+ var cookieStore = null,
+ localStorageStore = null,
+ sessionStorageStore = null,
+ _assert = $.ui.fancytree.assert,
+ ACTIVE = "active",
+ EXPANDED = "expanded",
+ FOCUS = "focus",
+ SELECTED = "selected";
+
+ // Accessing window.xxxStorage may raise security exceptions (see #1022)
+ try {
+ _assert(window.localStorage && window.localStorage.getItem);
+ localStorageStore = {
+ get: function (key) {
+ return window.localStorage.getItem(key);
+ },
+ set: function (key, value) {
+ window.localStorage.setItem(key, value);
+ },
+ remove: function (key) {
+ window.localStorage.removeItem(key);
+ },
+ };
+ } catch (e) {
+ $.ui.fancytree.warn("Could not access window.localStorage", e);
+ }
+
+ try {
+ _assert(window.sessionStorage && window.sessionStorage.getItem);
+ sessionStorageStore = {
+ get: function (key) {
+ return window.sessionStorage.getItem(key);
+ },
+ set: function (key, value) {
+ window.sessionStorage.setItem(key, value);
+ },
+ remove: function (key) {
+ window.sessionStorage.removeItem(key);
+ },
+ };
+ } catch (e) {
+ $.ui.fancytree.warn("Could not access window.sessionStorage", e);
+ }
+
+ if (typeof Cookies === "function") {
+ // Assume https://github.com/js-cookie/js-cookie
+ cookieStore = {
+ get: Cookies.get,
+ set: function (key, value) {
+ Cookies.set(key, value, this.options.persist.cookie);
+ },
+ remove: Cookies.remove,
+ };
+ } else if ($ && typeof $.cookie === "function") {
+ // Fall back to https://github.com/carhartl/jquery-cookie
+ cookieStore = {
+ get: $.cookie,
+ set: function (key, value) {
+ $.cookie(key, value, this.options.persist.cookie);
+ },
+ remove: $.removeCookie,
+ };
+ }
+
+ /* Recursively load lazy nodes
+ * @param {string} mode 'load', 'expand', false
+ */
+ function _loadLazyNodes(tree, local, keyList, mode, dfd) {
+ var i,
+ key,
+ l,
+ node,
+ foundOne = false,
+ expandOpts = tree.options.persist.expandOpts,
+ deferredList = [],
+ missingKeyList = [];
+
+ keyList = keyList || [];
+ dfd = dfd || $.Deferred();
+
+ for (i = 0, l = keyList.length; i < l; i++) {
+ key = keyList[i];
+ node = tree.getNodeByKey(key);
+ if (node) {
+ if (mode && node.isUndefined()) {
+ foundOne = true;
+ tree.debug(
+ "_loadLazyNodes: " + node + " is lazy: loading..."
+ );
+ if (mode === "expand") {
+ deferredList.push(node.setExpanded(true, expandOpts));
+ } else {
+ deferredList.push(node.load());
+ }
+ } else {
+ tree.debug("_loadLazyNodes: " + node + " already loaded.");
+ node.setExpanded(true, expandOpts);
+ }
+ } else {
+ missingKeyList.push(key);
+ tree.debug("_loadLazyNodes: " + node + " was not yet found.");
+ }
+ }
+
+ $.when.apply($, deferredList).always(function () {
+ // All lazy-expands have finished
+ if (foundOne && missingKeyList.length > 0) {
+ // If we read new nodes from server, try to resolve yet-missing keys
+ _loadLazyNodes(tree, local, missingKeyList, mode, dfd);
+ } else {
+ if (missingKeyList.length) {
+ tree.warn(
+ "_loadLazyNodes: could not load those keys: ",
+ missingKeyList
+ );
+ for (i = 0, l = missingKeyList.length; i < l; i++) {
+ key = keyList[i];
+ local._appendKey(EXPANDED, keyList[i], false);
+ }
+ }
+ dfd.resolve();
+ }
+ });
+ return dfd;
+ }
+
+ /**
+ * [ext-persist] Remove persistence data of the given type(s).
+ * Called like
+ * $.ui.fancytree.getTree("#tree").clearCookies("active expanded focus selected");
+ *
+ * @alias Fancytree#clearPersistData
+ * @requires jquery.fancytree.persist.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.clearPersistData = function (
+ types
+ ) {
+ var local = this.ext.persist,
+ prefix = local.cookiePrefix;
+
+ types = types || "active expanded focus selected";
+ if (types.indexOf(ACTIVE) >= 0) {
+ local._data(prefix + ACTIVE, null);
+ }
+ if (types.indexOf(EXPANDED) >= 0) {
+ local._data(prefix + EXPANDED, null);
+ }
+ if (types.indexOf(FOCUS) >= 0) {
+ local._data(prefix + FOCUS, null);
+ }
+ if (types.indexOf(SELECTED) >= 0) {
+ local._data(prefix + SELECTED, null);
+ }
+ };
+
+ $.ui.fancytree._FancytreeClass.prototype.clearCookies = function (types) {
+ this.warn(
+ "'tree.clearCookies()' is deprecated since v2.27.0: use 'clearPersistData()' instead."
+ );
+ return this.clearPersistData(types);
+ };
+
+ /**
+ * [ext-persist] Return persistence information from cookies
+ *
+ * Called like
+ * $.ui.fancytree.getTree("#tree").getPersistData();
+ *
+ * @alias Fancytree#getPersistData
+ * @requires jquery.fancytree.persist.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.getPersistData = function () {
+ var local = this.ext.persist,
+ prefix = local.cookiePrefix,
+ delim = local.cookieDelimiter,
+ res = {};
+
+ res[ACTIVE] = local._data(prefix + ACTIVE);
+ res[EXPANDED] = (local._data(prefix + EXPANDED) || "").split(delim);
+ res[SELECTED] = (local._data(prefix + SELECTED) || "").split(delim);
+ res[FOCUS] = local._data(prefix + FOCUS);
+ return res;
+ };
+
+ /******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "persist",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ cookieDelimiter: "~",
+ cookiePrefix: undefined, // 'fancytree-<treeId>-' by default
+ cookie: {
+ raw: false,
+ expires: "",
+ path: "",
+ domain: "",
+ secure: false,
+ },
+ expandLazy: false, // true: recursively expand and load lazy nodes
+ expandOpts: undefined, // optional `opts` argument passed to setExpanded()
+ fireActivate: true, // false: suppress `activate` event after active node was restored
+ overrideSource: true, // true: cookie takes precedence over `source` data attributes.
+ store: "auto", // 'cookie': force cookie, 'local': force localStore, 'session': force sessionStore
+ types: "active expanded focus selected",
+ },
+
+ /* Generic read/write string data to cookie, sessionStorage or localStorage. */
+ _data: function (key, value) {
+ var store = this._local.store;
+
+ if (value === undefined) {
+ return store.get.call(this, key);
+ } else if (value === null) {
+ store.remove.call(this, key);
+ } else {
+ store.set.call(this, key, value);
+ }
+ },
+
+ /* Append `key` to a cookie. */
+ _appendKey: function (type, key, flag) {
+ key = "" + key; // #90
+ var local = this._local,
+ instOpts = this.options.persist,
+ delim = instOpts.cookieDelimiter,
+ cookieName = local.cookiePrefix + type,
+ data = local._data(cookieName),
+ keyList = data ? data.split(delim) : [],
+ idx = $.inArray(key, keyList);
+ // Remove, even if we add a key, so the key is always the last entry
+ if (idx >= 0) {
+ keyList.splice(idx, 1);
+ }
+ // Append key to cookie
+ if (flag) {
+ keyList.push(key);
+ }
+ local._data(cookieName, keyList.join(delim));
+ },
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ opts = ctx.options,
+ local = this._local,
+ instOpts = this.options.persist;
+
+ // // For 'auto' or 'cookie' mode, the cookie plugin must be available
+ // _assert((instOpts.store !== "auto" && instOpts.store !== "cookie") || cookieStore,
+ // "Missing required plugin for 'persist' extension: js.cookie.js or jquery.cookie.js");
+
+ local.cookiePrefix =
+ instOpts.cookiePrefix || "fancytree-" + tree._id + "-";
+ local.storeActive = instOpts.types.indexOf(ACTIVE) >= 0;
+ local.storeExpanded = instOpts.types.indexOf(EXPANDED) >= 0;
+ local.storeSelected = instOpts.types.indexOf(SELECTED) >= 0;
+ local.storeFocus = instOpts.types.indexOf(FOCUS) >= 0;
+ local.store = null;
+
+ if (instOpts.store === "auto") {
+ instOpts.store = localStorageStore ? "local" : "cookie";
+ }
+ if ($.isPlainObject(instOpts.store)) {
+ local.store = instOpts.store;
+ } else if (instOpts.store === "cookie") {
+ local.store = cookieStore;
+ } else if (instOpts.store === "local") {
+ local.store =
+ instOpts.store === "local"
+ ? localStorageStore
+ : sessionStorageStore;
+ } else if (instOpts.store === "session") {
+ local.store =
+ instOpts.store === "local"
+ ? localStorageStore
+ : sessionStorageStore;
+ }
+ _assert(local.store, "Need a valid store.");
+
+ // Bind init-handler to apply cookie state
+ tree.$div.on("fancytreeinit", function (event) {
+ if (
+ tree._triggerTreeEvent("beforeRestore", null, {}) === false
+ ) {
+ return;
+ }
+
+ var cookie,
+ dfd,
+ i,
+ keyList,
+ node,
+ prevFocus = local._data(local.cookiePrefix + FOCUS), // record this before node.setActive() overrides it;
+ noEvents = instOpts.fireActivate === false;
+
+ // tree.debug("document.cookie:", document.cookie);
+
+ cookie = local._data(local.cookiePrefix + EXPANDED);
+ keyList = cookie && cookie.split(instOpts.cookieDelimiter);
+
+ if (local.storeExpanded) {
+ // Recursively load nested lazy nodes if expandLazy is 'expand' or 'load'
+ // Also remove expand-cookies for unmatched nodes
+ dfd = _loadLazyNodes(
+ tree,
+ local,
+ keyList,
+ instOpts.expandLazy ? "expand" : false,
+ null
+ );
+ } else {
+ // nothing to do
+ dfd = new $.Deferred().resolve();
+ }
+
+ dfd.done(function () {
+ if (local.storeSelected) {
+ cookie = local._data(local.cookiePrefix + SELECTED);
+ if (cookie) {
+ keyList = cookie.split(instOpts.cookieDelimiter);
+ for (i = 0; i < keyList.length; i++) {
+ node = tree.getNodeByKey(keyList[i]);
+ if (node) {
+ if (
+ node.selected === undefined ||
+ (instOpts.overrideSource &&
+ node.selected === false)
+ ) {
+ // node.setSelected();
+ node.selected = true;
+ node.renderStatus();
+ }
+ } else {
+ // node is no longer member of the tree: remove from cookie also
+ local._appendKey(
+ SELECTED,
+ keyList[i],
+ false
+ );
+ }
+ }
+ }
+ // In selectMode 3 we have to fix the child nodes, since we
+ // only stored the selected *top* nodes
+ if (tree.options.selectMode === 3) {
+ tree.visit(function (n) {
+ if (n.selected) {
+ n.fixSelection3AfterClick();
+ return "skip";
+ }
+ });
+ }
+ }
+ if (local.storeActive) {
+ cookie = local._data(local.cookiePrefix + ACTIVE);
+ if (
+ cookie &&
+ (opts.persist.overrideSource || !tree.activeNode)
+ ) {
+ node = tree.getNodeByKey(cookie);
+ if (node) {
+ node.debug("persist: set active", cookie);
+ // We only want to set the focus if the container
+ // had the keyboard focus before
+ node.setActive(true, {
+ noFocus: true,
+ noEvents: noEvents,
+ });
+ }
+ }
+ }
+ if (local.storeFocus && prevFocus) {
+ node = tree.getNodeByKey(prevFocus);
+ if (node) {
+ // node.debug("persist: set focus", cookie);
+ if (tree.options.titlesTabbable) {
+ $(node.span).find(".fancytree-title").focus();
+ } else {
+ $(tree.$container).focus();
+ }
+ // node.setFocus();
+ }
+ }
+ tree._triggerTreeEvent("restore", null, {});
+ });
+ });
+ // Init the tree
+ return this._superApply(arguments);
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var res,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeActive) {
+ local._data(
+ local.cookiePrefix + ACTIVE,
+ this.activeNode ? this.activeNode.key : null
+ );
+ }
+ return res;
+ },
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var res,
+ node = ctx.node,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeExpanded) {
+ local._appendKey(EXPANDED, node.key, flag);
+ }
+ return res;
+ },
+ nodeSetFocus: function (ctx, flag) {
+ var res,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeFocus) {
+ local._data(
+ local.cookiePrefix + FOCUS,
+ this.focusNode ? this.focusNode.key : null
+ );
+ }
+ return res;
+ },
+ nodeSetSelected: function (ctx, flag, callOpts) {
+ var res,
+ selNodes,
+ tree = ctx.tree,
+ node = ctx.node,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeSelected) {
+ if (tree.options.selectMode === 3) {
+ // In selectMode 3 we only store the the selected *top* nodes.
+ // De-selecting a node may also de-select some parents, so we
+ // calculate the current status again
+ selNodes = $.map(tree.getSelectedNodes(true), function (n) {
+ return n.key;
+ });
+ selNodes = selNodes.join(
+ ctx.options.persist.cookieDelimiter
+ );
+ local._data(local.cookiePrefix + SELECTED, selNodes);
+ } else {
+ // beforeSelect can prevent the change - flag doesn't reflect the node.selected state
+ local._appendKey(SELECTED, node.key, node.selected);
+ }
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.table.js
+ *
+ * Render tree as table (aka 'tree grid', 'table tree').
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var _assert = $.ui.fancytree.assert;
+
+ function insertFirstChild(referenceNode, newNode) {
+ referenceNode.insertBefore(newNode, referenceNode.firstChild);
+ }
+
+ function insertSiblingAfter(referenceNode, newNode) {
+ referenceNode.parentNode.insertBefore(
+ newNode,
+ referenceNode.nextSibling
+ );
+ }
+
+ /* Show/hide all rows that are structural descendants of `parent`. */
+ function setChildRowVisibility(parent, flag) {
+ parent.visit(function (node) {
+ var tr = node.tr;
+ // currentFlag = node.hide ? false : flag; // fix for ext-filter
+ if (tr) {
+ tr.style.display = node.hide || !flag ? "none" : "";
+ }
+ if (!node.expanded) {
+ return "skip";
+ }
+ });
+ }
+
+ /* Find node that is rendered in previous row. */
+ function findPrevRowNode(node) {
+ var i,
+ last,
+ prev,
+ parent = node.parent,
+ siblings = parent ? parent.children : null;
+
+ if (siblings && siblings.length > 1 && siblings[0] !== node) {
+ // use the lowest descendant of the preceeding sibling
+ i = $.inArray(node, siblings);
+ prev = siblings[i - 1];
+ _assert(prev.tr);
+ // descend to lowest child (with a <tr> tag)
+ while (prev.children && prev.children.length) {
+ last = prev.children[prev.children.length - 1];
+ if (!last.tr) {
+ break;
+ }
+ prev = last;
+ }
+ } else {
+ // if there is no preceding sibling, use the direct parent
+ prev = parent;
+ }
+ return prev;
+ }
+
+ $.ui.fancytree.registerExtension({
+ name: "table",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx)
+ indentation: 16, // indent every node level by 16px
+ mergeStatusColumns: true, // display 'nodata', 'loading', 'error' centered in a single, merged TR
+ nodeColumnIdx: 0, // render node expander, icon, and title to this column (default: #0)
+ },
+ // Overide virtual methods for this extension.
+ // `this` : is this extension object
+ // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
+ treeInit: function (ctx) {
+ var i,
+ n,
+ $row,
+ $tbody,
+ tree = ctx.tree,
+ opts = ctx.options,
+ tableOpts = opts.table,
+ $table = tree.widget.element;
+
+ if (tableOpts.customStatus != null) {
+ if (opts.renderStatusColumns == null) {
+ tree.warn(
+ "The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' instead."
+ );
+ opts.renderStatusColumns = tableOpts.customStatus;
+ } else {
+ $.error(
+ "The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' only instead."
+ );
+ }
+ }
+ if (opts.renderStatusColumns) {
+ if (opts.renderStatusColumns === true) {
+ opts.renderStatusColumns = opts.renderColumns;
+ // } else if( opts.renderStatusColumns === "wide" ) {
+ // opts.renderStatusColumns = _renderStatusNodeWide;
+ }
+ }
+
+ $table.addClass("fancytree-container fancytree-ext-table");
+ $tbody = $table.find(">tbody");
+ if (!$tbody.length) {
+ // TODO: not sure if we can rely on browsers to insert missing <tbody> before <tr>s:
+ if ($table.find(">tr").length) {
+ $.error(
+ "Expected table > tbody > tr. If you see this please open an issue."
+ );
+ }
+ $tbody = $("<tbody>").appendTo($table);
+ }
+
+ tree.tbody = $tbody[0];
+
+ // Prepare row templates:
+ // Determine column count from table header if any
+ tree.columnCount = $("thead >tr", $table)
+ .last()
+ .find(">th", $table).length;
+ // Read TR templates from tbody if any
+ $row = $tbody.children("tr").first();
+ if ($row.length) {
+ n = $row.children("td").length;
+ if (tree.columnCount && n !== tree.columnCount) {
+ tree.warn(
+ "Column count mismatch between thead (" +
+ tree.columnCount +
+ ") and tbody (" +
+ n +
+ "): using tbody."
+ );
+ tree.columnCount = n;
+ }
+ $row = $row.clone();
+ } else {
+ // Only thead is defined: create default row markup
+ _assert(
+ tree.columnCount >= 1,
+ "Need either <thead> or <tbody> with <td> elements to determine column count."
+ );
+ $row = $("<tr />");
+ for (i = 0; i < tree.columnCount; i++) {
+ $row.append("<td />");
+ }
+ }
+ $row.find(">td")
+ .eq(tableOpts.nodeColumnIdx)
+ .html("<span class='fancytree-node' />");
+ if (opts.aria) {
+ $row.attr("role", "row");
+ $row.find("td").attr("role", "gridcell");
+ }
+ tree.rowFragment = document.createDocumentFragment();
+ tree.rowFragment.appendChild($row.get(0));
+
+ // // If tbody contains a second row, use this as status node template
+ // $row = $tbody.children("tr").eq(1);
+ // if( $row.length === 0 ) {
+ // tree.statusRowFragment = tree.rowFragment;
+ // } else {
+ // $row = $row.clone();
+ // tree.statusRowFragment = document.createDocumentFragment();
+ // tree.statusRowFragment.appendChild($row.get(0));
+ // }
+ //
+ $tbody.empty();
+
+ // Make sure that status classes are set on the node's <tr> elements
+ tree.statusClassPropName = "tr";
+ tree.ariaPropName = "tr";
+ this.nodeContainerAttrName = "tr";
+
+ // #489: make sure $container is set to <table>, even if ext-dnd is listed before ext-table
+ tree.$container = $table;
+
+ this._superApply(arguments);
+
+ // standard Fancytree created a root UL
+ $(tree.rootNode.ul).remove();
+ tree.rootNode.ul = null;
+
+ // Add container to the TAB chain
+ // #577: Allow to set tabindex to "0", "-1" and ""
+ this.$container.attr("tabindex", opts.tabindex);
+ // this.$container.attr("tabindex", opts.tabbable ? "0" : "-1");
+ if (opts.aria) {
+ tree.$container
+ .attr("role", "treegrid")
+ .attr("aria-readonly", true);
+ }
+ },
+ nodeRemoveChildMarkup: function (ctx) {
+ var node = ctx.node;
+ // node.debug("nodeRemoveChildMarkup()");
+ node.visit(function (n) {
+ if (n.tr) {
+ $(n.tr).remove();
+ n.tr = null;
+ }
+ });
+ },
+ nodeRemoveMarkup: function (ctx) {
+ var node = ctx.node;
+ // node.debug("nodeRemoveMarkup()");
+ if (node.tr) {
+ $(node.tr).remove();
+ node.tr = null;
+ }
+ this.nodeRemoveChildMarkup(ctx);
+ },
+ /* Override standard render. */
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ var children,
+ firstTr,
+ i,
+ l,
+ newRow,
+ prevNode,
+ prevTr,
+ subCtx,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = ctx.options,
+ isRootNode = !node.parent;
+
+ if (tree._enableUpdate === false) {
+ // $.ui.fancytree.debug("*** nodeRender _enableUpdate: false");
+ return;
+ }
+ if (!_recursive) {
+ ctx.hasCollapsedParents = node.parent && !node.parent.expanded;
+ }
+ // $.ui.fancytree.debug("*** nodeRender " + node + ", isRoot=" + isRootNode, "tr=" + node.tr, "hcp=" + ctx.hasCollapsedParents, "parent.tr=" + (node.parent && node.parent.tr));
+ if (!isRootNode) {
+ if (node.tr && force) {
+ this.nodeRemoveMarkup(ctx);
+ }
+ if (node.tr) {
+ if (force) {
+ // Set icon, link, and title (normally this is only required on initial render)
+ this.nodeRenderTitle(ctx); // triggers renderColumns()
+ } else {
+ // Update element classes according to node state
+ this.nodeRenderStatus(ctx);
+ }
+ } else {
+ if (ctx.hasCollapsedParents && !deep) {
+ // #166: we assume that the parent will be (recursively) rendered
+ // later anyway.
+ // node.debug("nodeRender ignored due to unrendered parent");
+ return;
+ }
+ // Create new <tr> after previous row
+ // if( node.isStatusNode() ) {
+ // newRow = tree.statusRowFragment.firstChild.cloneNode(true);
+ // } else {
+ newRow = tree.rowFragment.firstChild.cloneNode(true);
+ // }
+ prevNode = findPrevRowNode(node);
+ // $.ui.fancytree.debug("*** nodeRender " + node + ": prev: " + prevNode.key);
+ _assert(prevNode);
+ if (collapsed === true && _recursive) {
+ // hide all child rows, so we can use an animation to show it later
+ newRow.style.display = "none";
+ } else if (deep && ctx.hasCollapsedParents) {
+ // also hide this row if deep === true but any parent is collapsed
+ newRow.style.display = "none";
+ // newRow.style.color = "red";
+ }
+ if (prevNode.tr) {
+ insertSiblingAfter(prevNode.tr, newRow);
+ } else {
+ _assert(
+ !prevNode.parent,
+ "prev. row must have a tr, or be system root"
+ );
+ // tree.tbody.appendChild(newRow);
+ insertFirstChild(tree.tbody, newRow); // #675
+ }
+ node.tr = newRow;
+ if (node.key && opts.generateIds) {
+ node.tr.id = opts.idPrefix + node.key;
+ }
+ node.tr.ftnode = node;
+ // if(opts.aria){
+ // $(node.tr).attr("aria-labelledby", "ftal_" + opts.idPrefix + node.key);
+ // }
+ node.span = $("span.fancytree-node", node.tr).get(0);
+ // Set icon, link, and title (normally this is only required on initial render)
+ this.nodeRenderTitle(ctx);
+ // Allow tweaking, binding, after node was created for the first time
+ // tree._triggerNodeEvent("createNode", ctx);
+ if (opts.createNode) {
+ opts.createNode.call(tree, { type: "createNode" }, ctx);
+ }
+ }
+ }
+ // Allow tweaking after node state was rendered
+ // tree._triggerNodeEvent("renderNode", ctx);
+ if (opts.renderNode) {
+ opts.renderNode.call(tree, { type: "renderNode" }, ctx);
+ }
+ // Visit child nodes
+ // Add child markup
+ children = node.children;
+ if (children && (isRootNode || deep || node.expanded)) {
+ for (i = 0, l = children.length; i < l; i++) {
+ subCtx = $.extend({}, ctx, { node: children[i] });
+ subCtx.hasCollapsedParents =
+ subCtx.hasCollapsedParents || !node.expanded;
+ this.nodeRender(subCtx, force, deep, collapsed, true);
+ }
+ }
+ // Make sure, that <tr> order matches node.children order.
+ if (children && !_recursive) {
+ // we only have to do it once, for the root branch
+ prevTr = node.tr || null;
+ firstTr = tree.tbody.firstChild;
+ // Iterate over all descendants
+ node.visit(function (n) {
+ if (n.tr) {
+ if (
+ !n.parent.expanded &&
+ n.tr.style.display !== "none"
+ ) {
+ // fix after a node was dropped over a collapsed
+ n.tr.style.display = "none";
+ setChildRowVisibility(n, false);
+ }
+ if (n.tr.previousSibling !== prevTr) {
+ node.debug("_fixOrder: mismatch at node: " + n);
+ var nextTr = prevTr ? prevTr.nextSibling : firstTr;
+ tree.tbody.insertBefore(n.tr, nextTr);
+ }
+ prevTr = n.tr;
+ }
+ });
+ }
+ // Update element classes according to node state
+ // if(!isRootNode){
+ // this.nodeRenderStatus(ctx);
+ // }
+ },
+ nodeRenderTitle: function (ctx, title) {
+ var $cb,
+ res,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = ctx.options,
+ isStatusNode = node.isStatusNode();
+
+ res = this._super(ctx, title);
+
+ if (node.isRootNode()) {
+ return res;
+ }
+ // Move checkbox to custom column
+ if (
+ opts.checkbox &&
+ !isStatusNode &&
+ opts.table.checkboxColumnIdx != null
+ ) {
+ $cb = $("span.fancytree-checkbox", node.span); //.detach();
+ $(node.tr)
+ .find("td")
+ .eq(+opts.table.checkboxColumnIdx)
+ .html($cb);
+ }
+ // Update element classes according to node state
+ this.nodeRenderStatus(ctx);
+
+ if (isStatusNode) {
+ if (opts.renderStatusColumns) {
+ // Let user code write column content
+ opts.renderStatusColumns.call(
+ tree,
+ { type: "renderStatusColumns" },
+ ctx
+ );
+ } else if (opts.table.mergeStatusColumns && node.isTopLevel()) {
+ $(node.tr)
+ .find(">td")
+ .eq(0)
+ .prop("colspan", tree.columnCount)
+ .text(node.title)
+ .addClass("fancytree-status-merged")
+ .nextAll()
+ .remove();
+ } // else: default rendering for status node: leave other cells empty
+ } else if (opts.renderColumns) {
+ opts.renderColumns.call(tree, { type: "renderColumns" }, ctx);
+ }
+ return res;
+ },
+ nodeRenderStatus: function (ctx) {
+ var indent,
+ node = ctx.node,
+ opts = ctx.options;
+
+ this._super(ctx);
+
+ $(node.tr).removeClass("fancytree-node");
+ // indent
+ indent = (node.getLevel() - 1) * opts.table.indentation;
+ if (opts.rtl) {
+ $(node.span).css({ paddingRight: indent + "px" });
+ } else {
+ $(node.span).css({ paddingLeft: indent + "px" });
+ }
+ },
+ /* Expand node, return Deferred.promise. */
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ // flag defaults to true
+ flag = flag !== false;
+
+ if ((ctx.node.expanded && flag) || (!ctx.node.expanded && !flag)) {
+ // Expanded state isn't changed - just call base implementation
+ return this._superApply(arguments);
+ }
+
+ var dfd = new $.Deferred(),
+ subOpts = $.extend({}, callOpts, {
+ noEvents: true,
+ noAnimation: true,
+ });
+
+ callOpts = callOpts || {};
+
+ function _afterExpand(ok, args) {
+ // ctx.tree.info("ok:" + ok, args);
+ if (ok) {
+ // #1108 minExpandLevel: 2 together with table extension does not work
+ // don't call when 'ok' is false:
+ setChildRowVisibility(ctx.node, flag);
+ if (
+ flag &&
+ ctx.options.autoScroll &&
+ !callOpts.noAnimation &&
+ ctx.node.hasChildren()
+ ) {
+ // Scroll down to last child, but keep current node visible
+ ctx.node
+ .getLastChild()
+ .scrollIntoView(true, { topNode: ctx.node })
+ .always(function () {
+ if (!callOpts.noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.resolveWith(ctx.node);
+ });
+ } else {
+ if (!callOpts.noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.resolveWith(ctx.node);
+ }
+ } else {
+ if (!callOpts.noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.rejectWith(ctx.node);
+ }
+ }
+ // Call base-expand with disabled events and animation
+ this._super(ctx, flag, subOpts)
+ .done(function () {
+ _afterExpand(true, arguments);
+ })
+ .fail(function () {
+ _afterExpand(false, arguments);
+ });
+ return dfd.promise();
+ },
+ nodeSetStatus: function (ctx, status, message, details) {
+ if (status === "ok") {
+ var node = ctx.node,
+ firstChild = node.children ? node.children[0] : null;
+ if (firstChild && firstChild.isStatusNode()) {
+ $(firstChild.tr).remove();
+ }
+ }
+ return this._superApply(arguments);
+ },
+ treeClear: function (ctx) {
+ this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode));
+ return this._superApply(arguments);
+ },
+ treeDestroy: function (ctx) {
+ this.$container.find("tbody").empty();
+ if (this.$source) {
+ this.$source.removeClass("fancytree-helper-hidden");
+ }
+ return this._superApply(arguments);
+ },
+ /*,
+ treeSetFocus: function(ctx, flag) {
+// alert("treeSetFocus" + ctx.tree.$container);
+ ctx.tree.$container.focus();
+ $.ui.fancytree.focusTree = ctx.tree;
+ }*/
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.themeroller.js
+ *
+ * Enable jQuery UI ThemeRoller styles.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @see http://jqueryui.com/themeroller/
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "themeroller",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ activeClass: "ui-state-active", // Class added to active node
+ // activeClass: "ui-state-highlight",
+ addClass: "ui-corner-all", // Class added to all nodes
+ focusClass: "ui-state-focus", // Class added to focused node
+ hoverClass: "ui-state-hover", // Class added to hovered node
+ selectedClass: "ui-state-highlight", // Class added to selected nodes
+ // selectedClass: "ui-state-active"
+ },
+
+ treeInit: function (ctx) {
+ var $el = ctx.widget.element,
+ opts = ctx.options.themeroller;
+
+ this._superApply(arguments);
+
+ if ($el[0].nodeName === "TABLE") {
+ $el.addClass("ui-widget ui-corner-all");
+ $el.find(">thead tr").addClass("ui-widget-header");
+ $el.find(">tbody").addClass("ui-widget-conent");
+ } else {
+ $el.addClass("ui-widget ui-widget-content ui-corner-all");
+ }
+
+ $el.on(
+ "mouseenter mouseleave",
+ ".fancytree-node",
+ function (event) {
+ var node = $.ui.fancytree.getNode(event.target),
+ flag = event.type === "mouseenter";
+
+ $(node.tr ? node.tr : node.span).toggleClass(
+ opts.hoverClass + " " + opts.addClass,
+ flag
+ );
+ }
+ );
+ },
+ treeDestroy: function (ctx) {
+ this._superApply(arguments);
+ ctx.widget.element.removeClass(
+ "ui-widget ui-widget-content ui-corner-all"
+ );
+ },
+ nodeRenderStatus: function (ctx) {
+ var classes = {},
+ node = ctx.node,
+ $el = $(node.tr ? node.tr : node.span),
+ opts = ctx.options.themeroller;
+
+ this._super(ctx);
+ /*
+ .ui-state-highlight: Class to be applied to highlighted or selected elements. Applies "highlight" container styles to an element and its child text, links, and icons.
+ .ui-state-error: Class to be applied to error messaging container elements. Applies "error" container styles to an element and its child text, links, and icons.
+ .ui-state-error-text: An additional class that applies just the error text color without background. Can be used on form labels for instance. Also applies error icon color to child icons.
+
+ .ui-state-default: Class to be applied to clickable button-like elements. Applies "clickable default" container styles to an element and its child text, links, and icons.
+ .ui-state-hover: Class to be applied on mouseover to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+ .ui-state-focus: Class to be applied on keyboard focus to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+ .ui-state-active: Class to be applied on mousedown to clickable button-like elements. Applies "clickable active" container styles to an element and its child text, links, and icons.
+*/
+ // Set ui-state-* class (handle the case that the same class is assigned
+ // to different states)
+ classes[opts.activeClass] = false;
+ classes[opts.focusClass] = false;
+ classes[opts.selectedClass] = false;
+ if (node.isActive()) {
+ classes[opts.activeClass] = true;
+ }
+ if (node.hasFocus()) {
+ classes[opts.focusClass] = true;
+ }
+ // activeClass takes precedence before selectedClass:
+ if (node.isSelected() && !node.isActive()) {
+ classes[opts.selectedClass] = true;
+ }
+ $el.toggleClass(opts.activeClass, classes[opts.activeClass]);
+ $el.toggleClass(opts.focusClass, classes[opts.focusClass]);
+ $el.toggleClass(opts.selectedClass, classes[opts.selectedClass]);
+ // Additional classes (e.g. 'ui-corner-all')
+ $el.addClass(opts.addClass);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
+
+/*!
+ * jquery.fancytree.wide.js
+ * Support for 100% wide selection bars.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ var reNumUnit = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/; // split "1.5em" to ["1.5", "em"]
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+ // var _assert = $.ui.fancytree.assert;
+
+ /* Calculate inner width without scrollbar */
+ // function realInnerWidth($el) {
+ // // http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/
+ // // inst.contWidth = parseFloat(this.$container.css("width"), 10);
+ // // 'Client width without scrollbar' - 'padding'
+ // return $el[0].clientWidth - ($el.innerWidth() - parseFloat($el.css("width"), 10));
+ // }
+
+ /* Create a global embedded CSS style for the tree. */
+ function defineHeadStyleElement(id, cssText) {
+ id = "fancytree-style-" + id;
+ var $headStyle = $("#" + id);
+
+ if (!cssText) {
+ $headStyle.remove();
+ return null;
+ }
+ if (!$headStyle.length) {
+ $headStyle = $("<style />")
+ .attr("id", id)
+ .addClass("fancytree-style")
+ .prop("type", "text/css")
+ .appendTo("head");
+ }
+ try {
+ $headStyle.html(cssText);
+ } catch (e) {
+ // fix for IE 6-8
+ $headStyle[0].styleSheet.cssText = cssText;
+ }
+ return $headStyle;
+ }
+
+ /* Calculate the CSS rules that indent title spans. */
+ function renderLevelCss(
+ containerId,
+ depth,
+ levelOfs,
+ lineOfs,
+ labelOfs,
+ measureUnit
+ ) {
+ var i,
+ prefix = "#" + containerId + " span.fancytree-level-",
+ rules = [];
+
+ for (i = 0; i < depth; i++) {
+ rules.push(
+ prefix +
+ (i + 1) +
+ " span.fancytree-title { padding-left: " +
+ (i * levelOfs + lineOfs) +
+ measureUnit +
+ "; }"
+ );
+ }
+ // Some UI animations wrap the UL inside a DIV and set position:relative on both.
+ // This breaks the left:0 and padding-left:nn settings of the title
+ rules.push(
+ "#" +
+ containerId +
+ " div.ui-effects-wrapper ul li span.fancytree-title, " +
+ "#" +
+ containerId +
+ " li.fancytree-animating span.fancytree-title " + // #716
+ "{ padding-left: " +
+ labelOfs +
+ measureUnit +
+ "; position: static; width: auto; }"
+ );
+ return rules.join("\n");
+ }
+
+ // /**
+ // * [ext-wide] Recalculate the width of the selection bar after the tree container
+ // * was resized.<br>
+ // * May be called explicitly on container resize, since there is no resize event
+ // * for DIV tags.
+ // *
+ // * @alias Fancytree#wideUpdate
+ // * @requires jquery.fancytree.wide.js
+ // */
+ // $.ui.fancytree._FancytreeClass.prototype.wideUpdate = function(){
+ // var inst = this.ext.wide,
+ // prevCw = inst.contWidth,
+ // prevLo = inst.lineOfs;
+
+ // inst.contWidth = realInnerWidth(this.$container);
+ // // Each title is precceeded by 2 or 3 icons (16px + 3 margin)
+ // // + 1px title border and 3px title padding
+ // // TODO: use code from treeInit() below
+ // inst.lineOfs = (this.options.checkbox ? 3 : 2) * 19;
+ // if( prevCw !== inst.contWidth || prevLo !== inst.lineOfs ) {
+ // this.debug("wideUpdate: " + inst.contWidth);
+ // this.visit(function(node){
+ // node.tree._callHook("nodeRenderTitle", node);
+ // });
+ // }
+ // };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "wide",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ iconWidth: null, // Adjust this if @fancy-icon-width != "16px"
+ iconSpacing: null, // Adjust this if @fancy-icon-spacing != "3px"
+ labelSpacing: null, // Adjust this if padding between icon and label != "3px"
+ levelOfs: null, // Adjust this if ul padding != "16px"
+ },
+
+ treeCreate: function (ctx) {
+ this._superApply(arguments);
+ this.$container.addClass("fancytree-ext-wide");
+
+ var containerId,
+ cssText,
+ iconSpacingUnit,
+ labelSpacingUnit,
+ iconWidthUnit,
+ levelOfsUnit,
+ instOpts = ctx.options.wide,
+ // css sniffing
+ $dummyLI = $(
+ "<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />"
+ ).appendTo(ctx.tree.$container),
+ $dummyIcon = $dummyLI.find(".fancytree-icon"),
+ $dummyUL = $dummyLI.find("ul"),
+ // $dummyTitle = $dummyLI.find(".fancytree-title"),
+ iconSpacing =
+ instOpts.iconSpacing || $dummyIcon.css("margin-left"),
+ iconWidth = instOpts.iconWidth || $dummyIcon.css("width"),
+ labelSpacing = instOpts.labelSpacing || "3px",
+ levelOfs = instOpts.levelOfs || $dummyUL.css("padding-left");
+
+ $dummyLI.remove();
+
+ iconSpacingUnit = iconSpacing.match(reNumUnit)[2];
+ iconSpacing = parseFloat(iconSpacing, 10);
+ labelSpacingUnit = labelSpacing.match(reNumUnit)[2];
+ labelSpacing = parseFloat(labelSpacing, 10);
+ iconWidthUnit = iconWidth.match(reNumUnit)[2];
+ iconWidth = parseFloat(iconWidth, 10);
+ levelOfsUnit = levelOfs.match(reNumUnit)[2];
+ if (
+ iconSpacingUnit !== iconWidthUnit ||
+ levelOfsUnit !== iconWidthUnit ||
+ labelSpacingUnit !== iconWidthUnit
+ ) {
+ $.error(
+ "iconWidth, iconSpacing, and levelOfs must have the same css measure unit"
+ );
+ }
+ this._local.measureUnit = iconWidthUnit;
+ this._local.levelOfs = parseFloat(levelOfs);
+ this._local.lineOfs =
+ (1 +
+ (ctx.options.checkbox ? 1 : 0) +
+ (ctx.options.icon === false ? 0 : 1)) *
+ (iconWidth + iconSpacing) +
+ iconSpacing;
+ this._local.labelOfs = labelSpacing;
+ this._local.maxDepth = 10;
+
+ // Get/Set a unique Id on the container (if not already exists)
+ containerId = this.$container.uniqueId().attr("id");
+ // Generated css rules for some levels (extended on demand)
+ cssText = renderLevelCss(
+ containerId,
+ this._local.maxDepth,
+ this._local.levelOfs,
+ this._local.lineOfs,
+ this._local.labelOfs,
+ this._local.measureUnit
+ );
+ defineHeadStyleElement(containerId, cssText);
+ },
+ treeDestroy: function (ctx) {
+ // Remove generated css rules
+ defineHeadStyleElement(this.$container.attr("id"), null);
+ return this._superApply(arguments);
+ },
+ nodeRenderStatus: function (ctx) {
+ var containerId,
+ cssText,
+ res,
+ node = ctx.node,
+ level = node.getLevel();
+
+ res = this._super(ctx);
+ // Generate some more level-n rules if required
+ if (level > this._local.maxDepth) {
+ containerId = this.$container.attr("id");
+ this._local.maxDepth *= 2;
+ node.debug(
+ "Define global ext-wide css up to level " +
+ this._local.maxDepth
+ );
+ cssText = renderLevelCss(
+ containerId,
+ this._local.maxDepth,
+ this._local.levelOfs,
+ this._local.lineOfs,
+ this._local.labelSpacing,
+ this._local.measureUnit
+ );
+ defineHeadStyleElement(containerId, cssText);
+ }
+ // Add level-n class to apply indentation padding.
+ // (Setting element style would not work, since it cannot easily be
+ // overriden while animations run)
+ $(node.span).addClass("fancytree-level-" + level);
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all.min.js b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all.min.js
new file mode 100644
index 0000000..977c906
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree-all.min.js
@@ -0,0 +1,62 @@
+/*! jQuery Fancytree Plugin - 2.38.3 - 2023-02-01T20:52:50Z
+ * https://github.com/mar10/fancytree
+ * Copyright (c) 2023 Martin Wendt; Licensed MIT
+ */
+(function( factory ) {
+ if ( typeof define === "function" && define.amd ) {
+ // AMD. Register as an anonymous module.
+ define( [
+ "jquery",
+ "jquery-ui/ui/widgets/mouse",
+ "jquery-ui/ui/widgets/draggable",
+ "jquery-ui/ui/widgets/droppable",
+ "jquery-ui/ui/effects/effect-blind",
+ "jquery-ui/ui/data",
+ "jquery-ui/ui/effect",
+ "jquery-ui/ui/focusable",
+ "jquery-ui/ui/keycode",
+ "jquery-ui/ui/position",
+ "jquery-ui/ui/scroll-parent",
+ "jquery-ui/ui/tabbable",
+ "jquery-ui/ui/unique-id",
+ "jquery-ui/ui/widget"
+ ], factory );
+ } else if ( typeof module === "object" && module.exports ) {
+ // Node/CommonJS
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory( jQuery );
+ }
+}(function( $ ) {
+
+!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree.ui-deps"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree.ui-deps"),module.exports=e(require("jquery"))):e(jQuery)}(function(k){"use strict";if(!k.ui||!k.ui.fancytree){for(var e,h=null,c=new RegExp(/\.|\//),t=/[&<>"'/]/g,n=/[<>"'/]/g,f="$recursive_request",p="$request_target_invalid",i={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;"},r={16:!0,17:!0,18:!0},u={8:"backspace",9:"tab",10:"return",13:"return",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",59:";",61:"=",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},g={16:"shift",17:"ctrl",18:"alt",91:"meta",93:"meta"},o={0:"",1:"left",2:"middle",3:"right"},v="active expanded focus folder lazy radiogroup selected unselectable unselectableIgnore".split(" "),y={},b="columns types".split(" "),m="checkbox expanded extraClasses folder icon iconTooltip key lazy partsel radiogroup refKey selected statusNodeType title tooltip type unselectable unselectableIgnore unselectableStatus".split(" "),s={},x={},a={active:!0,children:!0,data:!0,focus:!0},l=0;l<v.length;l++)y[v[l]]=!0;for(l=0;l<m.length;l++)e=m[l],s[e]=!0,e!==e.toLowerCase()&&(x[e.toLowerCase()]=e);var N=Array.isArray;return _(k.ui,"Fancytree requires jQuery UI (http://jqueryui.com)"),Date.now||(Date.now=function(){return(new Date).getTime()}),I.prototype={_findDirectChild:function(e){var t,n,i=this.children;if(i)if("string"==typeof e){for(t=0,n=i.length;t<n;t++)if(i[t].key===e)return i[t]}else{if("number"==typeof e)return this.children[e];if(e.parent===this)return e}return null},_setChildren:function(e){_(e&&(!this.children||0===this.children.length),"only init supported"),this.children=[];for(var t=0,n=e.length;t<n;t++)this.children.push(new I(this,e[t]));this.tree._callHook("treeStructureChanged",this.tree,"setChildren")},addChildren:function(e,t){var n,i,r,o,s=this.getFirstChild(),a=this.getLastChild(),l=[];for(k.isPlainObject(e)&&(e=[e]),this.children||(this.children=[]),n=0,i=e.length;n<i;n++)l.push(new I(this,e[n]));if(o=l[0],null==t?this.children=this.children.concat(l):(t=this._findDirectChild(t),_(0<=(r=k.inArray(t,this.children)),"insertBefore must be an existing child"),this.children.splice.apply(this.children,[r,0].concat(l))),s&&!t){for(n=0,i=l.length;n<i;n++)l[n].render();s!==this.getFirstChild()&&s.renderStatus(),a!==this.getLastChild()&&a.renderStatus()}else this.parent&&!this.parent.ul&&!this.tr||this.render();return 3===this.tree.options.selectMode&&this.fixSelection3FromEndNodes(),this.triggerModifyChild("add",1===l.length?l[0]:null),o},addClass:function(e){return this.toggleClass(e,!0)},addNode:function(e,t){switch(t=void 0===t||"over"===t?"child":t){case"after":return this.getParent().addChildren(e,this.getNextSibling());case"before":return this.getParent().addChildren(e,this);case"firstChild":var n=this.children?this.children[0]:null;return this.addChildren(e,n);case"child":case"over":return this.addChildren(e)}_(!1,"Invalid mode: "+t)},addPagingNode:function(e,t){var n,i;if(t=t||"child",!1!==e)return e=k.extend({title:this.tree.options.strings.moreData,statusNodeType:"paging",icon:!1},e),this.partload=!0,this.addNode(e,t);for(n=this.children.length-1;0<=n;n--)"paging"===(i=this.children[n]).statusNodeType&&this.removeChild(i);this.partload=!1},appendSibling:function(e){return this.addNode(e,"after")},applyCommand:function(e,t){return this.tree.applyCommand(e,this,t)},applyPatch:function(e){if(null===e)return this.remove(),T(this);var t,n,i={children:!0,expanded:!0,parent:!0};for(t in e)C(e,t)&&(n=e[t],i[t]||w(n)||(s[t]?this[t]=n:this.data[t]=n));return C(e,"children")&&(this.removeChildren(),e.children&&this._setChildren(e.children)),this.isVisible()&&(this.renderTitle(),this.renderStatus()),C(e,"expanded")?this.setExpanded(e.expanded):T(this)},collapseSiblings:function(){return this.tree._callHook("nodeCollapseSiblings",this)},copyTo:function(e,t,n){return e.addNode(this.toDict(!0,n),t)},countChildren:function(e){var t,n,i,r=this.children;if(!r)return 0;if(i=r.length,!1!==e)for(t=0,n=i;t<n;t++)i+=r[t].countChildren();return i},debug:function(e){4<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("log",arguments))},discard:function(){return this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."),this.resetLazy()},discardMarkup:function(e){this.tree._callHook(e?"nodeRemoveMarkup":"nodeRemoveChildMarkup",this)},error:function(e){1<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("error",arguments))},findAll:function(t){t=w(t)?t:R(t);var n=[];return this.visit(function(e){t(e)&&n.push(e)}),n},findFirst:function(t){t=w(t)?t:R(t);var n=null;return this.visit(function(e){if(t(e))return n=e,!1}),n},findRelatedNode:function(e,t){return this.tree.findRelatedNode(this,e,t)},_changeSelectStatusAttrs:function(e){var t=!1,n=this.tree.options,i=h.evalOption("unselectable",this,this,n,!1),n=h.evalOption("unselectableStatus",this,this,n,void 0);switch(e=i&&null!=n?n:e){case!1:t=this.selected||this.partsel,this.selected=!1,this.partsel=!1;break;case!0:t=!this.selected||!this.partsel,this.selected=!0,this.partsel=!0;break;case void 0:t=this.selected||!this.partsel,this.selected=!1,this.partsel=!0;break;default:_(!1,"invalid state: "+e)}return t&&this.renderStatus(),t},fixSelection3AfterClick:function(e){var t=this.isSelected();this.visit(function(e){if(e._changeSelectStatusAttrs(t),e.radiogroup)return"skip"}),this.fixSelection3FromEndNodes(e)},fixSelection3FromEndNodes:function(e){var u=this.tree.options;_(3===u.selectMode,"expected selectMode 3"),function e(t){var n,i,r,o,s,a,l,d,c=t.children;if(c&&c.length){for(l=!(a=!0),n=0,i=c.length;n<i;n++)o=e(r=c[n]),h.evalOption("unselectableIgnore",r,r,u,!1)||(!1!==o&&(l=!0),!0!==o&&(a=!1));s=!!a||!!l&&void 0}else s=null==(d=h.evalOption("unselectableStatus",t,t,u,void 0))?!!t.selected:!!d;return t.partsel&&!t.selected&&t.lazy&&null==t.children&&(s=void 0),t._changeSelectStatusAttrs(s),s}(this),this.visitParents(function(e){for(var t,n,i,r=e.children,o=!0,s=!1,a=0,l=r.length;a<l;a++)t=r[a],h.evalOption("unselectableIgnore",t,t,u,!1)||(((n=null==(i=h.evalOption("unselectableStatus",t,t,u,void 0))?!!t.selected:!!i)||t.partsel)&&(s=!0),n||(o=!1));e._changeSelectStatusAttrs(n=!!o||!!s&&void 0)})},fromDict:function(e){for(var t in e)s[t]?this[t]=e[t]:"data"===t?k.extend(this.data,e.data):w(e[t])||a[t]||(this.data[t]=e[t]);e.children&&(this.removeChildren(),this.addChildren(e.children)),this.renderTitle()},getChildren:function(){if(void 0!==this.hasChildren())return this.children},getFirstChild:function(){return this.children?this.children[0]:null},getIndex:function(){return k.inArray(this,this.parent.children)},getIndexHier:function(e,n){e=e||".";var i,r=[];return k.each(this.getParentList(!1,!0),function(e,t){i=""+(t.getIndex()+1),n&&(i=("0000000"+i).substr(-n)),r.push(i)}),r.join(e)},getKeyPath:function(e){var t=this.tree.options.keyPathSeparator;return t+this.getPath(!e,"key",t)},getLastChild:function(){return this.children?this.children[this.children.length-1]:null},getLevel:function(){for(var e=0,t=this.parent;t;)e++,t=t.parent;return e},getNextSibling:function(){if(this.parent)for(var e=this.parent.children,t=0,n=e.length-1;t<n;t++)if(e[t]===this)return e[t+1];return null},getParent:function(){return this.parent},getParentList:function(e,t){for(var n=[],i=t?this:this.parent;i;)(e||i.parent)&&n.unshift(i),i=i.parent;return n},getPath:function(e,t,n){n=n||"/";var i,r=[],o=w(t=t||"title");return this.visitParents(function(e){e.parent&&(i=o?t(e):e[t],r.unshift(i))},e=!1!==e),r.join(n)},getPrevSibling:function(){if(this.parent)for(var e=this.parent.children,t=1,n=e.length;t<n;t++)if(e[t]===this)return e[t-1];return null},getSelectedNodes:function(t){var n=[];return this.visit(function(e){if(e.selected&&(n.push(e),!0===t))return"skip"}),n},hasChildren:function(){return this.lazy?null==this.children?void 0:0!==this.children.length&&(1!==this.children.length||!this.children[0].isStatusNode()||void 0):!(!this.children||!this.children.length)},hasClass:function(e){return 0<=(" "+(this.extraClasses||"")+" ").indexOf(" "+e+" ")},hasFocus:function(){return this.tree.hasFocus()&&this.tree.focusNode===this},info:function(e){3<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("info",arguments))},isActive:function(){return this.tree.activeNode===this},isBelowOf:function(e){return this.getIndexHier(".",5)>e.getIndexHier(".",5)},isChildOf:function(e){return this.parent&&this.parent===e},isDescendantOf:function(e){if(!e||e.tree!==this.tree)return!1;for(var t=this.parent;t;){if(t===e)return!0;t===t.parent&&k.error("Recursive parent link: "+t),t=t.parent}return!1},isExpanded:function(){return!!this.expanded},isFirstSibling:function(){var e=this.parent;return!e||e.children[0]===this},isFolder:function(){return!!this.folder},isLastSibling:function(){var e=this.parent;return!e||e.children[e.children.length-1]===this},isLazy:function(){return!!this.lazy},isLoaded:function(){return!this.lazy||void 0!==this.hasChildren()},isLoading:function(){return!!this._isLoading},isRoot:function(){return this.isRootNode()},isPartsel:function(){return!this.selected&&!!this.partsel},isPartload:function(){return!!this.partload},isRootNode:function(){return this.tree.rootNode===this},isSelected:function(){return!!this.selected},isStatusNode:function(){return!!this.statusNodeType},isPagingNode:function(){return"paging"===this.statusNodeType},isTopLevel:function(){return this.tree.rootNode===this.parent},isUndefined:function(){return void 0===this.hasChildren()},isVisible:function(){var e,t,n=this.tree.enableFilter,i=this.getParentList(!1,!1);if(n&&!this.match&&!this.subMatchCount)return!1;for(e=0,t=i.length;e<t;e++)if(!i[e].expanded)return!1;return!0},lazyLoad:function(e){k.error("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead.")},load:function(e){var t=this,n=this.isExpanded();return _(this.isLazy(),"load() requires a lazy node"),e||this.isUndefined()?(this.isLoaded()&&this.resetLazy(),!1===(e=this.tree._triggerNodeEvent("lazyLoad",this))?T(this):(_("boolean"!=typeof e,"lazyLoad event must return source in data.result"),e=this.tree._callHook("nodeLoadChildren",this,e),n?(this.expanded=!0,e.always(function(){t.render()})):e.always(function(){t.renderStatus()}),e)):T(this)},makeVisible:function(e){for(var t=this,n=[],i=new k.Deferred,r=this.getParentList(!1,!1),o=r.length,s=!(e&&!0===e.noAnimation),a=!(e&&!1===e.scrollIntoView),l=o-1;0<=l;l--)n.push(r[l].setExpanded(!0,e));return k.when.apply(k,n).done(function(){a?t.scrollIntoView(s).done(function(){i.resolve()}):i.resolve()}),i.promise()},moveTo:function(t,e,n){void 0===e||"over"===e?e="child":"firstChild"===e&&(t.children&&t.children.length?(e="before",t=t.children[0]):e="child");var i,r=this.tree,o=this.parent,s="child"===e?t:t.parent;if(this!==t){if(this.parent?s.isDescendantOf(this)&&k.error("Cannot move a node to its own descendant"):k.error("Cannot move system root"),s!==o&&o.triggerModifyChild("remove",this),1===this.parent.children.length){if(this.parent===s)return;this.parent.children=this.parent.lazy?[]:null,this.parent.expanded=!1}else _(0<=(i=k.inArray(this,this.parent.children)),"invalid source parent"),this.parent.children.splice(i,1);if((this.parent=s).hasChildren())switch(e){case"child":s.children.push(this);break;case"before":_(0<=(i=k.inArray(t,s.children)),"invalid target parent"),s.children.splice(i,0,this);break;case"after":_(0<=(i=k.inArray(t,s.children)),"invalid target parent"),s.children.splice(i+1,0,this);break;default:k.error("Invalid mode "+e)}else s.children=[this];n&&t.visit(n,!0),s===o?s.triggerModifyChild("move",this):s.triggerModifyChild("add",this),r!==t.tree&&(this.warn("Cross-tree moveTo is experimental!"),this.visit(function(e){e.tree=t.tree},!0)),r._callHook("treeStructureChanged",r,"moveTo"),o.isDescendantOf(s)||o.render(),s.isDescendantOf(o)||s===o||s.render()}},navigate:function(e,t){var n=k.ui.keyCode;switch(e){case"left":case n.LEFT:if(this.expanded)return this.setExpanded(!1);break;case"right":case n.RIGHT:if(!this.expanded&&(this.children||this.lazy))return this.setExpanded()}if(n=this.findRelatedNode(e)){try{n.makeVisible({scrollIntoView:!1})}catch(e){}return!1===t?(n.setFocus(),T()):n.setActive()}return this.warn("Could not find related node '"+e+"'."),T()},remove:function(){return this.parent.removeChild(this)},removeChild:function(e){return this.tree._callHook("nodeRemoveChild",this,e)},removeChildren:function(){return this.tree._callHook("nodeRemoveChildren",this)},removeClass:function(e){return this.toggleClass(e,!1)},render:function(e,t){return this.tree._callHook("nodeRender",this,e,t)},renderTitle:function(){return this.tree._callHook("nodeRenderTitle",this)},renderStatus:function(){return this.tree._callHook("nodeRenderStatus",this)},replaceWith:function(e){var n=this.parent,i=k.inArray(this,n.children),r=this;return _(this.isPagingNode(),"replaceWith() currently requires a paging status node"),(e=this.tree._callHook("nodeLoadChildren",this,e)).done(function(e){var t=r.children;for(l=0;l<t.length;l++)t[l].parent=n;n.children.splice.apply(n.children,[i+1,0].concat(t)),r.children=null,r.remove(),n.render()}).fail(function(){r.setExpanded()}),e},resetLazy:function(){this.removeChildren(),this.expanded=!1,this.lazy=!0,this.children=void 0,this.renderStatus()},scheduleAction:function(e,t){this.tree.timer&&(clearTimeout(this.tree.timer),this.tree.debug("clearTimeout(%o)",this.tree.timer)),this.tree.timer=null;var n=this;switch(e){case"cancel":break;case"expand":this.tree.timer=setTimeout(function(){n.tree.debug("setTimeout: trigger expand"),n.setExpanded(!0)},t);break;case"activate":this.tree.timer=setTimeout(function(){n.tree.debug("setTimeout: trigger activate"),n.setActive(!0)},t);break;default:k.error("Invalid mode "+e)}},scrollIntoView:function(e,t){if(void 0!==t&&((p=t).tree&&void 0!==p.statusNodeType))throw Error("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead.");var n=k.extend({effects:!0===e?{duration:200,queue:!1}:e,scrollOfs:this.tree.options.scrollOfs,scrollParent:this.tree.options.scrollParent,topNode:null},t),i=n.scrollParent,r=this.tree.$container,o=r.css("overflow-y");i?i.jquery||(i=k(i)):i=!this.tree.tbody&&("scroll"===o||"auto"===o)?r:r.scrollParent(),i[0]!==document&&i[0]!==document.body||(this.debug("scrollIntoView(): normalizing scrollParent to 'window':",i[0]),i=k(window));var s,a,l=new k.Deferred,d=this,c=k(this.span).height(),u=n.scrollOfs.top||0,h=n.scrollOfs.bottom||0,f=i.height(),p=i.scrollTop(),e=i,t=i[0]===window,o=n.topNode||null,r=null;return this.isRootNode()||!this.isVisible()?(this.info("scrollIntoView(): node is invisible."),T()):(t?(a=k(this.span).offset().top,s=o&&o.span?k(o.span).offset().top:0,e=k("html,body")):(_(i[0]!==document&&i[0]!==document.body,"scrollParent should be a simple element or `window`, not document or body."),t=i.offset().top,a=k(this.span).offset().top-t+p,s=o?k(o.span).offset().top-t+p:0,f-=Math.max(0,i.innerHeight()-i[0].clientHeight)),a<p+u?r=a-u:p+f-h<a+c&&(r=a+c-f+h,o&&(_(o.isRootNode()||o.isVisible(),"topNode must be visible"),s<r&&(r=s-u))),null===r?l.resolveWith(this):n.effects?(n.effects.complete=function(){l.resolveWith(d)},e.stop(!0).animate({scrollTop:r},n.effects)):(e[0].scrollTop=r,l.resolveWith(this)),l.promise())},setActive:function(e,t){return this.tree._callHook("nodeSetActive",this,e,t)},setExpanded:function(e,t){return this.tree._callHook("nodeSetExpanded",this,e,t)},setFocus:function(e){return this.tree._callHook("nodeSetFocus",this,e)},setSelected:function(e,t){return this.tree._callHook("nodeSetSelected",this,e,t)},setStatus:function(e,t,n){return this.tree._callHook("nodeSetStatus",this,e,t,n)},setTitle:function(e){this.title=e,this.renderTitle(),this.triggerModify("rename")},sortChildren:function(e,t){var n,i,r=this.children;if(r){if(r.sort(e=e||function(e,t){e=e.title.toLowerCase(),t=t.title.toLowerCase();return e===t?0:t<e?1:-1}),t)for(n=0,i=r.length;n<i;n++)r[n].children&&r[n].sortChildren(e,"$norender$");"$norender$"!==t&&this.render(),this.triggerModifyChild("sort")}},toDict:function(e,t){var n,i,r,o,s={},a=this;if(k.each(m,function(e,t){!a[t]&&!1!==a[t]||(s[t]=a[t])}),k.isEmptyObject(this.data)||(s.data=k.extend({},this.data),k.isEmptyObject(s.data)&&delete s.data),t){if(!1===(o=t(s,a)))return!1;"skip"===o&&(e=!1)}if(e&&N(this.children))for(s.children=[],n=0,i=this.children.length;n<i;n++)(r=this.children[n]).isStatusNode()||!1!==(o=r.toDict(!0,t))&&s.children.push(o);return s},toggleClass:function(e,t){var n,i,r=e.match(/\S+/g)||[],o=0,s=!1,a=this[this.tree.statusClassPropName],l=" "+(this.extraClasses||"")+" ";for(a&&k(a).toggleClass(e,t);n=r[o++];)if(i=0<=l.indexOf(" "+n+" "),t=void 0===t?!i:!!t)i||(l+=n+" ",s=!0);else for(;-1<l.indexOf(" "+n+" ");)l=l.replace(" "+n+" "," ");return this.extraClasses=S(l),s},toggleExpanded:function(){return this.tree._callHook("nodeToggleExpanded",this)},toggleSelected:function(){return this.tree._callHook("nodeToggleSelected",this)},toString:function(){return"FancytreeNode@"+this.key+"[title='"+this.title+"']"},triggerModifyChild:function(e,t,n){var i=this.tree.options.modifyChild;i&&(t&&t.parent!==this&&k.error("childNode "+t+" is not a child of "+this),t={node:this,tree:this.tree,operation:e,childNode:t||null},n&&k.extend(t,n),i({type:"modifyChild"},t))},triggerModify:function(e,t){this.parent.triggerModifyChild(e,this,t)},visit:function(e,t){var n,i,r=!0,o=this.children;if(!0===t&&(!1===(r=e(this))||"skip"===r))return r;if(o)for(n=0,i=o.length;n<i&&!1!==(r=o[n].visit(e,!0));n++);return r},visitAndLoad:function(n,e,t){var i,r,o,s=this;return!n||!0!==e||!1!==(r=n(s))&&"skip"!==r?s.children||s.lazy?(i=new k.Deferred,o=[],s.load().done(function(){for(var e=0,t=s.children.length;e<t;e++){if(!1===(r=s.children[e].visitAndLoad(n,!0,!0))){i.reject();break}"skip"!==r&&o.push(r)}k.when.apply(this,o).then(function(){i.resolve()})}),i.promise()):T():t?r:T()},visitParents:function(e,t){if(t&&!1===e(this))return!1;for(var n=this.parent;n;){if(!1===e(n))return!1;n=n.parent}return!0},visitSiblings:function(e,t){for(var n,i=this.parent.children,r=0,o=i.length;r<o;r++)if(n=i[r],(t||n!==this)&&!1===e(n))return!1;return!0},warn:function(e){2<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("warn",arguments))}},F.prototype={_makeHookContext:function(e,t,n){var i,r;return void 0!==e.node?(t&&e.originalEvent!==t&&k.error("invalid args"),i=e):e.tree?i={node:e,tree:r=e.tree,widget:r.widget,options:r.widget.options,originalEvent:t,typeInfo:r.types[e.type]||{}}:e.widget?i={node:null,tree:e,widget:e.widget,options:e.widget.options,originalEvent:t}:k.error("invalid args"),n&&k.extend(i,n),i},_callHook:function(e,t,n){var i=this._makeHookContext(t),r=this[e],t=Array.prototype.slice.call(arguments,2);return w(r)||k.error("_callHook('"+e+"') is not a function"),t.unshift(i),r.apply(this,t)},_setExpiringValue:function(e,t,n){this._tempCache[e]={value:t,expire:Date.now()+(+n||50)}},_getExpiringValue:function(e){var t=this._tempCache[e];return t&&t.expire>Date.now()?t.value:(delete this._tempCache[e],null)},_usesExtension:function(e){return 0<=k.inArray(e,this.options.extensions)},_requireExtension:function(e,t,n,i){null!=n&&(n=!!n);var r=this._local.name,o=this.options.extensions,s=k.inArray(e,o)<k.inArray(r,o),o=t&&null==this.ext[e],s=!o&&null!=n&&n!==s;return _(r&&r!==e,"invalid or same name '"+r+"' (require yourself?)"),!o&&!s||(i||(o||t?(i="'"+r+"' extension requires '"+e+"'",s&&(i+=" to be registered "+(n?"before":"after")+" itself")):i="If used together, `"+e+"` must be registered "+(n?"before":"after")+" `"+r+"`"),k.error(i),!1)},activateKey:function(e,t){e=this.getNodeByKey(e);return e?e.setActive(!0,t):this.activeNode&&this.activeNode.setActive(!1,t),e},addPagingNode:function(e,t){return this.rootNode.addPagingNode(e,t)},applyCommand:function(e,t,n){var i;switch(t=t||this.getActiveNode(),e){case"moveUp":(i=t.getPrevSibling())&&(t.moveTo(i,"before"),t.setActive());break;case"moveDown":(i=t.getNextSibling())&&(t.moveTo(i,"after"),t.setActive());break;case"indent":(i=t.getPrevSibling())&&(t.moveTo(i,"child"),i.setExpanded(),t.setActive());break;case"outdent":t.isTopLevel()||(t.moveTo(t.getParent(),"after"),t.setActive());break;case"remove":i=t.getPrevSibling()||t.getParent(),t.remove(),i&&i.setActive();break;case"addChild":t.editCreateNode("child","");break;case"addSibling":t.editCreateNode("after","");break;case"rename":t.editStart();break;case"down":case"first":case"last":case"left":case"parent":case"right":case"up":return t.navigate(e);default:k.error("Unhandled command: '"+e+"'")}},applyPatch:function(e){for(var t,n,i,r,o=e.length,s=[],a=0;a<o;a++)_(2===(t=e[a]).length,"patchList must be an array of length-2-arrays"),n=t[0],i=t[1],(r=null===n?this.rootNode:this.getNodeByKey(n))?(t=new k.Deferred,s.push(t),r.applyPatch(i).always(A(t,r))):this.warn("could not find node with key '"+n+"'");return k.when.apply(k,s).promise()},clear:function(e){this._callHook("treeClear",this)},count:function(){return this.rootNode.countChildren()},debug:function(e){4<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("log",arguments))},destroy:function(){this.widget.destroy()},enable:function(e){!1===e?this.widget.disable():this.widget.enable()},enableUpdate:function(e){return!!this._enableUpdate==!!(e=!1!==e)?e:((this._enableUpdate=e)?(this.debug("enableUpdate(true): redraw "),this._callHook("treeStructureChanged",this,"enableUpdate"),this.render()):this.debug("enableUpdate(false)..."),!e)},error:function(e){1<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("error",arguments))},expandAll:function(t,n){var e=this.enableUpdate(!1);t=!1!==t,this.visit(function(e){!1!==e.hasChildren()&&e.isExpanded()!==t&&e.setExpanded(t,n)}),this.enableUpdate(e)},findAll:function(e){return this.rootNode.findAll(e)},findFirst:function(e){return this.rootNode.findFirst(e)},findNextNode:function(t,n){var i,r=null,e=this.getFirstChild();function o(e){if((r=t(e)?e:r)||e===n)return!1}return t="string"==typeof t?(i=new RegExp("^"+t,"i"),function(e){return i.test(e.title)}):t,this.visitRows(o,{start:n=n||e,includeSelf:!1}),r||n===e||this.visitRows(o,{start:e,includeSelf:!0}),r},findRelatedNode:function(e,t,n){var i=null,r=k.ui.keyCode;switch(t){case"parent":case r.BACKSPACE:e.parent&&e.parent.parent&&(i=e.parent);break;case"first":case r.HOME:this.visit(function(e){if(e.isVisible())return i=e,!1});break;case"last":case r.END:this.visit(function(e){e.isVisible()&&(i=e)});break;case"left":case r.LEFT:e.expanded?e.setExpanded(!1):e.parent&&e.parent.parent&&(i=e.parent);break;case"right":case r.RIGHT:e.expanded||!e.children&&!e.lazy?e.children&&e.children.length&&(i=e.children[0]):(e.setExpanded(),i=e);break;case"up":case r.UP:this.visitRows(function(e){return i=e,!1},{start:e,reverse:!0,includeSelf:!1});break;case"down":case r.DOWN:this.visitRows(function(e){return i=e,!1},{start:e,includeSelf:!1});break;default:this.tree.warn("Unknown relation '"+t+"'.")}return i},generateFormElements:function(e,t,n){n=n||{};var i="string"==typeof e?e:"ft_"+this._id+"[]",r="string"==typeof t?t:"ft_"+this._id+"_active",o="fancytree_result_"+this._id,s=k("#"+o),a=3===this.options.selectMode&&!1!==n.stopOnParents;function l(e){s.append(k("<input>",{type:"checkbox",name:i,value:e.key,checked:!0}))}s.length?s.empty():s=k("<div>",{id:o}).hide().insertAfter(this.$container),!1!==t&&this.activeNode&&s.append(k("<input>",{type:"radio",name:r,value:this.activeNode.key,checked:!0})),n.filter?this.visit(function(e){var t=n.filter(e);if("skip"===t)return t;!1!==t&&l(e)}):!1!==e&&(a=this.getSelectedNodes(a),k.each(a,function(e,t){l(t)}))},getActiveNode:function(){return this.activeNode},getFirstChild:function(){return this.rootNode.getFirstChild()},getFocusNode:function(){return this.focusNode},getOption:function(e){return this.widget.option(e)},getNodeByKey:function(t,e){var n,i;return!e&&(n=document.getElementById(this.options.idPrefix+t))?n.ftnode||null:(e=e||this.rootNode,t=""+t,e.visit(function(e){if(e.key===t)return i=e,!1},!(i=null)),i)},getRootNode:function(){return this.rootNode},getSelectedNodes:function(e){return this.rootNode.getSelectedNodes(e)},hasFocus:function(){return!!this._hasFocus},info:function(e){3<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("info",arguments))},isLoading:function(){var t=!1;return this.rootNode.visit(function(e){if(e._isLoading||e._requestId)return!(t=!0)},!0),t},loadKeyPath:function(e,t){var i,n,r,o=this,s=new k.Deferred,a=this.getRootNode(),l=this.options.keyPathSeparator,d=[],c=k.extend({},t);for("function"==typeof t?i=t:t&&t.callback&&(i=t.callback),c.callback=function(e,t,n){i&&i.call(e,t,n),s.notifyWith(e,[{node:t,status:n}])},null==c.matchKey&&(c.matchKey=function(e,t){return e.key===t}),N(e)||(e=[e]),n=0;n<e.length;n++)(r=e[n]).charAt(0)===l&&(r=r.substr(1)),d.push(r.split(l));return setTimeout(function(){o._loadKeyPathImpl(s,c,a,d).done(function(){s.resolve()})},0),s.promise()},_loadKeyPathImpl:function(e,o,t,n){var i,r,s,a,l,d,c,u,h,f,p=this;for(c={},r=0;r<n.length;r++)for(h=n[r],u=t;h.length;){if(s=h.shift(),!(a=function(e,t){var n,i,r=e.children;if(r)for(n=0,i=r.length;n<i;n++)if(o.matchKey(r[n],t))return r[n];return null}(u,s))){this.warn("loadKeyPath: key not found: "+s+" (parent: "+u+")"),o.callback(this,s,"error");break}if(0===h.length){o.callback(this,a,"ok");break}if(a.lazy&&void 0===a.hasChildren()){o.callback(this,a,"loaded"),c[s=a.key]?c[s].pathSegList.push(h):c[s]={parent:a,pathSegList:[h]};break}o.callback(this,a,"loaded"),u=a}for(l in i=[],c)C(c,l)&&(d=c[l],f=new k.Deferred,i.push(f),function(t,n,e){o.callback(p,n,"loading"),n.load().done(function(){p._loadKeyPathImpl.call(p,t,o,n,e).always(A(t,p))}).fail(function(e){p.warn("loadKeyPath: error loading lazy "+n),o.callback(p,a,"error"),t.rejectWith(p)})}(f,d.parent,d.pathSegList));return k.when.apply(k,i).promise()},reactivate:function(e){var t,n=this.activeNode;return n?(this.activeNode=null,t=n.setActive(!0,{noFocus:!0}),e&&n.setFocus(),t):T()},reload:function(e){return this._callHook("treeClear",this),this._callHook("treeLoad",this,e)},render:function(e,t){return this.rootNode.render(e,t)},selectAll:function(t){this.visit(function(e){e.setSelected(t)})},setFocus:function(e){return this._callHook("treeSetFocus",this,e)},setOption:function(e,t){return this.widget.option(e,t)},debugTime:function(e){4<=this.options.debugLevel&&window.console.time(this+" - "+e)},debugTimeEnd:function(e){4<=this.options.debugLevel&&window.console.timeEnd(this+" - "+e)},toDict:function(e,t){t=this.rootNode.toDict(!0,t);return e?t:t.children},toString:function(){return"Fancytree@"+this._id},_triggerNodeEvent:function(e,t,n,i){i=this._makeHookContext(t,n,i),n=this.widget._trigger(e,n,i);return!1!==n&&void 0!==i.result?i.result:n},_triggerTreeEvent:function(e,t,n){n=this._makeHookContext(this,t,n),t=this.widget._trigger(e,t,n);return!1!==t&&void 0!==n.result?n.result:t},visit:function(e){return this.rootNode.visit(e,!1)},visitRows:function(t,e){if(!this.rootNode.hasChildren())return!1;if(e&&e.reverse)return delete e.reverse,this._visitRowsUp(t,e);for(var n,i,r,o=0,s=!1===(e=e||{}).includeSelf,a=!!e.includeHidden,l=!a&&this.enableFilter,d=e.start||this.rootNode.children[0],c=d.parent;c;){for(_(0<=(i=(r=c.children).indexOf(d)+o),"Could not find "+d+" in parent's children: "+c),n=i;n<r.length;n++)if(d=r[n],!l||d.match||d.subMatchCount){if(!s&&!1===t(d))return!1;if(s=!1,d.children&&d.children.length&&(a||d.expanded)&&!1===d.visit(function(e){return!l||e.match||e.subMatchCount?!1!==t(e)&&(a||!e.children||e.expanded?void 0:"skip"):"skip"},!1))return!1}c=(d=c).parent,o=1}return!0},_visitRowsUp:function(e,t){for(var n,i,r,o=!!t.includeHidden,s=t.start||this.rootNode.children[0];;){if((n=(r=s.parent).children)[0]===s){if(!(s=r).parent)break;n=r.children}else for(i=n.indexOf(s),s=n[i-1];(o||s.expanded)&&s.children&&s.children.length;)s=(n=(r=s).children)[n.length-1];if((o||s.isVisible())&&!1===e(s))return!1}},warn:function(e){2<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("warn",arguments))}},k.extend(F.prototype,{nodeClick:function(e){var t,n,i=e.targetType,r=e.node;if("expander"===i)r.isLoading()?r.debug("Got 2nd click while loading: ignored"):this._callHook("nodeToggleExpanded",e);else if("checkbox"===i)this._callHook("nodeToggleSelected",e),e.options.focusOnSelect&&this._callHook("nodeSetFocus",e,!0);else{if(t=!(n=!1),r.folder)switch(e.options.clickFolderMode){case 2:t=!(n=!0);break;case 3:n=t=!0}t&&(this.nodeSetFocus(e),this._callHook("nodeSetActive",e,!0)),n&&this._callHook("nodeToggleExpanded",e)}},nodeCollapseSiblings:function(e,t){var n,i,r,o=e.node;if(o.parent)for(i=0,r=(n=o.parent.children).length;i<r;i++)n[i]!==o&&n[i].expanded&&this._callHook("nodeSetExpanded",n[i],!1,t)},nodeDblclick:function(e){"title"===e.targetType&&4===e.options.clickFolderMode&&this._callHook("nodeToggleExpanded",e),"title"===e.targetType&&e.originalEvent.preventDefault()},nodeKeydown:function(e){var t=e.originalEvent,n=e.node,i=e.tree,r=e.options,o=t.which,s=t.key||String.fromCharCode(o),a=!!(t.altKey||t.ctrlKey||t.metaKey),l=!g[o]&&!u[o]&&!a,o=k(t.target),d=!0,c=!(t.ctrlKey||!r.autoActivate);if(n||(a=this.getActiveNode()||this.getFirstChild())&&(a.setFocus(),(n=e.node=this.focusNode).debug("Keydown force focus on active node")),r.quicksearch&&l&&!o.is(":input:enabled"))return 500<(o=Date.now())-i.lastQuicksearchTime&&(i.lastQuicksearchTerm=""),i.lastQuicksearchTime=o,i.lastQuicksearchTerm+=s,(s=i.findNextNode(i.lastQuicksearchTerm,i.getActiveNode()))&&s.setActive(),void t.preventDefault();switch(h.eventToString(t)){case"+":case"=":i.nodeSetExpanded(e,!0);break;case"-":i.nodeSetExpanded(e,!1);break;case"space":n.isPagingNode()?i._triggerNodeEvent("clickPaging",e,t):h.evalOption("checkbox",n,n,r,!1)?i.nodeToggleSelected(e):i.nodeSetActive(e,!0);break;case"return":i.nodeSetActive(e,!0);break;case"home":case"end":case"backspace":case"left":case"right":case"up":case"down":n.navigate(t.which,c);break;default:d=!1}d&&t.preventDefault()},nodeLoadChildren:function(o,s){var t,n,a,e=null,i=!0,l=o.tree,d=o.node,c=d.parent,r="nodeLoadChildren",u=Date.now();return w(s)&&_(!w(s=s.call(l,{type:"source"},o)),"source callback must not return another function"),w(s.then)?e=s:s.url?e=(t=k.extend({},o.options.ajax,s)).debugDelay?(n=t.debugDelay,delete t.debugDelay,N(n)&&(n=n[0]+Math.random()*(n[1]-n[0])),d.warn("nodeLoadChildren waiting debugDelay "+Math.round(n)+" ms ..."),k.Deferred(function(e){setTimeout(function(){k.ajax(t).done(function(){e.resolveWith(this,arguments)}).fail(function(){e.rejectWith(this,arguments)})},n)})):k.ajax(t):k.isPlainObject(s)||N(s)?i=!(e={then:function(e,t){e(s,null,null)}}):k.error("Invalid source type: "+s),d._requestId&&(d.warn("Recursive load request #"+u+" while #"+d._requestId+" is pending."),d._requestId=u),i&&(l.debugTime(r),l.nodeSetStatus(o,"loading")),a=new k.Deferred,e.then(function(e,t,n){var i,r;if("json"!==s.dataType&&"jsonp"!==s.dataType||"string"!=typeof e||k.error("Ajax request returned a string (did you get the JSON dataType wrong?)."),d._requestId&&d._requestId>u)a.rejectWith(this,[f]);else if(null!==d.parent||null===c){if(o.options.postProcess){try{(r=l._triggerNodeEvent("postProcess",o,o.originalEvent,{response:e,error:null,dataType:s.dataType})).error&&l.warn("postProcess returned error:",r)}catch(e){r={error:e,message:""+e,details:"postProcess failed"}}if(r.error)return i=k.isPlainObject(r.error)?r.error:{message:r.error},i=l._makeHookContext(d,null,i),void a.rejectWith(this,[i]);(N(r)||k.isPlainObject(r)&&N(r.children))&&(e=r)}else e&&C(e,"d")&&o.options.enableAspx&&(42===o.options.enableAspx&&l.warn("The default for enableAspx will change to `false` in the fututure. Pass `enableAspx: true` or implement postProcess to silence this warning."),e="string"==typeof e.d?k.parseJSON(e.d):e.d);a.resolveWith(this,[e])}else a.rejectWith(this,[p])},function(e,t,n){n=l._makeHookContext(d,null,{error:e,args:Array.prototype.slice.call(arguments),message:n,details:e.status+": "+n});a.rejectWith(this,[n])}),a.done(function(e){var t,n,i;l.nodeSetStatus(o,"ok"),k.isPlainObject(e)?(_(d.isRootNode(),"source may only be an object for root nodes (expecting an array of child objects otherwise)"),_(N(e.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),t=(n=e).children,delete n.children,k.each(b,function(e,t){void 0!==n[t]&&(l[t]=n[t],delete n[t])}),k.extend(l.data,n)):t=e,_(N(t),"expected array of children"),d._setChildren(t),l.options.nodata&&0===t.length&&(w(l.options.nodata)?i=l.options.nodata.call(l,{type:"nodata"},o):!0===l.options.nodata&&d.isRootNode()?i=l.options.strings.noData:"string"==typeof l.options.nodata&&d.isRootNode()&&(i=l.options.nodata),i&&d.setStatus("nodata",i)),l._triggerNodeEvent("loadChildren",d)}).fail(function(e){var t;e!==f?e!==p?(e.node&&e.error&&e.message?t=e:"[object Object]"===(t=l._makeHookContext(d,null,{error:e,args:Array.prototype.slice.call(arguments),message:e?e.message||e.toString():""})).message&&(t.message=""),d.warn("Load children failed ("+t.message+")",t),!1!==l._triggerNodeEvent("loadError",t,null)&&l.nodeSetStatus(o,"error",t.message,t.details)):d.warn("Lazy parent node was removed while loading: discarding response."):d.warn("Ignored response for obsolete load request #"+u+" (expected #"+d._requestId+")")}).always(function(){d._requestId=null,i&&l.debugTimeEnd(r)}),a.promise()},nodeLoadKeyPath:function(e,t){},nodeRemoveChild:function(e,t){var n=e.node,i=k.extend({},e,{node:t}),r=n.children;if(1===r.length)return _(t===r[0],"invalid single child"),this.nodeRemoveChildren(e);this.activeNode&&(t===this.activeNode||this.activeNode.isDescendantOf(t))&&this.activeNode.setActive(!1),this.focusNode&&(t===this.focusNode||this.focusNode.isDescendantOf(t))&&(this.focusNode=null),this.nodeRemoveMarkup(i),this.nodeRemoveChildren(i),_(0<=(i=k.inArray(t,r)),"invalid child"),n.triggerModifyChild("remove",t),t.visit(function(e){e.parent=null},!0),this._callHook("treeRegisterNode",this,!1,t),r.splice(i,1)},nodeRemoveChildMarkup:function(e){e=e.node;e.ul&&(e.isRootNode()?k(e.ul).empty():(k(e.ul).remove(),e.ul=null),e.visit(function(e){e.li=e.ul=null}))},nodeRemoveChildren:function(e){var t=e.tree,n=e.node;n.children&&(this.activeNode&&this.activeNode.isDescendantOf(n)&&this.activeNode.setActive(!1),this.focusNode&&this.focusNode.isDescendantOf(n)&&(this.focusNode=null),this.nodeRemoveChildMarkup(e),n.triggerModifyChild("remove",null),n.visit(function(e){e.parent=null,t._callHook("treeRegisterNode",t,!1,e)}),n.lazy?n.children=[]:n.children=null,n.isRootNode()||(n.expanded=!1),this.nodeRenderStatus(e))},nodeRemoveMarkup:function(e){var t=e.node;t.li&&(k(t.li).remove(),t.li=null),this.nodeRemoveChildMarkup(e)},nodeRender:function(e,t,n,i,r){var o,s,a,l,d,c,u,h=e.node,f=e.tree,p=e.options,g=p.aria,v=!1,y=h.parent,b=!y,m=h.children,x=null;if(!1!==f._enableUpdate&&(b||y.ul)){if(_(b||y.ul,"parent UL must exist"),b||(h.li&&(t||h.li.parentNode!==h.parent.ul)&&(h.li.parentNode===h.parent.ul?x=h.li.nextSibling:this.debug("Unlinking "+h+" (must be child of "+h.parent+")"),this.nodeRemoveMarkup(e)),h.li?this.nodeRenderStatus(e):(v=!0,h.li=document.createElement("li"),(h.li.ftnode=h).key&&p.generateIds&&(h.li.id=p.idPrefix+h.key),h.span=document.createElement("span"),h.span.className="fancytree-node",g&&!h.tr&&k(h.li).attr("role","treeitem"),h.li.appendChild(h.span),this.nodeRenderTitle(e),p.createNode&&p.createNode.call(f,{type:"createNode"},e)),p.renderNode&&p.renderNode.call(f,{type:"renderNode"},e)),m){if(b||h.expanded||!0===n){for(h.ul||(h.ul=document.createElement("ul"),(!0!==i||r)&&h.expanded||(h.ul.style.display="none"),g&&k(h.ul).attr("role","group"),h.li?h.li.appendChild(h.ul):h.tree.$div.append(h.ul)),l=0,d=m.length;l<d;l++)u=k.extend({},e,{node:m[l]}),this.nodeRender(u,t,n,!1,!0);for(o=h.ul.firstChild;o;)o=(a=o.ftnode)&&a.parent!==h?(h.debug("_fixParent: remove missing "+a,o),c=o.nextSibling,o.parentNode.removeChild(o),c):o.nextSibling;for(o=h.ul.firstChild,l=0,d=m.length-1;l<d;l++)(s=m[l])===(a=o.ftnode)?o=o.nextSibling:h.ul.insertBefore(s.li,a.li)}}else h.ul&&(this.warn("remove child markup for "+h),this.nodeRemoveChildMarkup(e));b||v&&y.ul.insertBefore(h.li,x)}},nodeRenderTitle:function(e,t){var n,i,r=e.node,o=e.tree,s=e.options,a=s.aria,l=r.getLevel(),d=[];void 0!==t&&(r.title=t),r.span&&!1!==o._enableUpdate&&(t=a&&!1!==r.hasChildren()?" role='button'":"",l<s.minExpandLevel?(r.lazy||(r.expanded=!0),1<l&&d.push("<span "+t+" class='fancytree-expander fancytree-expander-fixed'></span>")):d.push("<span "+t+" class='fancytree-expander'></span>"),(l=h.evalOption("checkbox",r,r,s,!1))&&!r.isStatusNode()&&(n="fancytree-checkbox",("radio"===l||r.parent&&r.parent.radiogroup)&&(n+=" fancytree-radio"),d.push("<span "+(t=a?" role='checkbox'":"")+" class='"+n+"'></span>")),void 0!==r.data.iconClass&&(r.icon?k.error("'iconClass' node option is deprecated since v2.14.0: use 'icon' only instead"):(r.warn("'iconClass' node option is deprecated since v2.14.0: use 'icon' instead"),r.icon=r.data.iconClass)),!1!==(n=h.evalOption("icon",r,r,s,!0))&&(t=a?" role='presentation'":"",i=(i=h.evalOption("iconTooltip",r,r,s,null))?" title='"+P(i)+"'":"","string"==typeof n?c.test(n)?(n="/"===n.charAt(0)?n:(s.imagePath||"")+n,d.push("<img src='"+n+"' class='fancytree-icon'"+i+" alt='' />")):d.push("<span "+t+" class='fancytree-custom-icon "+n+"'"+i+"></span>"):n.text?d.push("<span "+t+" class='fancytree-custom-icon "+(n.addClass||"")+"'"+i+">"+h.escapeHtml(n.text)+"</span>"):n.html?d.push("<span "+t+" class='fancytree-custom-icon "+(n.addClass||"")+"'"+i+">"+n.html+"</span>"):d.push("<span "+t+" class='fancytree-icon'"+i+"></span>")),t="",t=(t=s.renderTitle?s.renderTitle.call(o,{type:"renderTitle"},e)||"":t)||"<span class='fancytree-title'"+(i=(i=!0===(i=h.evalOption("tooltip",r,r,s,null))?r.title:i)?" title='"+P(i)+"'":"")+(s.titlesTabbable?" tabindex='0'":"")+">"+(s.escapeTitles?h.escapeHtml(r.title):r.title)+"</span>",d.push(t),r.span.innerHTML=d.join(""),this.nodeRenderStatus(e),s.enhanceTitle&&(e.$title=k(">span.fancytree-title",r.span),t=s.enhanceTitle.call(o,{type:"enhanceTitle"},e)||""))},nodeRenderStatus:function(e){var t,n=e.node,i=e.tree,r=e.options,o=n.hasChildren(),s=n.isLastSibling(),a=r.aria,l=r._classNames,d=[],e=n[i.statusClassPropName];e&&!1!==i._enableUpdate&&(a&&(t=k(n.tr||n.li)),d.push(l.node),i.activeNode===n&&d.push(l.active),i.focusNode===n&&d.push(l.focused),n.expanded&&d.push(l.expanded),a&&(!1===o?t.removeAttr("aria-expanded"):t.attr("aria-expanded",Boolean(n.expanded))),n.folder&&d.push(l.folder),!1!==o&&d.push(l.hasChildren),s&&d.push(l.lastsib),n.lazy&&null==n.children&&d.push(l.lazy),n.partload&&d.push(l.partload),n.partsel&&d.push(l.partsel),h.evalOption("unselectable",n,n,r,!1)&&d.push(l.unselectable),n._isLoading&&d.push(l.loading),n._error&&d.push(l.error),n.statusNodeType&&d.push(l.statusNodePrefix+n.statusNodeType),n.selected?(d.push(l.selected),a&&t.attr("aria-selected",!0)):a&&t.attr("aria-selected",!1),n.extraClasses&&d.push(n.extraClasses),!1===o?d.push(l.combinedExpanderPrefix+"n"+(s?"l":"")):d.push(l.combinedExpanderPrefix+(n.expanded?"e":"c")+(n.lazy&&null==n.children?"d":"")+(s?"l":"")),d.push(l.combinedIconPrefix+(n.expanded?"e":"c")+(n.folder?"f":"")),e.className=d.join(" "),n.li&&k(n.li).toggleClass(l.lastsib,s))},nodeSetActive:function(e,t,n){var i=e.node,r=e.tree,o=e.options,s=!0===(n=n||{}).noEvents,a=!0===n.noFocus,n=!1!==n.scrollIntoView;return i===r.activeNode===(t=!1!==t)?T(i):(n&&e.originalEvent&&k(e.originalEvent.target).is("a,:checkbox")&&(i.info("Not scrolling while clicking an embedded link."),n=!1),t&&!s&&!1===this._triggerNodeEvent("beforeActivate",i,e.originalEvent)?L(i,["rejected"]):(t?(r.activeNode&&(_(r.activeNode!==i,"node was active (inconsistency)"),t=k.extend({},e,{node:r.activeNode}),r.nodeSetActive(t,!1),_(null===r.activeNode,"deactivate was out of sync?")),o.activeVisible&&i.makeVisible({scrollIntoView:n}),r.activeNode=i,r.nodeRenderStatus(e),a||r.nodeSetFocus(e),s||r._triggerNodeEvent("activate",i,e.originalEvent)):(_(r.activeNode===i,"node was not active (inconsistency)"),r.activeNode=null,this.nodeRenderStatus(e),s||e.tree._triggerNodeEvent("deactivate",i,e.originalEvent)),T(i)))},nodeSetExpanded:function(i,r,e){var t,n,o,s,a,l,d=i.node,c=i.tree,u=i.options,h=!0===(e=e||{}).noAnimation,f=!0===e.noEvents;if(r=!1!==r,k(d.li).hasClass(u._classNames.animating))return d.warn("setExpanded("+r+") while animating: ignored."),L(d,["recursion"]);if(d.expanded&&r||!d.expanded&&!r)return T(d);if(r&&!d.lazy&&!d.hasChildren())return T(d);if(!r&&d.getLevel()<u.minExpandLevel)return L(d,["locked"]);if(!f&&!1===this._triggerNodeEvent("beforeExpand",d,i.originalEvent))return L(d,["rejected"]);if(h||d.isVisible()||(h=e.noAnimation=!0),n=new k.Deferred,r&&!d.expanded&&u.autoCollapse){a=d.getParentList(!1,!0),l=u.autoCollapse;try{for(u.autoCollapse=!1,o=0,s=a.length;o<s;o++)this._callHook("nodeCollapseSiblings",a[o],e)}finally{u.autoCollapse=l}}return n.done(function(){var e=d.getLastChild();r&&u.autoScroll&&!h&&e&&c._enableUpdate?e.scrollIntoView(!0,{topNode:d}).always(function(){f||i.tree._triggerNodeEvent(r?"expand":"collapse",i)}):f||i.tree._triggerNodeEvent(r?"expand":"collapse",i)}),t=function(e){var t=u._classNames,n=u.toggleEffect;if(d.expanded=r,c._callHook("treeStructureChanged",i,r?"expand":"collapse"),c._callHook("nodeRender",i,!1,!1,!0),d.ul)if("none"!==d.ul.style.display==!!d.expanded)d.warn("nodeSetExpanded: UL.style.display already set");else{if(n&&!h)return k(d.li).addClass(t.animating),void(w(k(d.ul)[n.effect])?k(d.ul)[n.effect]({duration:n.duration,always:function(){k(this).removeClass(t.animating),k(d.li).removeClass(t.animating),e()}}):(k(d.ul).stop(!0,!0),k(d.ul).parent().find(".ui-effects-placeholder").remove(),k(d.ul).toggle(n.effect,n.options,n.duration,function(){k(this).removeClass(t.animating),k(d.li).removeClass(t.animating),e()})));d.ul.style.display=d.expanded||!parent?"":"none"}e()},r&&d.lazy&&void 0===d.hasChildren()?d.load().done(function(){n.notifyWith&&n.notifyWith(d,["loaded"]),t(function(){n.resolveWith(d)})}).fail(function(e){t(function(){n.rejectWith(d,["load failed ("+e+")"])})}):t(function(){n.resolveWith(d)}),n.promise()},nodeSetFocus:function(e,t){var n,i=e.tree,r=e.node,o=i.options,s=!!e.originalEvent&&k(e.originalEvent.target).is(":input");if(t=!1!==t,i.focusNode){if(i.focusNode===r&&t)return;n=k.extend({},e,{node:i.focusNode}),i.focusNode=null,this._triggerNodeEvent("blur",n),this._callHook("nodeRenderStatus",n)}t&&(this.hasFocus()||(r.debug("nodeSetFocus: forcing container focus"),this._callHook("treeSetFocus",e,!0,{calledByNode:!0})),r.makeVisible({scrollIntoView:!1}),i.focusNode=r,o.titlesTabbable&&(s||k(r.span).find(".fancytree-title").focus()),o.aria&&k(i.$container).attr("aria-activedescendant",k(r.tr||r.li).uniqueId().attr("id")),this._triggerNodeEvent("focus",e),document.activeElement===i.$container.get(0)||1<=k(document.activeElement,i.$container).length||k(i.$container).focus(),o.autoScroll&&r.scrollIntoView(),this._callHook("nodeRenderStatus",e))},nodeSetSelected:function(e,t,n){var i=e.node,r=e.tree,o=e.options,s=!0===(n=n||{}).noEvents,a=i.parent;if(t=!1!==t,!h.evalOption("unselectable",i,i,o,!1))return i._lastSelectIntent=t,!!i.selected!==t||3===o.selectMode&&i.partsel&&!t?s||!1!==this._triggerNodeEvent("beforeSelect",i,e.originalEvent)?(t&&1===o.selectMode?(r.lastSelectedNode&&r.lastSelectedNode.setSelected(!1),i.selected=t):3!==o.selectMode||!a||a.radiogroup||i.radiogroup?a&&a.radiogroup?i.visitSiblings(function(e){e._changeSelectStatusAttrs(t&&e===i)},!0):i.selected=t:(i.selected=t,i.fixSelection3AfterClick(n)),this.nodeRenderStatus(e),r.lastSelectedNode=t?i:null,void(s||r._triggerNodeEvent("select",e))):!!i.selected:t},nodeSetStatus:function(i,e,t,n){var r=i.node,o=i.tree;function s(e,t){var n=r.children?r.children[0]:null;return n&&n.isStatusNode()?(k.extend(n,e),n.statusNodeType=t,o._callHook("nodeRenderTitle",n)):(r._setChildren([e]),o._callHook("treeStructureChanged",i,"setStatusNode"),r.children[0].statusNodeType=t,o.render()),r.children[0]}switch(e){case"ok":!function(){var e=r.children?r.children[0]:null;if(e&&e.isStatusNode()){try{r.ul&&(r.ul.removeChild(e.li),e.li=null)}catch(e){}1===r.children.length?r.children=[]:r.children.shift(),o._callHook("treeStructureChanged",i,"clearStatusNode")}}(),r._isLoading=!1,r._error=null,r.renderStatus();break;case"loading":r.parent||s({title:o.options.strings.loading+(t?" ("+t+")":""),checkbox:!1,tooltip:n},e),r._isLoading=!0,r._error=null,r.renderStatus();break;case"error":s({title:o.options.strings.loadError+(t?" ("+t+")":""),checkbox:!1,tooltip:n},e),r._isLoading=!1,r._error={message:t,details:n},r.renderStatus();break;case"nodata":s({title:t||o.options.strings.noData,checkbox:!1,tooltip:n},e),r._isLoading=!1,r._error=null,r.renderStatus();break;default:k.error("invalid node status "+e)}},nodeToggleExpanded:function(e){return this.nodeSetExpanded(e,!e.node.expanded)},nodeToggleSelected:function(e){var t=e.node,n=!t.selected;return t.partsel&&!t.selected&&!0===t._lastSelectIntent&&(t.selected=!(n=!1)),t._lastSelectIntent=n,this.nodeSetSelected(e,n)},treeClear:function(e){var t=e.tree;t.activeNode=null,t.focusNode=null,t.$div.find(">ul.fancytree-container").empty(),t.rootNode.children=null,t._callHook("treeStructureChanged",e,"clear")},treeCreate:function(e){},treeDestroy:function(e){this.$div.find(">ul.fancytree-container").remove(),this.$source&&this.$source.removeClass("fancytree-helper-hidden")},treeInit:function(e){var n=e.tree,i=n.options;n.$container.attr("tabindex",i.tabindex),k.each(b,function(e,t){void 0!==i[t]&&(n.info("Move option "+t+" to tree"),n[t]=i[t],delete i[t])}),i.checkboxAutoHide&&n.$container.addClass("fancytree-checkbox-auto-hide"),i.rtl?n.$container.attr("DIR","RTL").addClass("fancytree-rtl"):n.$container.removeAttr("DIR").removeClass("fancytree-rtl"),i.aria&&(n.$container.attr("role","tree"),1!==i.selectMode&&n.$container.attr("aria-multiselectable",!0)),this.treeLoad(e)},treeLoad:function(e,t){var n,i,r,o=e.tree,s=e.widget.element,a=k.extend({},e,{node:this.rootNode});if(o.rootNode.children&&this.treeClear(e),t=t||this.options.source)"string"==typeof t&&k.error("Not implemented");else switch(i=s.data("type")||"html"){case"html":(r=s.find(">ul").not(".fancytree-container").first()).length?(r.addClass("ui-fancytree-source fancytree-helper-hidden"),t=k.ui.fancytree.parseHtml(r),this.data=k.extend(this.data,H(r))):(h.warn("No `source` option was passed and container does not contain `<ul>`: assuming `source: []`."),t=[]);break;case"json":t=k.parseJSON(s.text()),s.contents().filter(function(){return 3===this.nodeType}).remove(),k.isPlainObject(t)&&(_(N(t.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),t=(n=t).children,delete n.children,k.each(b,function(e,t){void 0!==n[t]&&(o[t]=n[t],delete n[t])}),k.extend(o.data,n));break;default:k.error("Invalid data-type: "+i)}return o._triggerTreeEvent("preInit",null),this.nodeLoadChildren(a,t).done(function(){o._callHook("treeStructureChanged",e,"loadChildren"),o.render(),3===e.options.selectMode&&o.rootNode.fixSelection3FromEndNodes(),o.activeNode&&o.options.activeVisible&&o.activeNode.makeVisible(),o._triggerTreeEvent("init",null,{status:!0})}).fail(function(){o.render(),o._triggerTreeEvent("init",null,{status:!1})})},treeRegisterNode:function(e,t,n){e.tree._callHook("treeStructureChanged",e,t?"addNode":"removeNode")},treeSetFocus:function(e,t,n){var i;(t=!1!==t)!==this.hasFocus()&&(!(this._hasFocus=t)&&this.focusNode?this.focusNode.setFocus(!1):!t||n&&n.calledByNode||k(this.$container).focus(),this.$container.toggleClass("fancytree-treefocus",t),this._triggerTreeEvent(t?"focusTree":"blurTree"),t&&!this.activeNode&&(i=this._lastMousedownNode||this.getFirstChild())&&i.setFocus())},treeSetOption:function(e,t,n){var i=e.tree,r=!0,o=!1,s=!1;switch(t){case"aria":case"checkbox":case"icon":case"minExpandLevel":case"tabindex":s=o=!0;break;case"checkboxAutoHide":i.$container.toggleClass("fancytree-checkbox-auto-hide",!!n);break;case"escapeTitles":case"tooltip":s=!0;break;case"rtl":!1===n?i.$container.removeAttr("DIR").removeClass("fancytree-rtl"):i.$container.attr("DIR","RTL").addClass("fancytree-rtl"),s=!0;break;case"source":r=!1,i._callHook("treeLoad",i,n),s=!0}i.debug("set option "+t+"="+n+" <"+typeof n+">"),r&&(this.widget._super||k.Widget.prototype._setOption).call(this.widget,t,n),o&&i._callHook("treeCreate",i),s&&i.render(!0,!1)},treeStructureChanged:function(e,t){}}),k.widget("ui.fancytree",{options:{activeVisible:!0,ajax:{type:"GET",cache:!1,dataType:"json"},aria:!0,autoActivate:!0,autoCollapse:!1,autoScroll:!1,checkbox:!1,clickFolderMode:4,copyFunctionsToData:!1,debugLevel:null,disabled:!1,enableAspx:42,escapeTitles:!1,extensions:[],focusOnSelect:!1,generateIds:!1,icon:!0,idPrefix:"ft_",keyboard:!0,keyPathSeparator:"/",minExpandLevel:1,nodata:!0,quicksearch:!1,rtl:!1,scrollOfs:{top:0,bottom:0},scrollParent:null,selectMode:2,strings:{loading:"Loading...",loadError:"Load error!",moreData:"More...",noData:"No data."},tabindex:"0",titlesTabbable:!1,toggleEffect:{effect:"slideToggle",duration:200},tooltip:!1,treeId:null,_classNames:{active:"fancytree-active",animating:"fancytree-animating",combinedExpanderPrefix:"fancytree-exp-",combinedIconPrefix:"fancytree-ico-",error:"fancytree-error",expanded:"fancytree-expanded",focused:"fancytree-focused",folder:"fancytree-folder",hasChildren:"fancytree-has-children",lastsib:"fancytree-lastsib",lazy:"fancytree-lazy",loading:"fancytree-loading",node:"fancytree-node",partload:"fancytree-partload",partsel:"fancytree-partsel",radio:"fancytree-radio",selected:"fancytree-selected",statusNodePrefix:"fancytree-statusnode-",unselectable:"fancytree-unselectable"},lazyLoad:null,postProcess:null},_deprecationWarning:function(e){var t=this.tree;t&&3<=t.options.debugLevel&&t.warn("$().fancytree('"+e+"') is deprecated (see https://wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Widget.html")},_create:function(){this.tree=new F(this),this.$source=this.source||"json"===this.element.data("type")?this.element:this.element.find(">ul").first();for(var e,t,n=this.options,i=n.extensions,r=(this.tree,0);r<i.length;r++)t=i[r],(e=k.ui.fancytree._extensions[t])||k.error("Could not apply extension '"+t+"' (it is not registered, did you forget to include it?)"),this.tree.options[t]=function e(t){var n,i,r,o,s=t||{},a=1,l=arguments.length;if("object"==typeof s||w(s)||(s={}),a===l)throw Error("need at least two args");for(;a<l;a++)if(null!=(n=arguments[a]))for(i in n)C(n,i)&&(o=s[i],s!==(r=n[i])&&(r&&k.isPlainObject(r)?(o=o&&k.isPlainObject(o)?o:{},s[i]=e(o,r)):void 0!==r&&(s[i]=r)));return s}({},e.options,this.tree.options[t]),_(void 0===this.tree.ext[t],"Extension name must not exist as Fancytree.ext attribute: '"+t+"'"),this.tree.ext[t]={},function(e,t,n){for(var i in t)"function"==typeof t[i]?"function"==typeof e[i]?e[i]=E(i,e,0,t,n):"_"===i.charAt(0)?e.ext[n][i]=E(i,e,0,t,n):k.error("Could not override tree."+i+". Use prefix '_' to create tree."+n+"._"+i):"options"!==i&&(e.ext[n][i]=t[i])}(this.tree,e,t),0;void 0!==n.icons&&(!0===n.icon?(this.tree.warn("'icons' tree option is deprecated since v2.14.0: use 'icon' instead"),n.icon=n.icons):k.error("'icons' tree option is deprecated since v2.14.0: use 'icon' only instead")),void 0!==n.iconClass&&(n.icon?k.error("'iconClass' tree option is deprecated since v2.14.0: use 'icon' only instead"):(this.tree.warn("'iconClass' tree option is deprecated since v2.14.0: use 'icon' instead"),n.icon=n.iconClass)),void 0!==n.tabbable&&(n.tabindex=n.tabbable?"0":"-1",this.tree.warn("'tabbable' tree option is deprecated since v2.17.0: use 'tabindex='"+n.tabindex+"' instead")),this.tree._callHook("treeCreate",this.tree)},_init:function(){this.tree._callHook("treeInit",this.tree),this._bind()},_setOption:function(e,t){return this.tree._callHook("treeSetOption",this.tree,e,t)},_destroy:function(){this._unbind(),this.tree._callHook("treeDestroy",this.tree)},_unbind:function(){var e=this.tree._ns;this.element.off(e),this.tree.$container.off(e),k(document).off(e)},_bind:function(){var s=this,a=this.options,o=this.tree,e=o._ns;this._unbind(),o.$container.on("focusin"+e+" focusout"+e,function(e){var t=h.getNode(e),n="focusin"===e.type;if(!n&&t&&k(e.target).is("a"))t.debug("Ignored focusout on embedded <a> element.");else{if(n){if(o._getExpiringValue("focusin"))return void o.debug("Ignored double focusin.");o._setExpiringValue("focusin",!0,50),t||(t=o._getExpiringValue("mouseDownNode"))&&o.debug("Reconstruct mouse target for focusin from recent event.")}t?o._callHook("nodeSetFocus",o._makeHookContext(t,e),n):o.tbody&&k(e.target).parents("table.fancytree-container > thead").length?o.debug("Ignore focus event outside table body.",e):o._callHook("treeSetFocus",o,n)}}).on("selectstart"+e,"span.fancytree-title",function(e){e.preventDefault()}).on("keydown"+e,function(e){if(a.disabled||!1===a.keyboard)return!0;var t,n=o.focusNode,i=o._makeHookContext(n||o,e),r=o.phase;try{return o.phase="userEvent","preventNav"===(t=n?o._triggerNodeEvent("keydown",n,e):o._triggerTreeEvent("keydown",e))?t=!0:!1!==t&&(t=o._callHook("nodeKeydown",i)),t}finally{o.phase=r}}).on("mousedown"+e,function(e){e=h.getEventTarget(e);o._lastMousedownNode=e?e.node:null,o._setExpiringValue("mouseDownNode",o._lastMousedownNode)}).on("click"+e+" dblclick"+e,function(e){if(a.disabled)return!0;var t,n=h.getEventTarget(e),i=n.node,r=s.tree,o=r.phase;if(!i)return!0;t=r._makeHookContext(i,e);try{switch(r.phase="userEvent",e.type){case"click":return t.targetType=n.type,i.isPagingNode()?!0===r._triggerNodeEvent("clickPaging",t,e):!1!==r._triggerNodeEvent("click",t,e)&&r._callHook("nodeClick",t);case"dblclick":return t.targetType=n.type,!1!==r._triggerNodeEvent("dblclick",t,e)&&r._callHook("nodeDblclick",t)}}finally{r.phase=o}})},getActiveNode:function(){return this._deprecationWarning("getActiveNode"),this.tree.activeNode},getNodeByKey:function(e){return this._deprecationWarning("getNodeByKey"),this.tree.getNodeByKey(e)},getRootNode:function(){return this._deprecationWarning("getRootNode"),this.tree.rootNode},getTree:function(){return this._deprecationWarning("getTree"),this.tree}}),h=k.ui.fancytree,k.extend(k.ui.fancytree,{version:"2.38.3",buildType: "production",debugLevel: 3,_nextId:1,_nextNodeKey:1,_extensions:{},_FancytreeClass:F,_FancytreeNodeClass:I,jquerySupports:{positionMyOfs:function(e){for(var t,n,i=k.map(S(e).split("."),function(e){return parseInt(e,10)}),r=k.map(Array.prototype.slice.call(arguments,1),function(e){return parseInt(e,10)}),o=0;o<r.length;o++)if((t=i[o]||0)!==(n=r[o]||0))return n<t;return!0}(k.ui.version,1,9)},assert:_,createTree:function(e,t){t=k(e).fancytree(t);return h.getTree(t)},debounce:function(t,n,i,r){var o;return 3===arguments.length&&"boolean"!=typeof i&&(r=i,i=!1),function(){var e=arguments;r=r||this,i&&!o&&n.apply(r,e),clearTimeout(o),o=setTimeout(function(){i||n.apply(r,e),o=null},t)}},debug:function(e){4<=k.ui.fancytree.debugLevel&&d("log",arguments)},error:function(e){1<=k.ui.fancytree.debugLevel&&d("error",arguments)},escapeHtml:function(e){return(""+e).replace(t,function(e){return i[e]})},fixPositionOptions:function(e){var t,n,i,r;return(e.offset||0<=(""+e.my+e.at).indexOf("%"))&&k.error("expected new position syntax (but '%' is not supported)"),k.ui.fancytree.jquerySupports.positionMyOfs||(t=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(e.my),n=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(e.at),i=(t[2]?+t[2]:0)+(n[2]?+n[2]:0),r=(t[4]?+t[4]:0)+(n[4]?+n[4]:0),e=k.extend({},e,{my:t[1]+" "+t[3],at:n[1]+" "+n[3]}),(i||r)&&(e.offset=i+" "+r)),e},getEventTarget:function(e){var t=e&&e.target?e.target.className:"",n={node:this.getNode(e.target),type:void 0};return/\bfancytree-title\b/.test(t)?n.type="title":/\bfancytree-expander\b/.test(t)?n.type=!1===n.node.hasChildren()?"prefix":"expander":/\bfancytree-checkbox\b/.test(t)?n.type="checkbox":/\bfancytree(-custom)?-icon\b/.test(t)?n.type="icon":/\bfancytree-node\b/.test(t)?n.type="title":e&&e.target&&((e=k(e.target)).is("ul[role=group]")?((n.node&&n.node.tree||h).debug("Ignoring click on outer UL."),n.node=null):e.closest(".fancytree-title").length?n.type="title":e.closest(".fancytree-checkbox").length?n.type="checkbox":e.closest(".fancytree-expander").length&&(n.type="expander")),n},getEventTargetType:function(e){return this.getEventTarget(e).type},getNode:function(e){if(e instanceof I)return e;for(e instanceof k?e=e[0]:void 0!==e.originalEvent&&(e=e.target);e;){if(e.ftnode)return e.ftnode;e=e.parentNode}return null},getTree:function(e){var t=e;return e instanceof F?e:("number"==typeof(e=void 0===e?0:e)?e=k(".fancytree-container").eq(e):"string"==typeof e?(e=k("#ft-id-"+t).eq(0)).length||(e=k(t).eq(0)):e instanceof Element||e instanceof HTMLDocument?e=k(e):e instanceof k?e=e.eq(0):void 0!==e.originalEvent&&(e=k(e.target)),(e=(e=e.closest(":ui-fancytree")).data("ui-fancytree")||e.data("fancytree"))?e.tree:null)},evalOption:function(e,t,n,i,r){var o,s=t.tree,i=i[e],n=n[e];return w(i)?(o={node:t,tree:s,widget:s.widget,options:s.widget.options,typeInfo:s.types[t.type]||{}},null==(o=i.call(s,{type:e},o))&&(o=n)):o=null==n?i:n,o=null==o?r:o},setSpanIcon:function(e,t,n){var i=k(e);"string"==typeof n?i.attr("class",t+" "+n):(n.text?i.text(""+n.text):n.html&&(e.innerHTML=n.html),i.attr("class",t+" "+(n.addClass||"")))},eventToString:function(e){var t=e.which,n=e.type,i=[];return e.altKey&&i.push("alt"),e.ctrlKey&&i.push("ctrl"),e.metaKey&&i.push("meta"),e.shiftKey&&i.push("shift"),"click"===n||"dblclick"===n?i.push(o[e.button]+n):"wheel"===n?i.push(n):r[t]||i.push(u[t]||String.fromCharCode(t).toLowerCase()),i.join("+")},info:function(e){3<=k.ui.fancytree.debugLevel&&d("info",arguments)},keyEventToString:function(e){return this.warn("keyEventToString() is deprecated: use eventToString()"),this.eventToString(e)},overrideMethod:function(e,t,n,i){var r,o=e[t]||k.noop;e[t]=function(){var e=i||this;try{return r=e._super,e._super=o,n.apply(e,arguments)}finally{e._super=r}}},parseHtml:function(s){var a,l,d,c,u,h,f,p,e=s.find(">li"),g=[];return e.each(function(){var e,t,n=k(this),i=n.find(">span",this).first(),r=i.length?null:n.find(">a").first(),o={tooltip:null,data:{}};for(i.length?o.title=i.html():r&&r.length?(o.title=r.html(),o.data.href=r.attr("href"),o.data.target=r.attr("target"),o.tooltip=r.attr("title")):(o.title=n.html(),0<=(u=o.title.search(/<ul/i))&&(o.title=o.title.substring(0,u))),o.title=S(o.title),c=0,h=v.length;c<h;c++)o[v[c]]=void 0;for(a=this.className.split(" "),d=[],c=0,h=a.length;c<h;c++)l=a[c],y[l]?o[l]=!0:d.push(l);if(o.extraClasses=d.join(" "),(f=n.attr("title"))&&(o.tooltip=f),(f=n.attr("id"))&&(o.key=f),n.attr("hideCheckbox")&&(o.checkbox=!1),(e=H(n))&&!k.isEmptyObject(e)){for(t in x)C(e,t)&&(e[x[t]]=e[t],delete e[t]);for(c=0,h=m.length;c<h;c++)f=m[c],null!=(p=e[f])&&(delete e[f],o[f]=p);k.extend(o.data,e)}(s=n.find(">ul").first()).length?o.children=k.ui.fancytree.parseHtml(s):o.children=o.lazy?void 0:null,g.push(o)}),g},registerExtension:function(e){_(null!=e.name,"extensions must have a `name` property."),_(null!=e.version,"extensions must have a `version` property."),k.ui.fancytree._extensions[e.name]=e},trim:S,unescapeHtml:function(e){var t=document.createElement("div");return t.innerHTML=e,0===t.childNodes.length?"":t.childNodes[0].nodeValue},warn:function(e){2<=k.ui.fancytree.debugLevel&&d("warn",arguments)}}),k.ui.fancytree}function _(e,t){e||(k.ui.fancytree.error(t="Fancytree assertion failed"+(t=t?": "+t:"")),k.error(t))}function C(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function w(e){return"function"==typeof e}function S(e){return null==e?"":e.trim()}function d(t,n){var i,r,t=window.console?window.console[t]:null;if(t)try{t.apply(window.console,n)}catch(e){for(r="",i=0;i<n.length;i++)r+=n[i];t(r)}}function E(e,i,t,n,r){var o,s,a;function l(){return o.apply(i,arguments)}function d(e){return o.apply(i,e)}return o=i[e],s=n[e],a=i.ext[r],function(){var e=i._local,t=i._super,n=i._superApply;try{return i._local=a,i._super=l,i._superApply=d,s.apply(i,arguments)}finally{i._local=e,i._super=t,i._superApply=n}}}function T(e,t){return(void 0===e?k.Deferred(function(){this.resolve()}):k.Deferred(function(){this.resolveWith(e,t)})).promise()}function L(e,t){return(void 0===e?k.Deferred(function(){this.reject()}):k.Deferred(function(){this.rejectWith(e,t)})).promise()}function A(e,t){return function(){e.resolveWith(t)}}function H(e){var t=k.extend({},e.data()),e=t.json;return delete t.fancytree,delete t.uiFancytree,e&&(delete t.json,t=k.extend(t,e)),t}function P(e){return(""+e).replace(n,function(e){return i[e]})}function R(t){return t=t.toLowerCase(),function(e){return 0<=e.title.toLowerCase().indexOf(t)}}function I(e,t){var n,i,r;for(this.parent=e,this.tree=e.tree,this.ul=null,this.li=null,this.statusNodeType=null,this._isLoading=!1,this._error=null,this.data={},n=0,i=m.length;n<i;n++)this[r=m[n]]=t[r];for(r in null==this.unselectableIgnore&&null==this.unselectableStatus||(this.unselectable=!0),t.hideCheckbox&&k.error("'hideCheckbox' node option was removed in v2.23.0: use 'checkbox: false'"),t.data&&k.extend(this.data,t.data),t)s[r]||!this.tree.options.copyFunctionsToData&&w(t[r])||a[r]||(this.data[r]=t[r]);null==this.key?this.tree.options.defaultKey?(this.key=""+this.tree.options.defaultKey(this),_(this.key,"defaultKey() must return a unique key")):this.key="_"+h._nextNodeKey++:this.key=""+this.key,t.active&&(_(null===this.tree.activeNode,"only one active node allowed"),this.tree.activeNode=this),t.selected&&(this.tree.lastSelectedNode=this),(e=t.children)?e.length?this._setChildren(e):this.children=this.lazy?[]:null:this.children=null,this.tree._callHook("treeRegisterNode",this.tree,!0,this)}function F(e){this.widget=e,this.$div=e.element,this.options=e.options,this.options&&(void 0!==this.options.lazyload&&k.error("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."),void 0!==this.options.loaderror&&k.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."),void 0!==this.options.fx&&k.error("The 'fx' option was replaced by 'toggleEffect' since 2014-11-30."),void 0!==this.options.removeNode&&k.error("The 'removeNode' event was replaced by 'modifyChild' since 2.20 (2016-09-10).")),this.ext={},this.types={},this.columns={},this.data=H(this.$div),this._id=""+(this.options.treeId||k.ui.fancytree._nextId++),this._ns=".fancytree-"+this._id,this.activeNode=null,this.focusNode=null,this._hasFocus=null,this._tempCache={},this._lastMousedownNode=null,this._enableUpdate=!0,this.lastSelectedNode=null,this.systemFocusElement=null,this.lastQuicksearchTerm="",this.lastQuicksearchTime=0,this.viewport=null,this.statusClassPropName="span",this.ariaPropName="li",this.nodeContainerAttrName="li",this.$div.find(">ul.fancytree-container").remove(),this.rootNode=new I({tree:this},{title:"root",key:"root_"+this._id,children:null,expanded:!0}),this.rootNode.parent=null,e=k("<ul>",{id:"ft-id-"+this._id,class:"ui-fancytree fancytree-container fancytree-plain"}).appendTo(this.$div),this.$container=e,this.rootNode.ul=e[0],null==this.options.debugLevel&&(this.options.debugLevel=h.debugLevel)}k.ui.fancytree.warn("Fancytree: ignored duplicate include")});
+
+/*! Extension 'jquery.fancytree.childcounter.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(i){"use strict";return i.ui.fancytree._FancytreeClass.prototype.countSelected=function(e){this.options;return this.getSelectedNodes(e).length},i.ui.fancytree._FancytreeNodeClass.prototype.updateCounters=function(){var e=this,n=i("span.fancytree-childcounter",e.span),t=e.tree.options.childcounter,o=e.countChildren(t.deep);!(e.data.childCounter=o)&&t.hideZeros||e.isExpanded()&&t.hideExpanded?n.remove():(n=!n.length?i("<span class='fancytree-childcounter'/>").appendTo(i("span.fancytree-icon,span.fancytree-custom-icon",e.span)):n).text(o),!t.deep||e.isTopLevel()||e.isRootNode()||e.parent.updateCounters()},i.ui.fancytree.prototype.widgetMethod1=function(e){this.tree;return e},i.ui.fancytree.registerExtension({name:"childcounter",version:"2.38.3",options:{deep:!0,hideZeros:!0,hideExpanded:!1},foo:42,_appendCounter:function(e){},treeInit:function(e){e.options,e.options.childcounter;this._superApply(arguments),this.$container.addClass("fancytree-ext-childcounter")},treeDestroy:function(e){this._superApply(arguments)},nodeRenderTitle:function(e,n){var t=e.node,o=e.options.childcounter,r=null==t.data.childCounter?t.countChildren(o.deep):+t.data.childCounter;this._super(e,n),!r&&o.hideZeros||t.isExpanded()&&o.hideExpanded||i("span.fancytree-icon,span.fancytree-custom-icon",t.span).append(i("<span class='fancytree-childcounter'/>").text(r))},nodeSetExpanded:function(e,n,t){var o=e.tree;e.node;return this._superApply(arguments).always(function(){o.nodeRenderTitle(e)})}}),i.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.clones.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(c){"use strict";var f=c.ui.fancytree.assert;function n(e,t,n){for(var r,s,i=3&e.length,o=e.length-i,l=n,a=3432918353,u=461845907,c=0;c<o;)s=255&e.charCodeAt(c)|(255&e.charCodeAt(++c))<<8|(255&e.charCodeAt(++c))<<16|(255&e.charCodeAt(++c))<<24,++c,l=27492+(65535&(r=5*(65535&(l=(l^=s=(65535&(s=(s=(65535&s)*a+(((s>>>16)*a&65535)<<16)&4294967295)<<15|s>>>17))*u+(((s>>>16)*u&65535)<<16)&4294967295)<<13|l>>>19))+((5*(l>>>16)&65535)<<16)&4294967295))+((58964+(r>>>16)&65535)<<16);switch(s=0,i){case 3:s^=(255&e.charCodeAt(c+2))<<16;case 2:s^=(255&e.charCodeAt(c+1))<<8;case 1:l^=s=(65535&(s=(s=(65535&(s^=255&e.charCodeAt(c)))*a+(((s>>>16)*a&65535)<<16)&4294967295)<<15|s>>>17))*u+(((s>>>16)*u&65535)<<16)&4294967295}return l^=e.length,l=2246822507*(65535&(l^=l>>>16))+((2246822507*(l>>>16)&65535)<<16)&4294967295,l=3266489909*(65535&(l^=l>>>13))+((3266489909*(l>>>16)&65535)<<16)&4294967295,l^=l>>>16,t?("0000000"+(l>>>0).toString(16)).substr(-8):l>>>0}return c.ui.fancytree._FancytreeNodeClass.prototype.getCloneList=function(e){var t,n=this.tree,r=n.refMap[this.refKey]||null,s=n.keyMap;return r&&(t=this.key,e?r=c.map(r,function(e){return s[e]}):(r=c.map(r,function(e){return e===t?null:s[e]})).length<1&&(r=null)),r},c.ui.fancytree._FancytreeNodeClass.prototype.isClone=function(){var e=this.refKey||null,e=e&&this.tree.refMap[e]||null;return!!(e&&1<e.length)},c.ui.fancytree._FancytreeNodeClass.prototype.reRegister=function(t,e){e=null==e?null:""+e;var n=this.tree,r=this.key,s=this.refKey,i=n.keyMap,o=n.refMap,l=o[s]||null,n=!1;return null!=(t=null==t?null:""+t)&&t!==this.key&&(i[t]&&c.error("[ext-clones] reRegister("+t+"): already exists: "+this),delete i[r],i[t]=this,l&&(o[s]=c.map(l,function(e){return e===r?t:e})),this.key=t,n=!0),null!=e&&e!==this.refKey&&(l&&(1===l.length?delete o[s]:o[s]=c.map(l,function(e){return e===r?null:e})),o[e]?o[e].append(t):o[e]=[this.key],this.refKey=e,n=!0),n},c.ui.fancytree._FancytreeNodeClass.prototype.setRefKey=function(e){return this.reRegister(null,e)},c.ui.fancytree._FancytreeClass.prototype.getNodesByRef=function(e,t){var n=this.keyMap,e=this.refMap[e]||null;return e=e&&(e=t?c.map(e,function(e){e=n[e];return e.isDescendantOf(t)?e:null}):c.map(e,function(e){return n[e]})).length<1?null:e},c.ui.fancytree._FancytreeClass.prototype.changeRefKey=function(e,t){var n,r=this.keyMap,s=this.refMap[e]||null;if(s){for(n=0;n<s.length;n++)r[s[n]].refKey=t;delete this.refMap[e],this.refMap[t]=s}},c.ui.fancytree.registerExtension({name:"clones",version:"2.38.3",options:{highlightActiveClones:!0,highlightClones:!1},treeCreate:function(e){this._superApply(arguments),e.tree.refMap={},e.tree.keyMap={}},treeInit:function(e){this.$container.addClass("fancytree-ext-clones"),f(null==e.options.defaultKey),e.options.defaultKey=function(e){return t=e,"id_"+(t=n(e=(e=c.map(e.getParentList(!1,!0),function(e){return e.refKey||e.key})).join("/"),!0))+n(t+e,!0);var t},this._superApply(arguments)},treeClear:function(e){return e.tree.refMap={},e.tree.keyMap={},this._superApply(arguments)},treeRegisterNode:function(e,t,n){var r,s,i=e.tree,o=i.keyMap,l=i.refMap,a=n.key,u=n&&null!=n.refKey?""+n.refKey:null;return n.isStatusNode()||(t?(null!=o[n.key]&&(s=o[n.key],s="clones.treeRegisterNode: duplicate key '"+n.key+"': /"+n.getPath(!0)+" => "+s.getPath(!0),i.error(s),c.error(s)),o[a]=n,u&&((r=l[u])?(r.push(a),2===r.length&&e.options.clones.highlightClones&&o[r[0]].renderStatus()):l[u]=[a])):(null==o[a]&&c.error("clones.treeRegisterNode: node.key not registered: "+n.key),delete o[a],u&&(r=l[u])&&((s=r.length)<=1?(f(1===s),f(r[0]===a),delete l[u]):(function(e,t){for(var n=e.length-1;0<=n;n--)if(e[n]===t)return e.splice(n,1)}(r,a),2===s&&e.options.clones.highlightClones&&o[r[0]].renderStatus())))),this._super(e,t,n)},nodeRenderStatus:function(e){var t,n=e.node,r=this._super(e);return e.options.clones.highlightClones&&(t=c(n[e.tree.statusClassPropName])).length&&n.isClone()&&t.addClass("fancytree-clone"),r},nodeSetActive:function(e,n,t){var r=e.tree.statusClassPropName,s=e.node,i=this._superApply(arguments);return e.options.clones.highlightActiveClones&&s.isClone()&&c.each(s.getCloneList(!0),function(e,t){c(t[r]).toggleClass("fancytree-active-clone",!1!==n)}),i}}),c.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.dnd.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","jquery-ui/ui/widgets/draggable","jquery-ui/ui/widgets/droppable","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(v){"use strict";var t=!1,g="fancytree-drop-accept",u="fancytree-drop-after",c="fancytree-drop-before",f="fancytree-drop-reject";function h(e){return 0===e?"":0<e?"+"+e:""+e}function r(e){var r=e.options.dnd||null,n=e.options.glyph||null;r&&(t||(v.ui.plugin.add("draggable","connectToFancytree",{start:function(e,r){var t=v(this).data("ui-draggable")||v(this).data("draggable"),a=r.helper.data("ftSourceNode")||null;if(a)return t.offset.click.top=-2,t.offset.click.left=16,a.tree.ext.dnd._onDragEvent("start",a,null,e,r,t)},drag:function(e,r){var t,a=v(this).data("ui-draggable")||v(this).data("draggable"),n=r.helper.data("ftSourceNode")||null,o=r.helper.data("ftTargetNode")||null,d=v.ui.fancytree.getNode(e.target),l=n&&n.tree.options.dnd;e.target&&!d&&0<v(e.target).closest("div.fancytree-drag-helper,#fancytree-drop-marker").length?(n||o||v.ui.fancytree).debug("Drag event over helper: ignored."):(r.helper.data("ftTargetNode",d),l&&l.updateHelper&&(t=n.tree._makeHookContext(n,e,{otherNode:d,ui:r,draggable:a,dropMarker:v("#fancytree-drop-marker")}),l.updateHelper.call(n.tree,n,t)),o&&o!==d&&o.tree.ext.dnd._onDragEvent("leave",o,n,e,r,a),d&&d.tree.options.dnd.dragDrop&&(d===o||d.tree.ext.dnd._onDragEvent("enter",d,n,e,r,a),d.tree.ext.dnd._onDragEvent("over",d,n,e,r,a)))},stop:function(e,r){var t=v(this).data("ui-draggable")||v(this).data("draggable"),a=r.helper.data("ftSourceNode")||null,n=r.helper.data("ftTargetNode")||null,o="mouseup"===e.type&&1===e.which;o||(a||n||v.ui.fancytree).debug("Drag was cancelled"),n&&(o&&n.tree.ext.dnd._onDragEvent("drop",n,a,e,r,t),n.tree.ext.dnd._onDragEvent("leave",n,a,e,r,t)),a&&a.tree.ext.dnd._onDragEvent("stop",a,null,e,r,t)}}),t=!0)),r&&r.dragStart&&e.widget.element.draggable(v.extend({addClasses:!1,appendTo:e.$container,containment:!1,delay:0,distance:4,revert:!1,scroll:!0,scrollSpeed:7,scrollSensitivity:10,connectToFancytree:!0,helper:function(e){var r,t,a=v.ui.fancytree.getNode(e.target);return a?(t=a.tree.options.dnd,r=v(a.span),(r=v("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>").css({zIndex:3,position:"relative"}).append(r.find("span.fancytree-title").clone())).data("ftSourceNode",a),n&&r.find(".fancytree-drag-helper-img").addClass(n.map._addClass+" "+n.map.dragHelper),t.initHelper&&t.initHelper.call(a.tree,a,{node:a,tree:a.tree,originalEvent:e,ui:{helper:r}}),r):"<div>ERROR?: helper requested but sourceNode not found</div>"},start:function(e,r){return!!r.helper.data("ftSourceNode")}},e.options.dnd.draggable)),r&&r.dragDrop&&e.widget.element.droppable(v.extend({addClasses:!1,tolerance:"intersect",greedy:!1},e.options.dnd.droppable))}return v.ui.fancytree.registerExtension({name:"dnd",version:"2.38.3",options:{autoExpandMS:1e3,draggable:null,droppable:null,focusOnClick:!1,preventVoidMoves:!0,preventRecursiveMoves:!0,smartRevert:!0,dropMarkerOffsetX:-24,dropMarkerInsertOffsetX:-16,dragStart:null,dragStop:null,initHelper:null,updateHelper:null,dragEnter:null,dragOver:null,dragExpand:null,dragDrop:null,dragLeave:null},treeInit:function(t){var e=t.tree;this._superApply(arguments),e.options.dnd.dragStart&&e.$container.on("mousedown",function(e){var r;t.options.dnd.focusOnClick&&((r=v.ui.fancytree.getNode(e))&&r.debug("Re-enable focus that was prevented by jQuery UI draggable."),setTimeout(function(){v(e.target).closest(":tabbable").focus()},10))}),r(e)},_setDndStatus:function(e,r,t,a,n){var o,d="center",l=this._local,s=this.options.dnd,i=this.options.glyph,p=e?v(e.span):null,e=v(r.span),r=e.find("span.fancytree-title");if(l.$dropMarker||(l.$dropMarker=v("<div id='fancytree-drop-marker'></div>").hide().css({"z-index":1e3}).prependTo(v(this.$div).parent()),i&&l.$dropMarker.addClass(i.map._addClass+" "+i.map.dropMarker)),"after"===a||"before"===a||"over"===a){switch(o=s.dropMarkerOffsetX||0,a){case"before":d="top",o+=s.dropMarkerInsertOffsetX||0;break;case"after":d="bottom",o+=s.dropMarkerInsertOffsetX||0}r={my:"left"+h(o)+" center",at:"left "+d,of:r},this.options.rtl&&(r.my="right"+h(-o)+" center",r.at="right "+d),l.$dropMarker.toggleClass(u,"after"===a).toggleClass("fancytree-drop-over","over"===a).toggleClass(c,"before"===a).toggleClass("fancytree-rtl",!!this.options.rtl).show().position(v.ui.fancytree.fixPositionOptions(r))}else l.$dropMarker.hide();p&&p.toggleClass(g,!0===n).toggleClass(f,!1===n),e.toggleClass("fancytree-drop-target","after"===a||"before"===a||"over"===a).toggleClass(u,"after"===a).toggleClass(c,"before"===a).toggleClass(g,!0===n).toggleClass(f,!1===n),t.toggleClass(g,!0===n).toggleClass(f,!1===n)},_onDragEvent:function(e,r,t,a,n,o){var d,l,s,i,p=this.options.dnd,g=this._makeHookContext(r,a,{otherNode:t,ui:n,draggable:o}),u=null,c=this,f=v(r.span);switch(p.smartRevert&&(o.options.revert="invalid"),e){case"start":r.isStatusNode()?u=!1:p.dragStart&&(u=p.dragStart(r,g)),!1===u?(this.debug("tree.dragStart() cancelled"),n.helper.trigger("mouseup").hide()):(p.smartRevert&&(d=r[g.tree.nodeContainerAttrName].getBoundingClientRect(),l=v(o.options.appendTo)[0].getBoundingClientRect(),o.originalPosition.left=Math.max(0,d.left-l.left),o.originalPosition.top=Math.max(0,d.top-l.top)),f.addClass("fancytree-drag-source"),v(document).on("keydown.fancytree-dnd,mousedown.fancytree-dnd",function(e){("keydown"===e.type&&e.which===v.ui.keyCode.ESCAPE||"mousedown"===e.type)&&c.ext.dnd._cancelDrag()}));break;case"enter":u=!!(i=(!p.preventRecursiveMoves||!r.isDescendantOf(t))&&(p.dragEnter?p.dragEnter(r,g):null))&&(Array.isArray(i)?{over:0<=v.inArray("over",i),before:0<=v.inArray("before",i),after:0<=v.inArray("after",i)}:{over:!0===i||"over"===i,before:!0===i||"before"===i,after:!0===i||"after"===i}),n.helper.data("enterResponse",u);break;case"over":s=null,!1===(l=n.helper.data("enterResponse"))||("string"==typeof l?s=l:(i=f.offset(),i={x:(i={x:a.pageX-i.left,y:a.pageY-i.top}).x/f.width(),y:i.y/f.height()},l.after&&.75<i.y||!l.over&&l.after&&.5<i.y?s="after":l.before&&i.y<=.25||!l.over&&l.before&&i.y<=.5?s="before":l.over&&(s="over"),p.preventVoidMoves&&(r===t?(this.debug(" drop over source node prevented"),s=null):"before"===s&&t&&r===t.getNextSibling()?(this.debug(" drop after source node prevented"),s=null):"after"===s&&t&&r===t.getPrevSibling()?(this.debug(" drop before source node prevented"),s=null):"over"===s&&t&&t.parent===r&&t.isLastSibling()&&(this.debug(" drop last child over own parent prevented"),s=null)),n.helper.data("hitMode",s))),"before"===s||"after"===s||!p.autoExpandMS||!1===r.hasChildren()||r.expanded||p.dragExpand&&!1===p.dragExpand(r,g)||r.scheduleAction("expand",p.autoExpandMS),s&&p.dragOver&&(g.hitMode=s,u=p.dragOver(r,g)),l=!1!==u&&null!==s,p.smartRevert&&(o.options.revert=!l),this._local._setDndStatus(t,r,n.helper,s,l);break;case"drop":(s=n.helper.data("hitMode"))&&p.dragDrop&&(g.hitMode=s,p.dragDrop(r,g));break;case"leave":r.scheduleAction("cancel"),n.helper.data("enterResponse",null),n.helper.data("hitMode",null),this._local._setDndStatus(t,r,n.helper,"out",void 0),p.dragLeave&&p.dragLeave(r,g);break;case"stop":f.removeClass("fancytree-drag-source"),v(document).off(".fancytree-dnd"),p.dragStop&&p.dragStop(r,g);break;default:v.error("Unsupported drag event: "+e)}return u},_cancelDrag:function(){var e=v.ui.ddmanager.current;e&&e.cancel()}}),v.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.dnd5.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(c){"use strict";var s,l,u=c.ui.fancytree,n=/Mac/.test(navigator.platform),i="fancytree-drag-source",f="fancytree-drag-remove",v="fancytree-drop-accept",y="fancytree-drop-after",b="fancytree-drop-before",h="fancytree-drop-over",m="fancytree-drop-reject",E="fancytree-drop-target",p="application/x-fancytree-node",D=null,g=null,w=null,N=null,x=null,d=null,S=null,k=null,C=null,M=null;function A(){w=g=d=k=S=M=x=null,N&&N.removeClass(i+" "+f),N=null,D&&D.hide(),l&&(l.remove(),l=null)}function T(e){return 0===e?"":0<e?"+"+e:""+e}function I(e,r){var t,o=r.tree,a=r.dataTransfer;"dragstart"===e.type?(r.effectAllowed=o.options.dnd5.effectAllowed,r.dropEffect=o.options.dnd5.dropEffectDefault):(r.effectAllowed=k,r.dropEffect=S),r.dropEffectSuggested=(t=e,o=(e=o).options.dnd5.dropEffectDefault,n?t.metaKey&&t.altKey||t.ctrlKey?o="link":t.metaKey?o="move":t.altKey&&(o="copy"):t.ctrlKey?o="copy":t.shiftKey?o="move":t.altKey&&(o="link"),o!==d&&e.info("evalEffectModifiers: "+t.type+" - evalEffectModifiers(): "+d+" -> "+o),d=o),r.isMove="move"===r.dropEffect,r.files=a.files||[]}function O(e,r,t){var o=r.tree,a=r.dataTransfer;return"dragstart"!==e.type&&k!==r.effectAllowed&&o.warn("effectAllowed should only be changed in dragstart event: "+e.type+": data.effectAllowed changed from "+k+" -> "+r.effectAllowed),!1===t&&(o.info("applyDropEffectCallback: allowDrop === false"),r.effectAllowed="none",r.dropEffect="none"),r.isMove="move"===r.dropEffect,"dragstart"===e.type&&(k=r.effectAllowed,S=r.dropEffect),a.effectAllowed=k,a.dropEffect=S}function P(e,r){if(r.options.dnd5.scroll&&(g=r.tree,d=e,a=g.options.dnd5,n=g.$scrollParent[0],l=a.scrollSensitivity,p=a.scrollSpeed,o=0,n!==document&&"HTML"!==n.tagName?(a=g.$scrollParent.offset(),i=n.scrollTop,a.top+n.offsetHeight-d.pageY<l?0<n.scrollHeight-g.$scrollParent.innerHeight()-i&&(n.scrollTop=o=i+p):0<i&&d.pageY-a.top<l&&(n.scrollTop=o=i-p)):0<(i=c(document).scrollTop())&&d.pageY-i<l?(o=i-p,c(document).scrollTop(o)):c(window).height()-(d.pageY-i)<l&&(o=i+p,c(document).scrollTop(o)),o&&g.debug("autoScroll: "+o+"px")),!r.node)return r.tree.warn("Ignored dragover for non-node"),C;var t,o,a=null,n=r.tree,d=n.options,s=d.dnd5,l=r.node,i=r.otherNode,f="center",p=c(l.span),g=p.find("span.fancytree-title");if(!1===x)return n.debug("Ignored dragover, since dragenter returned false."),!1;if("string"==typeof x&&c.error("assert failed: dragenter returned string"),o=p.offset(),p=(e.pageY-o.top)/p.height(),void 0===e.pageY&&n.warn("event.pageY is undefined: see issue #1013."),x.after&&.75<p||!x.over&&x.after&&.5<p?a="after":x.before&&p<=.25||!x.over&&x.before&&p<=.5?a="before":x.over&&(a="over"),s.preventVoidMoves&&"move"===r.dropEffect&&(l===i?(l.debug("Drop over source node prevented."),a=null):"before"===a&&i&&l===i.getNextSibling()?(l.debug("Drop after source node prevented."),a=null):"after"===a&&i&&l===i.getPrevSibling()?(l.debug("Drop before source node prevented."),a=null):"over"===a&&i&&i.parent===l&&i.isLastSibling()&&(l.debug("Drop last child over own parent prevented."),a=null)),(r.hitMode=a)&&s.dragOver&&(I(e,r),s.dragOver(l,r),O(e,r,!!a),a=r.hitMode),"after"===(C=a)||"before"===a||"over"===a){switch(t=s.dropMarkerOffsetX||0,a){case"before":f="top",t+=s.dropMarkerInsertOffsetX||0;break;case"after":f="bottom",t+=s.dropMarkerInsertOffsetX||0}g={my:"left"+T(t)+" center",at:"left "+f,of:g},d.rtl&&(g.my="right"+T(-t)+" center",g.at="right "+f),D.toggleClass(y,"after"===a).toggleClass(h,"over"===a).toggleClass(b,"before"===a).show().position(u.fixPositionOptions(g))}else D.hide();return c(l.span).toggleClass(E,"after"===a||"before"===a||"over"===a).toggleClass(y,"after"===a).toggleClass(b,"before"===a).toggleClass(v,"over"===a).toggleClass(m,!1===a),a}function j(e){var r,t=this,o=t.options.dnd5,a=null,n=u.getNode(e),d=e.dataTransfer||e.originalEvent.dataTransfer,s={tree:t,node:n,options:t.options,originalEvent:e.originalEvent,widget:t.widget,hitMode:x,dataTransfer:d,otherNode:g||null,otherNodeList:w||null,otherNodeData:null,useDefaultImage:!0,dropEffect:void 0,dropEffectSuggested:void 0,effectAllowed:void 0,files:null,isCancelled:void 0,isMove:void 0};switch(e.type){case"dragenter":if(M=null,!n){t.debug("Ignore non-node "+e.type+": "+e.target.tagName+"."+e.target.className),x=!1;break}if(c(n.span).addClass(h).removeClass(v+" "+m),r=0<=c.inArray(p,d.types),o.preventNonNodes&&!r){n.debug("Reject dropping a non-node."),x=!1;break}if(o.preventForeignNodes&&(!g||g.tree!==n.tree)){n.debug("Reject dropping a foreign node."),x=!1;break}if(o.preventSameParent&&s.otherNode&&s.otherNode.tree===n.tree&&n.parent===s.otherNode.parent){n.debug("Reject dropping as sibling (same parent)."),x=!1;break}if(o.preventRecursion&&s.otherNode&&s.otherNode.tree===n.tree&&n.isDescendantOf(s.otherNode)){n.debug("Reject dropping below own ancestor."),x=!1;break}if(o.preventLazyParents&&!n.isLoaded()){n.warn("Drop over unloaded target node prevented."),x=!1;break}D.show(),I(e,s),r=o.dragEnter(n,s),r=!!(r=r)&&(r=c.isPlainObject(r)?{over:!!r.over,before:!!r.before,after:!!r.after}:Array.isArray(r)?{over:0<=c.inArray("over",r),before:0<=c.inArray("before",r),after:0<=c.inArray("after",r)}:{over:!0===r||"over"===r,before:!0===r||"before"===r,after:!0===r||"after"===r},0!==Object.keys(r).length&&r),O(e,s,a=(x=r)&&(r.over||r.before||r.after));break;case"dragover":if(!n){t.debug("Ignore non-node "+e.type+": "+e.target.tagName+"."+e.target.className);break}I(e,s),a=!!(C=P(e,s)),("over"===C||!1===C)&&!n.expanded&&!1!==n.hasChildren()?M?!(o.autoExpandMS&&Date.now()-M>o.autoExpandMS)||n.isLoading()||o.dragExpand&&!1===o.dragExpand(n,s)||n.setExpanded():M=Date.now():M=null;break;case"dragleave":if(!n){t.debug("Ignore non-node "+e.type+": "+e.target.tagName+"."+e.target.className);break}if(!c(n.span).hasClass(h)){n.debug("Ignore dragleave (multi).");break}c(n.span).removeClass(h+" "+v+" "+m),n.scheduleAction("cancel"),o.dragLeave(n,s),D.hide();break;case"drop":if(0<=c.inArray(p,d.types)&&(i=d.getData(p),t.info(e.type+": getData('application/x-fancytree-node'): '"+i+"'")),i||(i=d.getData("text"),t.info(e.type+": getData('text'): '"+i+"'")),i)try{void 0!==(l=JSON.parse(i)).title&&(s.otherNodeData=l)}catch(e){}t.debug(e.type+": nodeData: '"+i+"', otherNodeData: ",s.otherNodeData),c(n.span).removeClass(h+" "+v+" "+m),s.hitMode=C,I(e,s),s.isCancelled=!C;var l=g&&g.span,i=g&&g.tree;o.dragDrop(n,s),e.preventDefault(),l&&!document.body.contains(l)&&(i===t?(t.debug("Drop handler removed source element: generating dragEnd."),o.dragEnd(g,s)):t.warn("Drop handler removed source element: dragend event may be lost.")),A()}if(a)return e.preventDefault(),!1}return c.ui.fancytree.getDragNodeList=function(){return w||[]},c.ui.fancytree.getDragNode=function(){return g},c.ui.fancytree.registerExtension({name:"dnd5",version:"2.38.3",options:{autoExpandMS:1500,dropMarkerInsertOffsetX:-16,dropMarkerOffsetX:-24,dropMarkerParent:"body",multiSource:!1,effectAllowed:"all",dropEffectDefault:"move",preventForeignNodes:!1,preventLazyParents:!0,preventNonNodes:!1,preventRecursion:!0,preventSameParent:!1,preventVoidMoves:!0,scroll:!0,scrollSensitivity:20,scrollSpeed:5,setTextTypeJson:!1,sourceCopyHook:null,dragStart:null,dragDrag:c.noop,dragEnd:c.noop,dragEnter:null,dragOver:c.noop,dragExpand:c.noop,dragDrop:c.noop,dragLeave:c.noop},treeInit:function(e){var r=e.tree,t=e.options,o=t.glyph||null,a=t.dnd5;0<=c.inArray("dnd",t.extensions)&&c.error("Extensions 'dnd' and 'dnd5' are mutually exclusive."),a.dragStop&&c.error("dragStop is not used by ext-dnd5. Use dragEnd instead."),null!=a.preventRecursiveMoves&&c.error("preventRecursiveMoves was renamed to preventRecursion."),a.dragStart&&u.overrideMethod(e.options,"createNode",function(e,r){this._super.apply(this,arguments),r.node.span?r.node.span.draggable=!0:r.node.warn("Cannot add `draggable`: no span tag")}),this._superApply(arguments),this.$container.addClass("fancytree-ext-dnd5"),e=c("<span>").appendTo(this.$container),this.$scrollParent=e.scrollParent(),e.remove(),(D=c("#fancytree-drop-marker")).length||(D=c("<div id='fancytree-drop-marker'></div>").hide().css({"z-index":1e3,"pointer-events":"none"}).prependTo(a.dropMarkerParent),o&&u.setSpanIcon(D[0],o.map._addClass,o.map.dropMarker)),D.toggleClass("fancytree-rtl",!!t.rtl),a.dragStart&&r.$container.on("dragstart drag dragend",function(e){var r=this,t=r.options.dnd5,o=u.getNode(e),a=e.dataTransfer||e.originalEvent.dataTransfer,n={tree:r,node:o,options:r.options,originalEvent:e.originalEvent,widget:r.widget,dataTransfer:a,useDefaultImage:!0,dropEffect:void 0,dropEffectSuggested:void 0,effectAllowed:void 0,files:void 0,isCancelled:void 0,isMove:void 0};switch(e.type){case"dragstart":if(!o)return r.info("Ignored dragstart on a non-node."),!1;g=o,w=!1===t.multiSource?[o]:!0===t.multiSource?o.isSelected()?r.getSelectedNodes():[o]:t.multiSource(o,n),(N=c(c.map(w,function(e){return e.span}))).addClass(i);var d=o.toDict(!0,t.sourceCopyHook);d.treeId=o.tree._id,d=JSON.stringify(d);try{a.setData(p,d),a.setData("text/html",c(o.span).html()),a.setData("text/plain",o.title)}catch(e){r.warn("Could not set data (IE only accepts 'text') - "+e)}return(t.setTextTypeJson?a.setData("text",d):a.setData("text",o.title),I(e,n),!1===t.dragStart(o,n))?(A(),!1):(O(e,n),l=null,n.useDefaultImage&&(s=c(o.span).find(".fancytree-title"),w&&1<w.length&&(l=c("<span class='fancytree-childcounter'/>").text("+"+(w.length-1)).appendTo(s)),a.setDragImage&&a.setDragImage(s[0],-10,-10)),!0);case"drag":I(e,n),t.dragDrag(o,n),O(e,n),N.toggleClass(f,n.isMove);break;case"dragend":I(e,n),A(),n.isCancelled=!C,t.dragEnd(o,n,!C)}}.bind(r)),a.dragEnter&&r.$container.on("dragenter dragover dragleave drop",j.bind(r))}}),c.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.edit.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(l){"use strict";var t=/Mac/.test(navigator.platform),c=l.ui.fancytree.escapeHtml,u=l.ui.fancytree.trim,o=l.ui.fancytree.unescapeHtml;return l.ui.fancytree._FancytreeNodeClass.prototype.editStart=function(){var t,i=this,e=this.tree,n=e.ext.edit,r=e.options.edit,a=l(".fancytree-title",i.span),s={node:i,tree:e,options:e.options,isNew:l(i[e.statusClassPropName]).hasClass("fancytree-edit-new"),orgTitle:i.title,input:null,dirty:!1};if(!1===r.beforeEdit.call(i,{type:"beforeEdit"},s))return!1;l.ui.fancytree.assert(!n.currentNode,"recursive edit"),n.currentNode=this,n.eventData=s,e.widget._unbind(),n.lastDraggableAttrValue=i.span.draggable,n.lastDraggableAttrValue&&(i.span.draggable=!1),l(document).on("mousedown.fancytree-edit",function(e){l(e.target).hasClass("fancytree-edit-input")||i.editEnd(!0,e)}),t=l("<input />",{class:"fancytree-edit-input",type:"text",value:e.options.escapeTitles?s.orgTitle:o(s.orgTitle)}),n.eventData.input=t,null!=r.adjustWidthOfs&&t.width(a.width()+r.adjustWidthOfs),null!=r.inputCss&&t.css(r.inputCss),a.html(t),t.focus().change(function(e){t.addClass("fancytree-edit-dirty")}).on("keydown",function(e){switch(e.which){case l.ui.keyCode.ESCAPE:i.editEnd(!1,e);break;case l.ui.keyCode.ENTER:return i.editEnd(!0,e),!1}e.stopPropagation()}).blur(function(e){return i.editEnd(!0,e)}),r.edit.call(i,{type:"edit"},s)},l.ui.fancytree._FancytreeNodeClass.prototype.editEnd=function(e,t){var i,n=this,r=this.tree,a=r.ext.edit,s=a.eventData,o=r.options.edit,d=l(".fancytree-title",n.span).find("input.fancytree-edit-input");return o.trim&&d.val(u(d.val())),i=d.val(),s.dirty=i!==n.title,s.originalEvent=t,!1===e?s.save=!1:s.isNew?s.save=""!==i:s.save=s.dirty&&""!==i,!1!==o.beforeClose.call(n,{type:"beforeClose"},s)&&((!s.save||!1!==o.save.call(n,{type:"save"},s))&&(d.removeClass("fancytree-edit-dirty").off(),l(document).off(".fancytree-edit"),s.save?(n.setTitle(r.options.escapeTitles?i:c(i)),n.setFocus()):s.isNew?(n.remove(),n=s.node=null,a.relatedNode.setFocus()):(n.renderTitle(),n.setFocus()),a.eventData=null,a.currentNode=null,a.relatedNode=null,r.widget._bind(),n&&a.lastDraggableAttrValue&&(n.span.draggable=!0),r.$container.get(0).focus({preventScroll:!0}),s.input=null,o.close.call(n,{type:"close"},s),!0))},l.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode=function(e,t){var i,n=this.tree,r=this;e=e||"child",null==t?t={title:""}:"string"==typeof t?t={title:t}:l.ui.fancytree.assert(l.isPlainObject(t)),"child"!==e||this.isExpanded()||!1===this.hasChildren()?((i=this.addNode(t,e)).match=!0,l(i[n.statusClassPropName]).removeClass("fancytree-hide").addClass("fancytree-match"),i.makeVisible().done(function(){l(i[n.statusClassPropName]).addClass("fancytree-edit-new"),r.tree.ext.edit.relatedNode=r,i.editStart()})):this.setExpanded().done(function(){r.editCreateNode(e,t)})},l.ui.fancytree._FancytreeClass.prototype.isEditing=function(){return this.ext.edit?this.ext.edit.currentNode:null},l.ui.fancytree._FancytreeNodeClass.prototype.isEditing=function(){return!!this.tree.ext.edit&&this.tree.ext.edit.currentNode===this},l.ui.fancytree.registerExtension({name:"edit",version:"2.38.3",options:{adjustWidthOfs:4,allowEmpty:!1,inputCss:{minWidth:"3em"},triggerStart:["f2","mac+enter","shift+click"],trim:!0,beforeClose:l.noop,beforeEdit:l.noop,close:l.noop,edit:l.noop,save:l.noop},currentNode:null,treeInit:function(e){var n=e.tree;this._superApply(arguments),this.$container.addClass("fancytree-ext-edit").on("fancytreebeforeupdateviewport",function(e,t){var i=n.isEditing();i&&(i.info("Cancel edit due to scroll event."),i.editEnd(!1,e))})},nodeClick:function(e){var t=l.ui.fancytree.eventToString(e.originalEvent),i=e.options.edit.triggerStart;return"shift+click"===t&&0<=l.inArray("shift+click",i)&&e.originalEvent.shiftKey||"click"===t&&0<=l.inArray("clickActive",i)&&e.node.isActive()&&!e.node.isEditing()&&l(e.originalEvent.target).hasClass("fancytree-title")?(e.node.editStart(),!1):this._superApply(arguments)},nodeDblclick:function(e){return 0<=l.inArray("dblclick",e.options.edit.triggerStart)?(e.node.editStart(),!1):this._superApply(arguments)},nodeKeydown:function(e){switch(e.originalEvent.which){case 113:if(0<=l.inArray("f2",e.options.edit.triggerStart))return e.node.editStart(),!1;break;case l.ui.keyCode.ENTER:if(0<=l.inArray("mac+enter",e.options.edit.triggerStart)&&t)return e.node.editStart(),!1}return this._superApply(arguments)}}),l.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.filter.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(g){"use strict";var m="__not_found__",x=g.ui.fancytree.escapeHtml;function v(e){return(e+"").replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function C(e,t,i){for(var n=[],a=1;a<t.length;a++){var r=t[a].length+(1===a?0:1)+(n[n.length-1]||0);n.push(r)}var s=e.split("");return i?n.forEach(function(e){s[e]="\ufff7"+s[e]+"\ufff8"}):n.forEach(function(e){s[e]="<mark>"+s[e]+"</mark>"}),s.join("")}return g.ui.fancytree._FancytreeClass.prototype._applyFilterImpl=function(n,a,e){var t,r,s,l,o,h,d=0,i=this.options,c=i.escapeTitles,u=i.autoCollapse,p=g.extend({},i.filter,e),f="hide"===p.mode,y=!!p.leavesOnly&&!a;if("string"==typeof n){if(""===n)return this.warn("Fancytree passing an empty string as a filter is handled as clearFilter()."),void this.clearFilter();t=p.fuzzy?n.split("").map(v).reduce(function(e,t){return e+"([^"+t+"]*)"+t},""):v(n),r=new RegExp(t,"i"),s=new RegExp(v(n),"gi"),c&&(l=new RegExp(v("\ufff7"),"g"),o=new RegExp(v("\ufff8"),"g")),n=function(e){if(!e.title)return!1;var t,i=c?e.title:0<=(t=e.title).indexOf(">")?g("<div/>").html(t).text():t,t=i.match(r);return t&&p.highlight&&(c?(h=p.fuzzy?C(i,t,c):i.replace(s,function(e){return"\ufff7"+e+"\ufff8"}),e.titleWithHighlight=x(h).replace(l,"<mark>").replace(o,"</mark>")):p.fuzzy?e.titleWithHighlight=C(i,t):e.titleWithHighlight=i.replace(s,function(e){return"<mark>"+e+"</mark>"})),!!t}}return this.enableFilter=!0,this.lastFilterArgs=arguments,e=this.enableUpdate(!1),this.$div.addClass("fancytree-ext-filter"),f?this.$div.addClass("fancytree-ext-filter-hide"):this.$div.addClass("fancytree-ext-filter-dimm"),this.$div.toggleClass("fancytree-ext-filter-hide-expanders",!!p.hideExpanders),this.rootNode.subMatchCount=0,this.visit(function(e){delete e.match,delete e.titleWithHighlight,e.subMatchCount=0}),(t=this.getRootNode()._findDirectChild(m))&&t.remove(),i.autoCollapse=!1,this.visit(function(t){if(!y||null==t.children){var e=n(t),i=!1;if("skip"===e)return t.visit(function(e){e.match=!1},!0),"skip";e||!a&&"branch"!==e||!t.parent.match||(i=e=!0),e&&(d++,t.match=!0,t.visitParents(function(e){e!==t&&(e.subMatchCount+=1),!p.autoExpand||i||e.expanded||(e.setExpanded(!0,{noAnimation:!0,noEvents:!0,scrollIntoView:!1}),e._filterAutoExpanded=!0)},!0))}}),i.autoCollapse=u,0===d&&p.nodata&&f&&(!0===(t="function"==typeof(t=p.nodata)?t():t)?t={}:"string"==typeof t&&(t={title:t}),t=g.extend({statusNodeType:"nodata",key:m,title:this.options.strings.noData},t),this.getRootNode().addNode(t).match=!0),this._callHook("treeStructureChanged",this,"applyFilter"),this.enableUpdate(e),d},g.ui.fancytree._FancytreeClass.prototype.filterNodes=function(e,t){return"boolean"==typeof t&&(t={leavesOnly:t},this.warn("Fancytree.filterNodes() leavesOnly option is deprecated since 2.9.0 / 2015-04-19. Use opts.leavesOnly instead.")),this._applyFilterImpl(e,!1,t)},g.ui.fancytree._FancytreeClass.prototype.filterBranches=function(e,t){return this._applyFilterImpl(e,!0,t)},g.ui.fancytree._FancytreeClass.prototype.updateFilter=function(){this.enableFilter&&this.lastFilterArgs&&this.options.filter.autoApply?this._applyFilterImpl.apply(this,this.lastFilterArgs):this.warn("updateFilter(): no filter active.")},g.ui.fancytree._FancytreeClass.prototype.clearFilter=function(){var t,e=this.getRootNode()._findDirectChild(m),i=this.options.escapeTitles,n=this.options.enhanceTitle,a=this.enableUpdate(!1);e&&e.remove(),delete this.rootNode.match,delete this.rootNode.subMatchCount,this.visit(function(e){e.match&&e.span&&(t=g(e.span).find(">span.fancytree-title"),i?t.text(e.title):t.html(e.title),n&&n({type:"enhanceTitle"},{node:e,$title:t})),delete e.match,delete e.subMatchCount,delete e.titleWithHighlight,e.$subMatchBadge&&(e.$subMatchBadge.remove(),delete e.$subMatchBadge),e._filterAutoExpanded&&e.expanded&&e.setExpanded(!1,{noAnimation:!0,noEvents:!0,scrollIntoView:!1}),delete e._filterAutoExpanded}),this.enableFilter=!1,this.lastFilterArgs=null,this.$div.removeClass("fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide"),this._callHook("treeStructureChanged",this,"clearFilter"),this.enableUpdate(a)},g.ui.fancytree._FancytreeClass.prototype.isFilterActive=function(){return!!this.enableFilter},g.ui.fancytree._FancytreeNodeClass.prototype.isMatched=function(){return!(this.tree.enableFilter&&!this.match)},g.ui.fancytree.registerExtension({name:"filter",version:"2.38.3",options:{autoApply:!0,autoExpand:!1,counter:!0,fuzzy:!1,hideExpandedCounter:!0,hideExpanders:!1,highlight:!0,leavesOnly:!1,nodata:!0,mode:"dimm"},nodeLoadChildren:function(e,t){var i=e.tree;return this._superApply(arguments).done(function(){i.enableFilter&&i.lastFilterArgs&&e.options.filter.autoApply&&i._applyFilterImpl.apply(i,i.lastFilterArgs)})},nodeSetExpanded:function(e,t,i){var n=e.node;return delete n._filterAutoExpanded,!t&&e.options.filter.hideExpandedCounter&&n.$subMatchBadge&&n.$subMatchBadge.show(),this._superApply(arguments)},nodeRenderStatus:function(e){var t=e.node,i=e.tree,n=e.options.filter,a=g(t.span).find("span.fancytree-title"),r=g(t[i.statusClassPropName]),s=e.options.enhanceTitle,l=e.options.escapeTitles,e=this._super(e);return r.length&&i.enableFilter&&(r.toggleClass("fancytree-match",!!t.match).toggleClass("fancytree-submatch",!!t.subMatchCount).toggleClass("fancytree-hide",!(t.match||t.subMatchCount)),!n.counter||!t.subMatchCount||t.isExpanded()&&n.hideExpandedCounter?t.$subMatchBadge&&t.$subMatchBadge.hide():(t.$subMatchBadge||(t.$subMatchBadge=g("<span class='fancytree-childcounter'/>"),g("span.fancytree-icon, span.fancytree-custom-icon",t.span).append(t.$subMatchBadge)),t.$subMatchBadge.show().text(t.subMatchCount)),!t.span||t.isEditing&&t.isEditing.call(t)||(t.titleWithHighlight?a.html(t.titleWithHighlight):l?a.text(t.title):a.html(t.title),s&&s({type:"enhanceTitle"},{node:t,$title:a}))),e}}),g.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.glyph.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(i){"use strict";var d=i.ui.fancytree,n={awesome3:{_addClass:"",checkbox:"icon-check-empty",checkboxSelected:"icon-check",checkboxUnknown:"icon-check icon-muted",dragHelper:"icon-caret-right",dropMarker:"icon-caret-right",error:"icon-exclamation-sign",expanderClosed:"icon-caret-right",expanderLazy:"icon-angle-right",expanderOpen:"icon-caret-down",loading:"icon-refresh icon-spin",nodata:"icon-meh",noExpander:"",radio:"icon-circle-blank",radioSelected:"icon-circle",doc:"icon-file-alt",docOpen:"icon-file-alt",folder:"icon-folder-close-alt",folderOpen:"icon-folder-open-alt"},awesome4:{_addClass:"fa",checkbox:"fa-square-o",checkboxSelected:"fa-check-square-o",checkboxUnknown:"fa-square fancytree-helper-indeterminate-cb",dragHelper:"fa-arrow-right",dropMarker:"fa-long-arrow-right",error:"fa-warning",expanderClosed:"fa-caret-right",expanderLazy:"fa-angle-right",expanderOpen:"fa-caret-down",loading:{html:"<span class='fa fa-spinner fa-pulse' />"},nodata:"fa-meh-o",noExpander:"",radio:"fa-circle-thin",radioSelected:"fa-circle",doc:"fa-file-o",docOpen:"fa-file-o",folder:"fa-folder-o",folderOpen:"fa-folder-open-o"},awesome5:{_addClass:"",checkbox:"far fa-square",checkboxSelected:"far fa-check-square",checkboxUnknown:"fas fa-square fancytree-helper-indeterminate-cb",radio:"far fa-circle",radioSelected:"fas fa-circle",radioUnknown:"far fa-dot-circle",dragHelper:"fas fa-arrow-right",dropMarker:"fas fa-long-arrow-alt-right",error:"fas fa-exclamation-triangle",expanderClosed:"fas fa-caret-right",expanderLazy:"fas fa-angle-right",expanderOpen:"fas fa-caret-down",loading:"fas fa-spinner fa-pulse",nodata:"far fa-meh",noExpander:"",doc:"far fa-file",docOpen:"far fa-file",folder:"far fa-folder",folderOpen:"far fa-folder-open"},bootstrap3:{_addClass:"glyphicon",checkbox:"glyphicon-unchecked",checkboxSelected:"glyphicon-check",checkboxUnknown:"glyphicon-expand fancytree-helper-indeterminate-cb",dragHelper:"glyphicon-play",dropMarker:"glyphicon-arrow-right",error:"glyphicon-warning-sign",expanderClosed:"glyphicon-menu-right",expanderLazy:"glyphicon-menu-right",expanderOpen:"glyphicon-menu-down",loading:"glyphicon-refresh fancytree-helper-spin",nodata:"glyphicon-info-sign",noExpander:"",radio:"glyphicon-remove-circle",radioSelected:"glyphicon-ok-circle",doc:"glyphicon-file",docOpen:"glyphicon-file",folder:"glyphicon-folder-close",folderOpen:"glyphicon-folder-open"},material:{_addClass:"material-icons",checkbox:{text:"check_box_outline_blank"},checkboxSelected:{text:"check_box"},checkboxUnknown:{text:"indeterminate_check_box"},dragHelper:{text:"play_arrow"},dropMarker:{text:"arrow-forward"},error:{text:"warning"},expanderClosed:{text:"chevron_right"},expanderLazy:{text:"last_page"},expanderOpen:{text:"expand_more"},loading:{text:"autorenew",addClass:"fancytree-helper-spin"},nodata:{text:"info"},noExpander:{text:""},radio:{text:"radio_button_unchecked"},radioSelected:{text:"radio_button_checked"},doc:{text:"insert_drive_file"},docOpen:{text:"insert_drive_file"},folder:{text:"folder"},folderOpen:{text:"folder_open"}}};function l(e,r,n,a,o){var t=a.map,c=t[o],d=i(r),a=d.find(".fancytree-childcounter"),t=n+" "+(t._addClass||"");"string"==typeof(c="function"==typeof c?c.call(this,e,r,o):c)?(r.innerHTML="",d.attr("class",t+" "+c).append(a)):c&&(c.text?r.textContent=""+c.text:c.html?r.innerHTML=c.html:r.innerHTML="",d.attr("class",t+" "+(c.addClass||"")).append(a))}return i.ui.fancytree.registerExtension({name:"glyph",version:"2.38.3",options:{preset:null,map:{}},treeInit:function(e){var r=e.tree,e=e.options.glyph;e.preset?(d.assert(!!n[e.preset],"Invalid value for `options.glyph.preset`: "+e.preset),e.map=i.extend({},n[e.preset],e.map)):r.warn("ext-glyph: missing `preset` option."),this._superApply(arguments),r.$container.addClass("fancytree-ext-glyph")},nodeRenderStatus:function(e){var r,n,a=e.node,o=i(a.span),t=e.options.glyph,c=this._super(e);return a.isRootNode()||((n=o.children(".fancytree-expander").get(0))&&(r=a.expanded&&a.hasChildren()?"expanderOpen":a.isUndefined()?"expanderLazy":a.hasChildren()?"expanderClosed":"noExpander",l(a,n,"fancytree-expander",t,r)),(n=(a.tr?i("td",a.tr).find(".fancytree-checkbox"):o.children(".fancytree-checkbox")).get(0))&&(e=d.evalOption("checkbox",a,a,t,!1),a.parent&&a.parent.radiogroup||"radio"===e?l(a,n,"fancytree-checkbox fancytree-radio",t,r=a.selected?"radioSelected":"radio"):l(a,n,"fancytree-checkbox",t,r=a.selected?"checkboxSelected":a.partsel?"checkboxUnknown":"checkbox")),(n=o.children(".fancytree-icon").get(0))&&(r=a.statusNodeType||(a.folder?a.expanded&&a.hasChildren()?"folderOpen":"folder":a.expanded?"docOpen":"doc"),l(a,n,"fancytree-icon",t,r))),c},nodeSetStatus:function(e,r,n,a){var o,t=e.options.glyph,c=e.node,e=this._superApply(arguments);return"error"!==r&&"loading"!==r&&"nodata"!==r||(c.parent?(o=i(".fancytree-expander",c.span).get(0))&&l(c,o,"fancytree-expander",t,r):(o=i(".fancytree-statusnode-"+r,c[this.nodeContainerAttrName]).find(".fancytree-icon").get(0))&&l(c,o,"fancytree-icon",t,r)),e}}),i.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.gridnav.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree","./jquery.fancytree.table"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree.table"),module.exports=e(require("jquery"))):e(jQuery)}(function(l){"use strict";var p=l.ui.keyCode,o={text:[p.UP,p.DOWN],checkbox:[p.UP,p.DOWN,p.LEFT,p.RIGHT],link:[p.UP,p.DOWN,p.LEFT,p.RIGHT],radiobutton:[p.UP,p.DOWN,p.LEFT,p.RIGHT],"select-one":[p.LEFT,p.RIGHT],"select-multiple":[p.LEFT,p.RIGHT]};function a(e,t){var n,i,r,o,a,s,u=e.closest("td"),c=null;switch(t){case p.LEFT:c=u.prev();break;case p.RIGHT:c=u.next();break;case p.UP:case p.DOWN:for(n=u.parent(),r=n,a=u.get(0),s=0,r.children().each(function(){return this!==a&&(o=l(this).prop("colspan"),void(s+=o||1))}),i=s;(n=t===p.UP?n.prev():n.next()).length&&(n.is(":hidden")||!(c=function(e,t){var n,i=null,r=0;return e.children().each(function(){return t<=r?(i=l(this),!1):(n=l(this).prop("colspan"),void(r+=n||1))}),i}(n,i))||!c.find(":input,a").length););}return c}return l.ui.fancytree.registerExtension({name:"gridnav",version:"2.38.3",options:{autofocusInput:!1,handleCursorKeys:!0},treeInit:function(n){this._requireExtension("table",!0,!0),this._superApply(arguments),this.$container.addClass("fancytree-ext-gridnav"),this.$container.on("focusin",function(e){var t=l.ui.fancytree.getNode(e.target);t&&!t.isActive()&&(e=n.tree._makeHookContext(t,e),n.tree._callHook("nodeSetActive",e,!0))})},nodeSetActive:function(e,t,n){var i=e.options.gridnav,r=e.node,o=e.originalEvent||{},o=l(o.target).is(":input");t=!1!==t,this._superApply(arguments),t&&(e.options.titlesTabbable?(o||(l(r.span).find("span.fancytree-title").focus(),r.setFocus()),e.tree.$container.attr("tabindex","-1")):i.autofocusInput&&!o&&l(r.tr||r.span).find(":input:enabled").first().focus())},nodeKeydown:function(e){var t,n,i=e.options.gridnav,r=e.originalEvent,e=l(r.target);return e.is(":input:enabled")?t=e.prop("type"):e.is("a")&&(t="link"),t&&i.handleCursorKeys?!((t=o[t])&&0<=l.inArray(r.which,t)&&(n=a(e,r.which))&&n.length)||(n.find(":input:enabled,a").focus(),!1):this._superApply(arguments)}}),l.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.multi.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(o){"use strict";return o.ui.fancytree.registerExtension({name:"multi",version:"2.38.3",options:{allowNoSelect:!1,mode:"sameParent"},treeInit:function(e){this._superApply(arguments),this.$container.addClass("fancytree-ext-multi"),1===e.options.selectMode&&o.error("Fancytree ext-multi: selectMode: 1 (single) is not compatible.")},nodeClick:function(e){var t=e.tree,i=e.node,r=t.getActiveNode()||t.getFirstChild(),n="checkbox"===e.targetType,c="expander"===e.targetType;switch(o.ui.fancytree.eventToString(e.originalEvent)){case"click":if(c)break;n||(t.selectAll(!1),i.setSelected());break;case"shift+click":t.visitRows(function(e){if(e.setSelected(),e===i)return!1},{start:r,reverse:r.isBelowOf(i)});break;case"ctrl+click":case"meta+click":return void i.toggleSelected()}return this._superApply(arguments)},nodeKeydown:function(e){var t=e.tree,i=e.node,r=e.originalEvent;switch(o.ui.fancytree.eventToString(r)){case"up":case"down":t.selectAll(!1),i.navigate(r.which,!0),t.getActiveNode().setSelected();break;case"shift+up":case"shift+down":i.navigate(r.which,!0),t.getActiveNode().setSelected()}return this._superApply(arguments)}}),o.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.persist.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(y){"use strict";var t=null,o=null,i=null,s=y.ui.fancytree.assert,u="active",v="expanded",p="focus",f="selected";try{s(window.localStorage&&window.localStorage.getItem),o={get:function(e){return window.localStorage.getItem(e)},set:function(e,t){window.localStorage.setItem(e,t)},remove:function(e){window.localStorage.removeItem(e)}}}catch(e){y.ui.fancytree.warn("Could not access window.localStorage",e)}try{s(window.sessionStorage&&window.sessionStorage.getItem),i={get:function(e){return window.sessionStorage.getItem(e)},set:function(e,t){window.sessionStorage.setItem(e,t)},remove:function(e){window.sessionStorage.removeItem(e)}}}catch(e){y.ui.fancytree.warn("Could not access window.sessionStorage",e)}return"function"==typeof Cookies?t={get:Cookies.get,set:function(e,t){Cookies.set(e,t,this.options.persist.cookie)},remove:Cookies.remove}:y&&"function"==typeof y.cookie&&(t={get:y.cookie,set:function(e,t){y.cookie(e,t,this.options.persist.cookie)},remove:y.removeCookie}),y.ui.fancytree._FancytreeClass.prototype.clearPersistData=function(e){var t=this.ext.persist,o=t.cookiePrefix;0<=(e=e||"active expanded focus selected").indexOf(u)&&t._data(o+u,null),0<=e.indexOf(v)&&t._data(o+v,null),0<=e.indexOf(p)&&t._data(o+p,null),0<=e.indexOf(f)&&t._data(o+f,null)},y.ui.fancytree._FancytreeClass.prototype.clearCookies=function(e){return this.warn("'tree.clearCookies()' is deprecated since v2.27.0: use 'clearPersistData()' instead."),this.clearPersistData(e)},y.ui.fancytree._FancytreeClass.prototype.getPersistData=function(){var e=this.ext.persist,t=e.cookiePrefix,o=e.cookieDelimiter,i={};return i[u]=e._data(t+u),i[v]=(e._data(t+v)||"").split(o),i[f]=(e._data(t+f)||"").split(o),i[p]=e._data(t+p),i},y.ui.fancytree.registerExtension({name:"persist",version:"2.38.3",options:{cookieDelimiter:"~",cookiePrefix:void 0,cookie:{raw:!1,expires:"",path:"",domain:"",secure:!1},expandLazy:!1,expandOpts:void 0,fireActivate:!0,overrideSource:!0,store:"auto",types:"active expanded focus selected"},_data:function(e,t){var o=this._local.store;if(void 0===t)return o.get.call(this,e);null===t?o.remove.call(this,e):o.set.call(this,e,t)},_appendKey:function(e,t,o){t=""+t;var i=this._local,s=this.options.persist.cookieDelimiter,r=i.cookiePrefix+e,n=i._data(r),e=n?n.split(s):[],n=y.inArray(t,e);0<=n&&e.splice(n,1),o&&e.push(t),i._data(r,e.join(s))},treeInit:function(e){var a=e.tree,c=e.options,d=this._local,l=this.options.persist;return d.cookiePrefix=l.cookiePrefix||"fancytree-"+a._id+"-",d.storeActive=0<=l.types.indexOf(u),d.storeExpanded=0<=l.types.indexOf(v),d.storeSelected=0<=l.types.indexOf(f),d.storeFocus=0<=l.types.indexOf(p),d.store=null,"auto"===l.store&&(l.store=o?"local":"cookie"),y.isPlainObject(l.store)?d.store=l.store:"cookie"===l.store?d.store=t:"local"!==l.store&&"session"!==l.store||(d.store="local"===l.store?o:i),s(d.store,"Need a valid store."),a.$div.on("fancytreeinit",function(e){var t,o,i,s,r,n;!1!==a._triggerTreeEvent("beforeRestore",null,{})&&(i=d._data(d.cookiePrefix+p),s=!1===l.fireActivate,r=d._data(d.cookiePrefix+v),n=r&&r.split(l.cookieDelimiter),(d.storeExpanded?function e(t,o,i,s,r){var n,a,c,d,l=!1,u=t.options.persist.expandOpts,p=[],f=[];for(i=i||[],r=r||y.Deferred(),n=0,c=i.length;n<c;n++)a=i[n],(d=t.getNodeByKey(a))?s&&d.isUndefined()?(l=!0,t.debug("_loadLazyNodes: "+d+" is lazy: loading..."),"expand"===s?p.push(d.setExpanded(!0,u)):p.push(d.load())):(t.debug("_loadLazyNodes: "+d+" already loaded."),d.setExpanded(!0,u)):(f.push(a),t.debug("_loadLazyNodes: "+d+" was not yet found."));return y.when.apply(y,p).always(function(){if(l&&0<f.length)e(t,o,f,s,r);else{if(f.length)for(t.warn("_loadLazyNodes: could not load those keys: ",f),n=0,c=f.length;n<c;n++)a=i[n],o._appendKey(v,i[n],!1);r.resolve()}}),r}(a,d,n,!!l.expandLazy&&"expand",null):(new y.Deferred).resolve()).done(function(){if(d.storeSelected){if(r=d._data(d.cookiePrefix+f))for(n=r.split(l.cookieDelimiter),t=0;t<n.length;t++)(o=a.getNodeByKey(n[t]))?(void 0===o.selected||l.overrideSource&&!1===o.selected)&&(o.selected=!0,o.renderStatus()):d._appendKey(f,n[t],!1);3===a.options.selectMode&&a.visit(function(e){if(e.selected)return e.fixSelection3AfterClick(),"skip"})}d.storeActive&&(!(r=d._data(d.cookiePrefix+u))||!c.persist.overrideSource&&a.activeNode||(o=a.getNodeByKey(r))&&(o.debug("persist: set active",r),o.setActive(!0,{noFocus:!0,noEvents:s}))),d.storeFocus&&i&&(o=a.getNodeByKey(i))&&(a.options.titlesTabbable?y(o.span).find(".fancytree-title"):y(a.$container)).focus(),a._triggerTreeEvent("restore",null,{})}))}),this._superApply(arguments)},nodeSetActive:function(e,t,o){var i=this._local;return t=!1!==t,t=this._superApply(arguments),i.storeActive&&i._data(i.cookiePrefix+u,this.activeNode?this.activeNode.key:null),t},nodeSetExpanded:function(e,t,o){var i=e.node,s=this._local;return t=!1!==t,e=this._superApply(arguments),s.storeExpanded&&s._appendKey(v,i.key,t),e},nodeSetFocus:function(e,t){var o=this._local;return t=!1!==t,t=this._superApply(arguments),o.storeFocus&&o._data(o.cookiePrefix+p,this.focusNode?this.focusNode.key:null),t},nodeSetSelected:function(e,t,o){var i=e.tree,s=e.node,r=this._local;return t=!1!==t,t=this._superApply(arguments),r.storeSelected&&(3===i.options.selectMode?(i=(i=y.map(i.getSelectedNodes(!0),function(e){return e.key})).join(e.options.persist.cookieDelimiter),r._data(r.cookiePrefix+f,i)):r._appendKey(f,s.key,s.selected)),t}}),y.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.table.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(v){"use strict";var g=v.ui.fancytree.assert;function x(e,n){e.visit(function(e){var t=e.tr;if(t&&(t.style.display=e.hide||!n?"none":""),!e.expanded)return"skip"})}return v.ui.fancytree.registerExtension({name:"table",version:"2.38.3",options:{checkboxColumnIdx:null,indentation:16,mergeStatusColumns:!0,nodeColumnIdx:0},treeInit:function(e){var t,n,r,o=e.tree,d=e.options,s=d.table,a=o.widget.element;if(null!=s.customStatus&&(null==d.renderStatusColumns?(o.warn("The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' instead."),d.renderStatusColumns=s.customStatus):v.error("The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' only instead.")),d.renderStatusColumns&&!0===d.renderStatusColumns&&(d.renderStatusColumns=d.renderColumns),a.addClass("fancytree-container fancytree-ext-table"),(r=a.find(">tbody")).length||(a.find(">tr").length&&v.error("Expected table > tbody > tr. If you see this please open an issue."),r=v("<tbody>").appendTo(a)),o.tbody=r[0],o.columnCount=v("thead >tr",a).last().find(">th",a).length,(n=r.children("tr").first()).length)e=n.children("td").length,o.columnCount&&e!==o.columnCount&&(o.warn("Column count mismatch between thead ("+o.columnCount+") and tbody ("+e+"): using tbody."),o.columnCount=e),n=n.clone();else for(g(1<=o.columnCount,"Need either <thead> or <tbody> with <td> elements to determine column count."),n=v("<tr />"),t=0;t<o.columnCount;t++)n.append("<td />");n.find(">td").eq(s.nodeColumnIdx).html("<span class='fancytree-node' />"),d.aria&&(n.attr("role","row"),n.find("td").attr("role","gridcell")),o.rowFragment=document.createDocumentFragment(),o.rowFragment.appendChild(n.get(0)),r.empty(),o.statusClassPropName="tr",o.ariaPropName="tr",this.nodeContainerAttrName="tr",o.$container=a,this._superApply(arguments),v(o.rootNode.ul).remove(),o.rootNode.ul=null,this.$container.attr("tabindex",d.tabindex),d.aria&&o.$container.attr("role","treegrid").attr("aria-readonly",!0)},nodeRemoveChildMarkup:function(e){e.node.visit(function(e){e.tr&&(v(e.tr).remove(),e.tr=null)})},nodeRemoveMarkup:function(e){var t=e.node;t.tr&&(v(t.tr).remove(),t.tr=null),this.nodeRemoveChildMarkup(e)},nodeRender:function(e,t,n,r,o){var d,s,a,i,l,u,c,p,h,m=e.tree,f=e.node,y=e.options,C=!f.parent;if(!1!==m._enableUpdate){if(o||(e.hasCollapsedParents=f.parent&&!f.parent.expanded),!C)if(f.tr&&t&&this.nodeRemoveMarkup(e),f.tr)t?this.nodeRenderTitle(e):this.nodeRenderStatus(e);else{if(e.hasCollapsedParents&&!n)return;l=m.rowFragment.firstChild.cloneNode(!0),p=function(e){var t,n,r=e.parent,o=r?r.children:null;if(o&&1<o.length&&o[0]!==e)for(n=o[v.inArray(e,o)-1],g(n.tr);n.children&&n.children.length&&(t=n.children[n.children.length-1]).tr;)n=t;else n=r;return n}(f),g(p),(!0===r&&o||n&&e.hasCollapsedParents)&&(l.style.display="none"),p.tr?(h=p.tr).parentNode.insertBefore(l,h.nextSibling):(g(!p.parent,"prev. row must have a tr, or be system root"),(p=m.tbody).insertBefore(l,p.firstChild)),f.tr=l,f.key&&y.generateIds&&(f.tr.id=y.idPrefix+f.key),(f.tr.ftnode=f).span=v("span.fancytree-node",f.tr).get(0),this.nodeRenderTitle(e),y.createNode&&y.createNode.call(m,{type:"createNode"},e)}if(y.renderNode&&y.renderNode.call(m,{type:"renderNode"},e),(d=f.children)&&(C||n||f.expanded))for(a=0,i=d.length;a<i;a++)(c=v.extend({},e,{node:d[a]})).hasCollapsedParents=c.hasCollapsedParents||!f.expanded,this.nodeRender(c,t,n,r,!0);d&&!o&&(u=f.tr||null,s=m.tbody.firstChild,f.visit(function(e){var t;e.tr&&(e.parent.expanded||"none"===e.tr.style.display||(e.tr.style.display="none",x(e,!1)),e.tr.previousSibling!==u&&(f.debug("_fixOrder: mismatch at node: "+e),t=u?u.nextSibling:s,m.tbody.insertBefore(e.tr,t)),u=e.tr)}))}},nodeRenderTitle:function(e,t){var n=e.tree,r=e.node,o=e.options,d=r.isStatusNode(),s=this._super(e,t);return r.isRootNode()||(o.checkbox&&!d&&null!=o.table.checkboxColumnIdx&&(t=v("span.fancytree-checkbox",r.span),v(r.tr).find("td").eq(+o.table.checkboxColumnIdx).html(t)),this.nodeRenderStatus(e),d?o.renderStatusColumns?o.renderStatusColumns.call(n,{type:"renderStatusColumns"},e):o.table.mergeStatusColumns&&r.isTopLevel()&&v(r.tr).find(">td").eq(0).prop("colspan",n.columnCount).text(r.title).addClass("fancytree-status-merged").nextAll().remove():o.renderColumns&&o.renderColumns.call(n,{type:"renderColumns"},e)),s},nodeRenderStatus:function(e){var t=e.node,n=e.options;this._super(e),v(t.tr).removeClass("fancytree-node"),e=(t.getLevel()-1)*n.table.indentation,n.rtl?v(t.span).css({paddingRight:e+"px"}):v(t.span).css({paddingLeft:e+"px"})},nodeSetExpanded:function(t,n,r){if(n=!1!==n,t.node.expanded&&n||!t.node.expanded&&!n)return this._superApply(arguments);var o=new v.Deferred,e=v.extend({},r,{noEvents:!0,noAnimation:!0});function d(e){e?(x(t.node,n),n&&t.options.autoScroll&&!r.noAnimation&&t.node.hasChildren()?t.node.getLastChild().scrollIntoView(!0,{topNode:t.node}).always(function(){r.noEvents||t.tree._triggerNodeEvent(n?"expand":"collapse",t),o.resolveWith(t.node)}):(r.noEvents||t.tree._triggerNodeEvent(n?"expand":"collapse",t),o.resolveWith(t.node))):(r.noEvents||t.tree._triggerNodeEvent(n?"expand":"collapse",t),o.rejectWith(t.node))}return r=r||{},this._super(t,n,e).done(function(){d(!0)}).fail(function(){d(!1)}),o.promise()},nodeSetStatus:function(e,t,n,r){return"ok"!==t||(e=(e=e.node).children?e.children[0]:null)&&e.isStatusNode()&&v(e.tr).remove(),this._superApply(arguments)},treeClear:function(e){return this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode)),this._superApply(arguments)},treeDestroy:function(e){return this.$container.find("tbody").empty(),this.$source&&this.$source.removeClass("fancytree-helper-hidden"),this._superApply(arguments)}}),v.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.themeroller.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(l){"use strict";return l.ui.fancytree.registerExtension({name:"themeroller",version:"2.38.3",options:{activeClass:"ui-state-active",addClass:"ui-corner-all",focusClass:"ui-state-focus",hoverClass:"ui-state-hover",selectedClass:"ui-state-highlight"},treeInit:function(e){var s=e.widget.element,t=e.options.themeroller;this._superApply(arguments),"TABLE"===s[0].nodeName?(s.addClass("ui-widget ui-corner-all"),s.find(">thead tr").addClass("ui-widget-header"),s.find(">tbody").addClass("ui-widget-conent")):s.addClass("ui-widget ui-widget-content ui-corner-all"),s.on("mouseenter mouseleave",".fancytree-node",function(e){var s=l.ui.fancytree.getNode(e.target),e="mouseenter"===e.type;l(s.tr||s.span).toggleClass(t.hoverClass+" "+t.addClass,e)})},treeDestroy:function(e){this._superApply(arguments),e.widget.element.removeClass("ui-widget ui-widget-content ui-corner-all")},nodeRenderStatus:function(e){var s={},t=e.node,a=l(t.tr||t.span),i=e.options.themeroller;this._super(e),s[i.activeClass]=!1,s[i.focusClass]=!1,s[i.selectedClass]=!1,t.isActive()&&(s[i.activeClass]=!0),t.hasFocus()&&(s[i.focusClass]=!0),t.isSelected()&&!t.isActive()&&(s[i.selectedClass]=!0),a.toggleClass(i.activeClass,s[i.activeClass]),a.toggleClass(i.focusClass,s[i.focusClass]),a.toggleClass(i.selectedClass,s[i.selectedClass]),a.addClass(i.addClass)}}),l.ui.fancytree});
+
+/*! Extension 'jquery.fancytree.wide.min.js' */!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree"),module.exports=e(require("jquery"))):e(jQuery)}(function(o){"use strict";var p=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function f(e,t){var a=o("#"+(e="fancytree-style-"+e));if(t){a.length||(a=o("<style />").attr("id",e).addClass("fancytree-style").prop("type","text/css").appendTo("head"));try{a.html(t)}catch(e){a[0].styleSheet.cssText=t}return a}a.remove()}function u(e,t,a,n,l,i){for(var s="#"+e+" span.fancytree-level-",c=[],r=0;r<t;r++)c.push(s+(r+1)+" span.fancytree-title { padding-left: "+(r*a+n)+i+"; }");return c.push("#"+e+" div.ui-effects-wrapper ul li span.fancytree-title, #"+e+" li.fancytree-animating span.fancytree-title { padding-left: "+l+i+"; position: static; width: auto; }"),c.join("\n")}return o.ui.fancytree.registerExtension({name:"wide",version:"2.38.3",options:{iconWidth:null,iconSpacing:null,labelSpacing:null,levelOfs:null},treeCreate:function(e){this._superApply(arguments),this.$container.addClass("fancytree-ext-wide");var t=e.options.wide,a=o("<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />").appendTo(e.tree.$container),n=a.find(".fancytree-icon"),l=a.find("ul"),i=t.iconSpacing||n.css("margin-left"),s=t.iconWidth||n.css("width"),c=t.labelSpacing||"3px",r=t.levelOfs||l.css("padding-left");a.remove(),n=i.match(p)[2],i=parseFloat(i,10),t=c.match(p)[2],c=parseFloat(c,10),l=s.match(p)[2],s=parseFloat(s,10),a=r.match(p)[2],n===l&&a===l&&t===l||o.error("iconWidth, iconSpacing, and levelOfs must have the same css measure unit"),this._local.measureUnit=l,this._local.levelOfs=parseFloat(r),this._local.lineOfs=(1+(e.options.checkbox?1:0)+(!1===e.options.icon?0:1))*(s+i)+i,this._local.labelOfs=c,this._local.maxDepth=10,f(c=this.$container.uniqueId().attr("id"),u(c,this._local.maxDepth,this._local.levelOfs,this._local.lineOfs,this._local.labelOfs,this._local.measureUnit))},treeDestroy:function(e){return f(this.$container.attr("id"),null),this._superApply(arguments)},nodeRenderStatus:function(e){var t=e.node,a=t.getLevel(),n=this._super(e);return a>this._local.maxDepth&&(e=this.$container.attr("id"),this._local.maxDepth*=2,t.debug("Define global ext-wide css up to level "+this._local.maxDepth),f(e,u(e,this._local.maxDepth,this._local.levelOfs,this._local.lineOfs,this._local.labelSpacing,this._local.measureUnit))),o(t.span).addClass("fancytree-level-"+a),n}}),o.ui.fancytree});
+// Value returned by `require('jquery.fancytree')`
+return $.ui.fancytree;
+})); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree.min.js b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree.min.js
new file mode 100644
index 0000000..452a287
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/jquery.fancytree.min.js
@@ -0,0 +1 @@
+!function(e){"function"==typeof define&&define.amd?define(["jquery","./jquery.fancytree.ui-deps"],e):"object"==typeof module&&module.exports?(require("./jquery.fancytree.ui-deps"),module.exports=e(require("jquery"))):e(jQuery)}(function(k){"use strict";if(!k.ui||!k.ui.fancytree){for(var e,h=null,c=new RegExp(/\.|\//),t=/[&<>"'/]/g,n=/[<>"'/]/g,f="$recursive_request",p="$request_target_invalid",i={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;"},r={16:!0,17:!0,18:!0},u={8:"backspace",9:"tab",10:"return",13:"return",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",59:";",61:"=",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},g={16:"shift",17:"ctrl",18:"alt",91:"meta",93:"meta"},o={0:"",1:"left",2:"middle",3:"right"},v="active expanded focus folder lazy radiogroup selected unselectable unselectableIgnore".split(" "),y={},b="columns types".split(" "),m="checkbox expanded extraClasses folder icon iconTooltip key lazy partsel radiogroup refKey selected statusNodeType title tooltip type unselectable unselectableIgnore unselectableStatus".split(" "),s={},x={},a={active:!0,children:!0,data:!0,focus:!0},l=0;l<v.length;l++)y[v[l]]=!0;for(l=0;l<m.length;l++)e=m[l],s[e]=!0,e!==e.toLowerCase()&&(x[e.toLowerCase()]=e);var N=Array.isArray;return _(k.ui,"Fancytree requires jQuery UI (http://jqueryui.com)"),Date.now||(Date.now=function(){return(new Date).getTime()}),I.prototype={_findDirectChild:function(e){var t,n,i=this.children;if(i)if("string"==typeof e){for(t=0,n=i.length;t<n;t++)if(i[t].key===e)return i[t]}else{if("number"==typeof e)return this.children[e];if(e.parent===this)return e}return null},_setChildren:function(e){_(e&&(!this.children||0===this.children.length),"only init supported"),this.children=[];for(var t=0,n=e.length;t<n;t++)this.children.push(new I(this,e[t]));this.tree._callHook("treeStructureChanged",this.tree,"setChildren")},addChildren:function(e,t){var n,i,r,o,s=this.getFirstChild(),a=this.getLastChild(),l=[];for(k.isPlainObject(e)&&(e=[e]),this.children||(this.children=[]),n=0,i=e.length;n<i;n++)l.push(new I(this,e[n]));if(o=l[0],null==t?this.children=this.children.concat(l):(t=this._findDirectChild(t),_(0<=(r=k.inArray(t,this.children)),"insertBefore must be an existing child"),this.children.splice.apply(this.children,[r,0].concat(l))),s&&!t){for(n=0,i=l.length;n<i;n++)l[n].render();s!==this.getFirstChild()&&s.renderStatus(),a!==this.getLastChild()&&a.renderStatus()}else this.parent&&!this.parent.ul&&!this.tr||this.render();return 3===this.tree.options.selectMode&&this.fixSelection3FromEndNodes(),this.triggerModifyChild("add",1===l.length?l[0]:null),o},addClass:function(e){return this.toggleClass(e,!0)},addNode:function(e,t){switch(t=void 0===t||"over"===t?"child":t){case"after":return this.getParent().addChildren(e,this.getNextSibling());case"before":return this.getParent().addChildren(e,this);case"firstChild":var n=this.children?this.children[0]:null;return this.addChildren(e,n);case"child":case"over":return this.addChildren(e)}_(!1,"Invalid mode: "+t)},addPagingNode:function(e,t){var n,i;if(t=t||"child",!1!==e)return e=k.extend({title:this.tree.options.strings.moreData,statusNodeType:"paging",icon:!1},e),this.partload=!0,this.addNode(e,t);for(n=this.children.length-1;0<=n;n--)"paging"===(i=this.children[n]).statusNodeType&&this.removeChild(i);this.partload=!1},appendSibling:function(e){return this.addNode(e,"after")},applyCommand:function(e,t){return this.tree.applyCommand(e,this,t)},applyPatch:function(e){if(null===e)return this.remove(),T(this);var t,n,i={children:!0,expanded:!0,parent:!0};for(t in e)C(e,t)&&(n=e[t],i[t]||w(n)||(s[t]?this[t]=n:this.data[t]=n));return C(e,"children")&&(this.removeChildren(),e.children&&this._setChildren(e.children)),this.isVisible()&&(this.renderTitle(),this.renderStatus()),C(e,"expanded")?this.setExpanded(e.expanded):T(this)},collapseSiblings:function(){return this.tree._callHook("nodeCollapseSiblings",this)},copyTo:function(e,t,n){return e.addNode(this.toDict(!0,n),t)},countChildren:function(e){var t,n,i,r=this.children;if(!r)return 0;if(i=r.length,!1!==e)for(t=0,n=i;t<n;t++)i+=r[t].countChildren();return i},debug:function(e){4<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("log",arguments))},discard:function(){return this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."),this.resetLazy()},discardMarkup:function(e){this.tree._callHook(e?"nodeRemoveMarkup":"nodeRemoveChildMarkup",this)},error:function(e){1<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("error",arguments))},findAll:function(t){t=w(t)?t:R(t);var n=[];return this.visit(function(e){t(e)&&n.push(e)}),n},findFirst:function(t){t=w(t)?t:R(t);var n=null;return this.visit(function(e){if(t(e))return n=e,!1}),n},findRelatedNode:function(e,t){return this.tree.findRelatedNode(this,e,t)},_changeSelectStatusAttrs:function(e){var t=!1,n=this.tree.options,i=h.evalOption("unselectable",this,this,n,!1),n=h.evalOption("unselectableStatus",this,this,n,void 0);switch(e=i&&null!=n?n:e){case!1:t=this.selected||this.partsel,this.selected=!1,this.partsel=!1;break;case!0:t=!this.selected||!this.partsel,this.selected=!0,this.partsel=!0;break;case void 0:t=this.selected||!this.partsel,this.selected=!1,this.partsel=!0;break;default:_(!1,"invalid state: "+e)}return t&&this.renderStatus(),t},fixSelection3AfterClick:function(e){var t=this.isSelected();this.visit(function(e){if(e._changeSelectStatusAttrs(t),e.radiogroup)return"skip"}),this.fixSelection3FromEndNodes(e)},fixSelection3FromEndNodes:function(e){var u=this.tree.options;_(3===u.selectMode,"expected selectMode 3"),function e(t){var n,i,r,o,s,a,l,d,c=t.children;if(c&&c.length){for(l=!(a=!0),n=0,i=c.length;n<i;n++)o=e(r=c[n]),h.evalOption("unselectableIgnore",r,r,u,!1)||(!1!==o&&(l=!0),!0!==o&&(a=!1));s=!!a||!!l&&void 0}else s=null==(d=h.evalOption("unselectableStatus",t,t,u,void 0))?!!t.selected:!!d;return t.partsel&&!t.selected&&t.lazy&&null==t.children&&(s=void 0),t._changeSelectStatusAttrs(s),s}(this),this.visitParents(function(e){for(var t,n,i,r=e.children,o=!0,s=!1,a=0,l=r.length;a<l;a++)t=r[a],h.evalOption("unselectableIgnore",t,t,u,!1)||(((n=null==(i=h.evalOption("unselectableStatus",t,t,u,void 0))?!!t.selected:!!i)||t.partsel)&&(s=!0),n||(o=!1));e._changeSelectStatusAttrs(n=!!o||!!s&&void 0)})},fromDict:function(e){for(var t in e)s[t]?this[t]=e[t]:"data"===t?k.extend(this.data,e.data):w(e[t])||a[t]||(this.data[t]=e[t]);e.children&&(this.removeChildren(),this.addChildren(e.children)),this.renderTitle()},getChildren:function(){if(void 0!==this.hasChildren())return this.children},getFirstChild:function(){return this.children?this.children[0]:null},getIndex:function(){return k.inArray(this,this.parent.children)},getIndexHier:function(e,n){e=e||".";var i,r=[];return k.each(this.getParentList(!1,!0),function(e,t){i=""+(t.getIndex()+1),n&&(i=("0000000"+i).substr(-n)),r.push(i)}),r.join(e)},getKeyPath:function(e){var t=this.tree.options.keyPathSeparator;return t+this.getPath(!e,"key",t)},getLastChild:function(){return this.children?this.children[this.children.length-1]:null},getLevel:function(){for(var e=0,t=this.parent;t;)e++,t=t.parent;return e},getNextSibling:function(){if(this.parent)for(var e=this.parent.children,t=0,n=e.length-1;t<n;t++)if(e[t]===this)return e[t+1];return null},getParent:function(){return this.parent},getParentList:function(e,t){for(var n=[],i=t?this:this.parent;i;)(e||i.parent)&&n.unshift(i),i=i.parent;return n},getPath:function(e,t,n){n=n||"/";var i,r=[],o=w(t=t||"title");return this.visitParents(function(e){e.parent&&(i=o?t(e):e[t],r.unshift(i))},e=!1!==e),r.join(n)},getPrevSibling:function(){if(this.parent)for(var e=this.parent.children,t=1,n=e.length;t<n;t++)if(e[t]===this)return e[t-1];return null},getSelectedNodes:function(t){var n=[];return this.visit(function(e){if(e.selected&&(n.push(e),!0===t))return"skip"}),n},hasChildren:function(){return this.lazy?null==this.children?void 0:0!==this.children.length&&(1!==this.children.length||!this.children[0].isStatusNode()||void 0):!(!this.children||!this.children.length)},hasClass:function(e){return 0<=(" "+(this.extraClasses||"")+" ").indexOf(" "+e+" ")},hasFocus:function(){return this.tree.hasFocus()&&this.tree.focusNode===this},info:function(e){3<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("info",arguments))},isActive:function(){return this.tree.activeNode===this},isBelowOf:function(e){return this.getIndexHier(".",5)>e.getIndexHier(".",5)},isChildOf:function(e){return this.parent&&this.parent===e},isDescendantOf:function(e){if(!e||e.tree!==this.tree)return!1;for(var t=this.parent;t;){if(t===e)return!0;t===t.parent&&k.error("Recursive parent link: "+t),t=t.parent}return!1},isExpanded:function(){return!!this.expanded},isFirstSibling:function(){var e=this.parent;return!e||e.children[0]===this},isFolder:function(){return!!this.folder},isLastSibling:function(){var e=this.parent;return!e||e.children[e.children.length-1]===this},isLazy:function(){return!!this.lazy},isLoaded:function(){return!this.lazy||void 0!==this.hasChildren()},isLoading:function(){return!!this._isLoading},isRoot:function(){return this.isRootNode()},isPartsel:function(){return!this.selected&&!!this.partsel},isPartload:function(){return!!this.partload},isRootNode:function(){return this.tree.rootNode===this},isSelected:function(){return!!this.selected},isStatusNode:function(){return!!this.statusNodeType},isPagingNode:function(){return"paging"===this.statusNodeType},isTopLevel:function(){return this.tree.rootNode===this.parent},isUndefined:function(){return void 0===this.hasChildren()},isVisible:function(){var e,t,n=this.tree.enableFilter,i=this.getParentList(!1,!1);if(n&&!this.match&&!this.subMatchCount)return!1;for(e=0,t=i.length;e<t;e++)if(!i[e].expanded)return!1;return!0},lazyLoad:function(e){k.error("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead.")},load:function(e){var t=this,n=this.isExpanded();return _(this.isLazy(),"load() requires a lazy node"),e||this.isUndefined()?(this.isLoaded()&&this.resetLazy(),!1===(e=this.tree._triggerNodeEvent("lazyLoad",this))?T(this):(_("boolean"!=typeof e,"lazyLoad event must return source in data.result"),e=this.tree._callHook("nodeLoadChildren",this,e),n?(this.expanded=!0,e.always(function(){t.render()})):e.always(function(){t.renderStatus()}),e)):T(this)},makeVisible:function(e){for(var t=this,n=[],i=new k.Deferred,r=this.getParentList(!1,!1),o=r.length,s=!(e&&!0===e.noAnimation),a=!(e&&!1===e.scrollIntoView),l=o-1;0<=l;l--)n.push(r[l].setExpanded(!0,e));return k.when.apply(k,n).done(function(){a?t.scrollIntoView(s).done(function(){i.resolve()}):i.resolve()}),i.promise()},moveTo:function(t,e,n){void 0===e||"over"===e?e="child":"firstChild"===e&&(t.children&&t.children.length?(e="before",t=t.children[0]):e="child");var i,r=this.tree,o=this.parent,s="child"===e?t:t.parent;if(this!==t){if(this.parent?s.isDescendantOf(this)&&k.error("Cannot move a node to its own descendant"):k.error("Cannot move system root"),s!==o&&o.triggerModifyChild("remove",this),1===this.parent.children.length){if(this.parent===s)return;this.parent.children=this.parent.lazy?[]:null,this.parent.expanded=!1}else _(0<=(i=k.inArray(this,this.parent.children)),"invalid source parent"),this.parent.children.splice(i,1);if((this.parent=s).hasChildren())switch(e){case"child":s.children.push(this);break;case"before":_(0<=(i=k.inArray(t,s.children)),"invalid target parent"),s.children.splice(i,0,this);break;case"after":_(0<=(i=k.inArray(t,s.children)),"invalid target parent"),s.children.splice(i+1,0,this);break;default:k.error("Invalid mode "+e)}else s.children=[this];n&&t.visit(n,!0),s===o?s.triggerModifyChild("move",this):s.triggerModifyChild("add",this),r!==t.tree&&(this.warn("Cross-tree moveTo is experimental!"),this.visit(function(e){e.tree=t.tree},!0)),r._callHook("treeStructureChanged",r,"moveTo"),o.isDescendantOf(s)||o.render(),s.isDescendantOf(o)||s===o||s.render()}},navigate:function(e,t){var n=k.ui.keyCode;switch(e){case"left":case n.LEFT:if(this.expanded)return this.setExpanded(!1);break;case"right":case n.RIGHT:if(!this.expanded&&(this.children||this.lazy))return this.setExpanded()}if(n=this.findRelatedNode(e)){try{n.makeVisible({scrollIntoView:!1})}catch(e){}return!1===t?(n.setFocus(),T()):n.setActive()}return this.warn("Could not find related node '"+e+"'."),T()},remove:function(){return this.parent.removeChild(this)},removeChild:function(e){return this.tree._callHook("nodeRemoveChild",this,e)},removeChildren:function(){return this.tree._callHook("nodeRemoveChildren",this)},removeClass:function(e){return this.toggleClass(e,!1)},render:function(e,t){return this.tree._callHook("nodeRender",this,e,t)},renderTitle:function(){return this.tree._callHook("nodeRenderTitle",this)},renderStatus:function(){return this.tree._callHook("nodeRenderStatus",this)},replaceWith:function(e){var n=this.parent,i=k.inArray(this,n.children),r=this;return _(this.isPagingNode(),"replaceWith() currently requires a paging status node"),(e=this.tree._callHook("nodeLoadChildren",this,e)).done(function(e){var t=r.children;for(l=0;l<t.length;l++)t[l].parent=n;n.children.splice.apply(n.children,[i+1,0].concat(t)),r.children=null,r.remove(),n.render()}).fail(function(){r.setExpanded()}),e},resetLazy:function(){this.removeChildren(),this.expanded=!1,this.lazy=!0,this.children=void 0,this.renderStatus()},scheduleAction:function(e,t){this.tree.timer&&(clearTimeout(this.tree.timer),this.tree.debug("clearTimeout(%o)",this.tree.timer)),this.tree.timer=null;var n=this;switch(e){case"cancel":break;case"expand":this.tree.timer=setTimeout(function(){n.tree.debug("setTimeout: trigger expand"),n.setExpanded(!0)},t);break;case"activate":this.tree.timer=setTimeout(function(){n.tree.debug("setTimeout: trigger activate"),n.setActive(!0)},t);break;default:k.error("Invalid mode "+e)}},scrollIntoView:function(e,t){if(void 0!==t&&((p=t).tree&&void 0!==p.statusNodeType))throw Error("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead.");var n=k.extend({effects:!0===e?{duration:200,queue:!1}:e,scrollOfs:this.tree.options.scrollOfs,scrollParent:this.tree.options.scrollParent,topNode:null},t),i=n.scrollParent,r=this.tree.$container,o=r.css("overflow-y");i?i.jquery||(i=k(i)):i=!this.tree.tbody&&("scroll"===o||"auto"===o)?r:r.scrollParent(),i[0]!==document&&i[0]!==document.body||(this.debug("scrollIntoView(): normalizing scrollParent to 'window':",i[0]),i=k(window));var s,a,l=new k.Deferred,d=this,c=k(this.span).height(),u=n.scrollOfs.top||0,h=n.scrollOfs.bottom||0,f=i.height(),p=i.scrollTop(),e=i,t=i[0]===window,o=n.topNode||null,r=null;return this.isRootNode()||!this.isVisible()?(this.info("scrollIntoView(): node is invisible."),T()):(t?(a=k(this.span).offset().top,s=o&&o.span?k(o.span).offset().top:0,e=k("html,body")):(_(i[0]!==document&&i[0]!==document.body,"scrollParent should be a simple element or `window`, not document or body."),t=i.offset().top,a=k(this.span).offset().top-t+p,s=o?k(o.span).offset().top-t+p:0,f-=Math.max(0,i.innerHeight()-i[0].clientHeight)),a<p+u?r=a-u:p+f-h<a+c&&(r=a+c-f+h,o&&(_(o.isRootNode()||o.isVisible(),"topNode must be visible"),s<r&&(r=s-u))),null===r?l.resolveWith(this):n.effects?(n.effects.complete=function(){l.resolveWith(d)},e.stop(!0).animate({scrollTop:r},n.effects)):(e[0].scrollTop=r,l.resolveWith(this)),l.promise())},setActive:function(e,t){return this.tree._callHook("nodeSetActive",this,e,t)},setExpanded:function(e,t){return this.tree._callHook("nodeSetExpanded",this,e,t)},setFocus:function(e){return this.tree._callHook("nodeSetFocus",this,e)},setSelected:function(e,t){return this.tree._callHook("nodeSetSelected",this,e,t)},setStatus:function(e,t,n){return this.tree._callHook("nodeSetStatus",this,e,t,n)},setTitle:function(e){this.title=e,this.renderTitle(),this.triggerModify("rename")},sortChildren:function(e,t){var n,i,r=this.children;if(r){if(r.sort(e=e||function(e,t){e=e.title.toLowerCase(),t=t.title.toLowerCase();return e===t?0:t<e?1:-1}),t)for(n=0,i=r.length;n<i;n++)r[n].children&&r[n].sortChildren(e,"$norender$");"$norender$"!==t&&this.render(),this.triggerModifyChild("sort")}},toDict:function(e,t){var n,i,r,o,s={},a=this;if(k.each(m,function(e,t){!a[t]&&!1!==a[t]||(s[t]=a[t])}),k.isEmptyObject(this.data)||(s.data=k.extend({},this.data),k.isEmptyObject(s.data)&&delete s.data),t){if(!1===(o=t(s,a)))return!1;"skip"===o&&(e=!1)}if(e&&N(this.children))for(s.children=[],n=0,i=this.children.length;n<i;n++)(r=this.children[n]).isStatusNode()||!1!==(o=r.toDict(!0,t))&&s.children.push(o);return s},toggleClass:function(e,t){var n,i,r=e.match(/\S+/g)||[],o=0,s=!1,a=this[this.tree.statusClassPropName],l=" "+(this.extraClasses||"")+" ";for(a&&k(a).toggleClass(e,t);n=r[o++];)if(i=0<=l.indexOf(" "+n+" "),t=void 0===t?!i:!!t)i||(l+=n+" ",s=!0);else for(;-1<l.indexOf(" "+n+" ");)l=l.replace(" "+n+" "," ");return this.extraClasses=S(l),s},toggleExpanded:function(){return this.tree._callHook("nodeToggleExpanded",this)},toggleSelected:function(){return this.tree._callHook("nodeToggleSelected",this)},toString:function(){return"FancytreeNode@"+this.key+"[title='"+this.title+"']"},triggerModifyChild:function(e,t,n){var i=this.tree.options.modifyChild;i&&(t&&t.parent!==this&&k.error("childNode "+t+" is not a child of "+this),t={node:this,tree:this.tree,operation:e,childNode:t||null},n&&k.extend(t,n),i({type:"modifyChild"},t))},triggerModify:function(e,t){this.parent.triggerModifyChild(e,this,t)},visit:function(e,t){var n,i,r=!0,o=this.children;if(!0===t&&(!1===(r=e(this))||"skip"===r))return r;if(o)for(n=0,i=o.length;n<i&&!1!==(r=o[n].visit(e,!0));n++);return r},visitAndLoad:function(n,e,t){var i,r,o,s=this;return!n||!0!==e||!1!==(r=n(s))&&"skip"!==r?s.children||s.lazy?(i=new k.Deferred,o=[],s.load().done(function(){for(var e=0,t=s.children.length;e<t;e++){if(!1===(r=s.children[e].visitAndLoad(n,!0,!0))){i.reject();break}"skip"!==r&&o.push(r)}k.when.apply(this,o).then(function(){i.resolve()})}),i.promise()):T():t?r:T()},visitParents:function(e,t){if(t&&!1===e(this))return!1;for(var n=this.parent;n;){if(!1===e(n))return!1;n=n.parent}return!0},visitSiblings:function(e,t){for(var n,i=this.parent.children,r=0,o=i.length;r<o;r++)if(n=i[r],(t||n!==this)&&!1===e(n))return!1;return!0},warn:function(e){2<=this.tree.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("warn",arguments))}},F.prototype={_makeHookContext:function(e,t,n){var i,r;return void 0!==e.node?(t&&e.originalEvent!==t&&k.error("invalid args"),i=e):e.tree?i={node:e,tree:r=e.tree,widget:r.widget,options:r.widget.options,originalEvent:t,typeInfo:r.types[e.type]||{}}:e.widget?i={node:null,tree:e,widget:e.widget,options:e.widget.options,originalEvent:t}:k.error("invalid args"),n&&k.extend(i,n),i},_callHook:function(e,t,n){var i=this._makeHookContext(t),r=this[e],t=Array.prototype.slice.call(arguments,2);return w(r)||k.error("_callHook('"+e+"') is not a function"),t.unshift(i),r.apply(this,t)},_setExpiringValue:function(e,t,n){this._tempCache[e]={value:t,expire:Date.now()+(+n||50)}},_getExpiringValue:function(e){var t=this._tempCache[e];return t&&t.expire>Date.now()?t.value:(delete this._tempCache[e],null)},_usesExtension:function(e){return 0<=k.inArray(e,this.options.extensions)},_requireExtension:function(e,t,n,i){null!=n&&(n=!!n);var r=this._local.name,o=this.options.extensions,s=k.inArray(e,o)<k.inArray(r,o),o=t&&null==this.ext[e],s=!o&&null!=n&&n!==s;return _(r&&r!==e,"invalid or same name '"+r+"' (require yourself?)"),!o&&!s||(i||(o||t?(i="'"+r+"' extension requires '"+e+"'",s&&(i+=" to be registered "+(n?"before":"after")+" itself")):i="If used together, `"+e+"` must be registered "+(n?"before":"after")+" `"+r+"`"),k.error(i),!1)},activateKey:function(e,t){e=this.getNodeByKey(e);return e?e.setActive(!0,t):this.activeNode&&this.activeNode.setActive(!1,t),e},addPagingNode:function(e,t){return this.rootNode.addPagingNode(e,t)},applyCommand:function(e,t,n){var i;switch(t=t||this.getActiveNode(),e){case"moveUp":(i=t.getPrevSibling())&&(t.moveTo(i,"before"),t.setActive());break;case"moveDown":(i=t.getNextSibling())&&(t.moveTo(i,"after"),t.setActive());break;case"indent":(i=t.getPrevSibling())&&(t.moveTo(i,"child"),i.setExpanded(),t.setActive());break;case"outdent":t.isTopLevel()||(t.moveTo(t.getParent(),"after"),t.setActive());break;case"remove":i=t.getPrevSibling()||t.getParent(),t.remove(),i&&i.setActive();break;case"addChild":t.editCreateNode("child","");break;case"addSibling":t.editCreateNode("after","");break;case"rename":t.editStart();break;case"down":case"first":case"last":case"left":case"parent":case"right":case"up":return t.navigate(e);default:k.error("Unhandled command: '"+e+"'")}},applyPatch:function(e){for(var t,n,i,r,o=e.length,s=[],a=0;a<o;a++)_(2===(t=e[a]).length,"patchList must be an array of length-2-arrays"),n=t[0],i=t[1],(r=null===n?this.rootNode:this.getNodeByKey(n))?(t=new k.Deferred,s.push(t),r.applyPatch(i).always(A(t,r))):this.warn("could not find node with key '"+n+"'");return k.when.apply(k,s).promise()},clear:function(e){this._callHook("treeClear",this)},count:function(){return this.rootNode.countChildren()},debug:function(e){4<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("log",arguments))},destroy:function(){this.widget.destroy()},enable:function(e){!1===e?this.widget.disable():this.widget.enable()},enableUpdate:function(e){return!!this._enableUpdate==!!(e=!1!==e)?e:((this._enableUpdate=e)?(this.debug("enableUpdate(true): redraw "),this._callHook("treeStructureChanged",this,"enableUpdate"),this.render()):this.debug("enableUpdate(false)..."),!e)},error:function(e){1<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("error",arguments))},expandAll:function(t,n){var e=this.enableUpdate(!1);t=!1!==t,this.visit(function(e){!1!==e.hasChildren()&&e.isExpanded()!==t&&e.setExpanded(t,n)}),this.enableUpdate(e)},findAll:function(e){return this.rootNode.findAll(e)},findFirst:function(e){return this.rootNode.findFirst(e)},findNextNode:function(t,n){var i,r=null,e=this.getFirstChild();function o(e){if((r=t(e)?e:r)||e===n)return!1}return t="string"==typeof t?(i=new RegExp("^"+t,"i"),function(e){return i.test(e.title)}):t,this.visitRows(o,{start:n=n||e,includeSelf:!1}),r||n===e||this.visitRows(o,{start:e,includeSelf:!0}),r},findRelatedNode:function(e,t,n){var i=null,r=k.ui.keyCode;switch(t){case"parent":case r.BACKSPACE:e.parent&&e.parent.parent&&(i=e.parent);break;case"first":case r.HOME:this.visit(function(e){if(e.isVisible())return i=e,!1});break;case"last":case r.END:this.visit(function(e){e.isVisible()&&(i=e)});break;case"left":case r.LEFT:e.expanded?e.setExpanded(!1):e.parent&&e.parent.parent&&(i=e.parent);break;case"right":case r.RIGHT:e.expanded||!e.children&&!e.lazy?e.children&&e.children.length&&(i=e.children[0]):(e.setExpanded(),i=e);break;case"up":case r.UP:this.visitRows(function(e){return i=e,!1},{start:e,reverse:!0,includeSelf:!1});break;case"down":case r.DOWN:this.visitRows(function(e){return i=e,!1},{start:e,includeSelf:!1});break;default:this.tree.warn("Unknown relation '"+t+"'.")}return i},generateFormElements:function(e,t,n){n=n||{};var i="string"==typeof e?e:"ft_"+this._id+"[]",r="string"==typeof t?t:"ft_"+this._id+"_active",o="fancytree_result_"+this._id,s=k("#"+o),a=3===this.options.selectMode&&!1!==n.stopOnParents;function l(e){s.append(k("<input>",{type:"checkbox",name:i,value:e.key,checked:!0}))}s.length?s.empty():s=k("<div>",{id:o}).hide().insertAfter(this.$container),!1!==t&&this.activeNode&&s.append(k("<input>",{type:"radio",name:r,value:this.activeNode.key,checked:!0})),n.filter?this.visit(function(e){var t=n.filter(e);if("skip"===t)return t;!1!==t&&l(e)}):!1!==e&&(a=this.getSelectedNodes(a),k.each(a,function(e,t){l(t)}))},getActiveNode:function(){return this.activeNode},getFirstChild:function(){return this.rootNode.getFirstChild()},getFocusNode:function(){return this.focusNode},getOption:function(e){return this.widget.option(e)},getNodeByKey:function(t,e){var n,i;return!e&&(n=document.getElementById(this.options.idPrefix+t))?n.ftnode||null:(e=e||this.rootNode,t=""+t,e.visit(function(e){if(e.key===t)return i=e,!1},!(i=null)),i)},getRootNode:function(){return this.rootNode},getSelectedNodes:function(e){return this.rootNode.getSelectedNodes(e)},hasFocus:function(){return!!this._hasFocus},info:function(e){3<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("info",arguments))},isLoading:function(){var t=!1;return this.rootNode.visit(function(e){if(e._isLoading||e._requestId)return!(t=!0)},!0),t},loadKeyPath:function(e,t){var i,n,r,o=this,s=new k.Deferred,a=this.getRootNode(),l=this.options.keyPathSeparator,d=[],c=k.extend({},t);for("function"==typeof t?i=t:t&&t.callback&&(i=t.callback),c.callback=function(e,t,n){i&&i.call(e,t,n),s.notifyWith(e,[{node:t,status:n}])},null==c.matchKey&&(c.matchKey=function(e,t){return e.key===t}),N(e)||(e=[e]),n=0;n<e.length;n++)(r=e[n]).charAt(0)===l&&(r=r.substr(1)),d.push(r.split(l));return setTimeout(function(){o._loadKeyPathImpl(s,c,a,d).done(function(){s.resolve()})},0),s.promise()},_loadKeyPathImpl:function(e,o,t,n){var i,r,s,a,l,d,c,u,h,f,p=this;for(c={},r=0;r<n.length;r++)for(h=n[r],u=t;h.length;){if(s=h.shift(),!(a=function(e,t){var n,i,r=e.children;if(r)for(n=0,i=r.length;n<i;n++)if(o.matchKey(r[n],t))return r[n];return null}(u,s))){this.warn("loadKeyPath: key not found: "+s+" (parent: "+u+")"),o.callback(this,s,"error");break}if(0===h.length){o.callback(this,a,"ok");break}if(a.lazy&&void 0===a.hasChildren()){o.callback(this,a,"loaded"),c[s=a.key]?c[s].pathSegList.push(h):c[s]={parent:a,pathSegList:[h]};break}o.callback(this,a,"loaded"),u=a}for(l in i=[],c)C(c,l)&&(d=c[l],f=new k.Deferred,i.push(f),function(t,n,e){o.callback(p,n,"loading"),n.load().done(function(){p._loadKeyPathImpl.call(p,t,o,n,e).always(A(t,p))}).fail(function(e){p.warn("loadKeyPath: error loading lazy "+n),o.callback(p,a,"error"),t.rejectWith(p)})}(f,d.parent,d.pathSegList));return k.when.apply(k,i).promise()},reactivate:function(e){var t,n=this.activeNode;return n?(this.activeNode=null,t=n.setActive(!0,{noFocus:!0}),e&&n.setFocus(),t):T()},reload:function(e){return this._callHook("treeClear",this),this._callHook("treeLoad",this,e)},render:function(e,t){return this.rootNode.render(e,t)},selectAll:function(t){this.visit(function(e){e.setSelected(t)})},setFocus:function(e){return this._callHook("treeSetFocus",this,e)},setOption:function(e,t){return this.widget.option(e,t)},debugTime:function(e){4<=this.options.debugLevel&&window.console.time(this+" - "+e)},debugTimeEnd:function(e){4<=this.options.debugLevel&&window.console.timeEnd(this+" - "+e)},toDict:function(e,t){t=this.rootNode.toDict(!0,t);return e?t:t.children},toString:function(){return"Fancytree@"+this._id},_triggerNodeEvent:function(e,t,n,i){i=this._makeHookContext(t,n,i),n=this.widget._trigger(e,n,i);return!1!==n&&void 0!==i.result?i.result:n},_triggerTreeEvent:function(e,t,n){n=this._makeHookContext(this,t,n),t=this.widget._trigger(e,t,n);return!1!==t&&void 0!==n.result?n.result:t},visit:function(e){return this.rootNode.visit(e,!1)},visitRows:function(t,e){if(!this.rootNode.hasChildren())return!1;if(e&&e.reverse)return delete e.reverse,this._visitRowsUp(t,e);for(var n,i,r,o=0,s=!1===(e=e||{}).includeSelf,a=!!e.includeHidden,l=!a&&this.enableFilter,d=e.start||this.rootNode.children[0],c=d.parent;c;){for(_(0<=(i=(r=c.children).indexOf(d)+o),"Could not find "+d+" in parent's children: "+c),n=i;n<r.length;n++)if(d=r[n],!l||d.match||d.subMatchCount){if(!s&&!1===t(d))return!1;if(s=!1,d.children&&d.children.length&&(a||d.expanded)&&!1===d.visit(function(e){return!l||e.match||e.subMatchCount?!1!==t(e)&&(a||!e.children||e.expanded?void 0:"skip"):"skip"},!1))return!1}c=(d=c).parent,o=1}return!0},_visitRowsUp:function(e,t){for(var n,i,r,o=!!t.includeHidden,s=t.start||this.rootNode.children[0];;){if((n=(r=s.parent).children)[0]===s){if(!(s=r).parent)break;n=r.children}else for(i=n.indexOf(s),s=n[i-1];(o||s.expanded)&&s.children&&s.children.length;)s=(n=(r=s).children)[n.length-1];if((o||s.isVisible())&&!1===e(s))return!1}},warn:function(e){2<=this.options.debugLevel&&(Array.prototype.unshift.call(arguments,this.toString()),d("warn",arguments))}},k.extend(F.prototype,{nodeClick:function(e){var t,n,i=e.targetType,r=e.node;if("expander"===i)r.isLoading()?r.debug("Got 2nd click while loading: ignored"):this._callHook("nodeToggleExpanded",e);else if("checkbox"===i)this._callHook("nodeToggleSelected",e),e.options.focusOnSelect&&this._callHook("nodeSetFocus",e,!0);else{if(t=!(n=!1),r.folder)switch(e.options.clickFolderMode){case 2:t=!(n=!0);break;case 3:n=t=!0}t&&(this.nodeSetFocus(e),this._callHook("nodeSetActive",e,!0)),n&&this._callHook("nodeToggleExpanded",e)}},nodeCollapseSiblings:function(e,t){var n,i,r,o=e.node;if(o.parent)for(i=0,r=(n=o.parent.children).length;i<r;i++)n[i]!==o&&n[i].expanded&&this._callHook("nodeSetExpanded",n[i],!1,t)},nodeDblclick:function(e){"title"===e.targetType&&4===e.options.clickFolderMode&&this._callHook("nodeToggleExpanded",e),"title"===e.targetType&&e.originalEvent.preventDefault()},nodeKeydown:function(e){var t=e.originalEvent,n=e.node,i=e.tree,r=e.options,o=t.which,s=t.key||String.fromCharCode(o),a=!!(t.altKey||t.ctrlKey||t.metaKey),l=!g[o]&&!u[o]&&!a,o=k(t.target),d=!0,c=!(t.ctrlKey||!r.autoActivate);if(n||(a=this.getActiveNode()||this.getFirstChild())&&(a.setFocus(),(n=e.node=this.focusNode).debug("Keydown force focus on active node")),r.quicksearch&&l&&!o.is(":input:enabled"))return 500<(o=Date.now())-i.lastQuicksearchTime&&(i.lastQuicksearchTerm=""),i.lastQuicksearchTime=o,i.lastQuicksearchTerm+=s,(s=i.findNextNode(i.lastQuicksearchTerm,i.getActiveNode()))&&s.setActive(),void t.preventDefault();switch(h.eventToString(t)){case"+":case"=":i.nodeSetExpanded(e,!0);break;case"-":i.nodeSetExpanded(e,!1);break;case"space":n.isPagingNode()?i._triggerNodeEvent("clickPaging",e,t):h.evalOption("checkbox",n,n,r,!1)?i.nodeToggleSelected(e):i.nodeSetActive(e,!0);break;case"return":i.nodeSetActive(e,!0);break;case"home":case"end":case"backspace":case"left":case"right":case"up":case"down":n.navigate(t.which,c);break;default:d=!1}d&&t.preventDefault()},nodeLoadChildren:function(o,s){var t,n,a,e=null,i=!0,l=o.tree,d=o.node,c=d.parent,r="nodeLoadChildren",u=Date.now();return w(s)&&_(!w(s=s.call(l,{type:"source"},o)),"source callback must not return another function"),w(s.then)?e=s:s.url?e=(t=k.extend({},o.options.ajax,s)).debugDelay?(n=t.debugDelay,delete t.debugDelay,N(n)&&(n=n[0]+Math.random()*(n[1]-n[0])),d.warn("nodeLoadChildren waiting debugDelay "+Math.round(n)+" ms ..."),k.Deferred(function(e){setTimeout(function(){k.ajax(t).done(function(){e.resolveWith(this,arguments)}).fail(function(){e.rejectWith(this,arguments)})},n)})):k.ajax(t):k.isPlainObject(s)||N(s)?i=!(e={then:function(e,t){e(s,null,null)}}):k.error("Invalid source type: "+s),d._requestId&&(d.warn("Recursive load request #"+u+" while #"+d._requestId+" is pending."),d._requestId=u),i&&(l.debugTime(r),l.nodeSetStatus(o,"loading")),a=new k.Deferred,e.then(function(e,t,n){var i,r;if("json"!==s.dataType&&"jsonp"!==s.dataType||"string"!=typeof e||k.error("Ajax request returned a string (did you get the JSON dataType wrong?)."),d._requestId&&d._requestId>u)a.rejectWith(this,[f]);else if(null!==d.parent||null===c){if(o.options.postProcess){try{(r=l._triggerNodeEvent("postProcess",o,o.originalEvent,{response:e,error:null,dataType:s.dataType})).error&&l.warn("postProcess returned error:",r)}catch(e){r={error:e,message:""+e,details:"postProcess failed"}}if(r.error)return i=k.isPlainObject(r.error)?r.error:{message:r.error},i=l._makeHookContext(d,null,i),void a.rejectWith(this,[i]);(N(r)||k.isPlainObject(r)&&N(r.children))&&(e=r)}else e&&C(e,"d")&&o.options.enableAspx&&(42===o.options.enableAspx&&l.warn("The default for enableAspx will change to `false` in the fututure. Pass `enableAspx: true` or implement postProcess to silence this warning."),e="string"==typeof e.d?k.parseJSON(e.d):e.d);a.resolveWith(this,[e])}else a.rejectWith(this,[p])},function(e,t,n){n=l._makeHookContext(d,null,{error:e,args:Array.prototype.slice.call(arguments),message:n,details:e.status+": "+n});a.rejectWith(this,[n])}),a.done(function(e){var t,n,i;l.nodeSetStatus(o,"ok"),k.isPlainObject(e)?(_(d.isRootNode(),"source may only be an object for root nodes (expecting an array of child objects otherwise)"),_(N(e.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),t=(n=e).children,delete n.children,k.each(b,function(e,t){void 0!==n[t]&&(l[t]=n[t],delete n[t])}),k.extend(l.data,n)):t=e,_(N(t),"expected array of children"),d._setChildren(t),l.options.nodata&&0===t.length&&(w(l.options.nodata)?i=l.options.nodata.call(l,{type:"nodata"},o):!0===l.options.nodata&&d.isRootNode()?i=l.options.strings.noData:"string"==typeof l.options.nodata&&d.isRootNode()&&(i=l.options.nodata),i&&d.setStatus("nodata",i)),l._triggerNodeEvent("loadChildren",d)}).fail(function(e){var t;e!==f?e!==p?(e.node&&e.error&&e.message?t=e:"[object Object]"===(t=l._makeHookContext(d,null,{error:e,args:Array.prototype.slice.call(arguments),message:e?e.message||e.toString():""})).message&&(t.message=""),d.warn("Load children failed ("+t.message+")",t),!1!==l._triggerNodeEvent("loadError",t,null)&&l.nodeSetStatus(o,"error",t.message,t.details)):d.warn("Lazy parent node was removed while loading: discarding response."):d.warn("Ignored response for obsolete load request #"+u+" (expected #"+d._requestId+")")}).always(function(){d._requestId=null,i&&l.debugTimeEnd(r)}),a.promise()},nodeLoadKeyPath:function(e,t){},nodeRemoveChild:function(e,t){var n=e.node,i=k.extend({},e,{node:t}),r=n.children;if(1===r.length)return _(t===r[0],"invalid single child"),this.nodeRemoveChildren(e);this.activeNode&&(t===this.activeNode||this.activeNode.isDescendantOf(t))&&this.activeNode.setActive(!1),this.focusNode&&(t===this.focusNode||this.focusNode.isDescendantOf(t))&&(this.focusNode=null),this.nodeRemoveMarkup(i),this.nodeRemoveChildren(i),_(0<=(i=k.inArray(t,r)),"invalid child"),n.triggerModifyChild("remove",t),t.visit(function(e){e.parent=null},!0),this._callHook("treeRegisterNode",this,!1,t),r.splice(i,1)},nodeRemoveChildMarkup:function(e){e=e.node;e.ul&&(e.isRootNode()?k(e.ul).empty():(k(e.ul).remove(),e.ul=null),e.visit(function(e){e.li=e.ul=null}))},nodeRemoveChildren:function(e){var t=e.tree,n=e.node;n.children&&(this.activeNode&&this.activeNode.isDescendantOf(n)&&this.activeNode.setActive(!1),this.focusNode&&this.focusNode.isDescendantOf(n)&&(this.focusNode=null),this.nodeRemoveChildMarkup(e),n.triggerModifyChild("remove",null),n.visit(function(e){e.parent=null,t._callHook("treeRegisterNode",t,!1,e)}),n.lazy?n.children=[]:n.children=null,n.isRootNode()||(n.expanded=!1),this.nodeRenderStatus(e))},nodeRemoveMarkup:function(e){var t=e.node;t.li&&(k(t.li).remove(),t.li=null),this.nodeRemoveChildMarkup(e)},nodeRender:function(e,t,n,i,r){var o,s,a,l,d,c,u,h=e.node,f=e.tree,p=e.options,g=p.aria,v=!1,y=h.parent,b=!y,m=h.children,x=null;if(!1!==f._enableUpdate&&(b||y.ul)){if(_(b||y.ul,"parent UL must exist"),b||(h.li&&(t||h.li.parentNode!==h.parent.ul)&&(h.li.parentNode===h.parent.ul?x=h.li.nextSibling:this.debug("Unlinking "+h+" (must be child of "+h.parent+")"),this.nodeRemoveMarkup(e)),h.li?this.nodeRenderStatus(e):(v=!0,h.li=document.createElement("li"),(h.li.ftnode=h).key&&p.generateIds&&(h.li.id=p.idPrefix+h.key),h.span=document.createElement("span"),h.span.className="fancytree-node",g&&!h.tr&&k(h.li).attr("role","treeitem"),h.li.appendChild(h.span),this.nodeRenderTitle(e),p.createNode&&p.createNode.call(f,{type:"createNode"},e)),p.renderNode&&p.renderNode.call(f,{type:"renderNode"},e)),m){if(b||h.expanded||!0===n){for(h.ul||(h.ul=document.createElement("ul"),(!0!==i||r)&&h.expanded||(h.ul.style.display="none"),g&&k(h.ul).attr("role","group"),h.li?h.li.appendChild(h.ul):h.tree.$div.append(h.ul)),l=0,d=m.length;l<d;l++)u=k.extend({},e,{node:m[l]}),this.nodeRender(u,t,n,!1,!0);for(o=h.ul.firstChild;o;)o=(a=o.ftnode)&&a.parent!==h?(h.debug("_fixParent: remove missing "+a,o),c=o.nextSibling,o.parentNode.removeChild(o),c):o.nextSibling;for(o=h.ul.firstChild,l=0,d=m.length-1;l<d;l++)(s=m[l])===(a=o.ftnode)?o=o.nextSibling:h.ul.insertBefore(s.li,a.li)}}else h.ul&&(this.warn("remove child markup for "+h),this.nodeRemoveChildMarkup(e));b||v&&y.ul.insertBefore(h.li,x)}},nodeRenderTitle:function(e,t){var n,i,r=e.node,o=e.tree,s=e.options,a=s.aria,l=r.getLevel(),d=[];void 0!==t&&(r.title=t),r.span&&!1!==o._enableUpdate&&(t=a&&!1!==r.hasChildren()?" role='button'":"",l<s.minExpandLevel?(r.lazy||(r.expanded=!0),1<l&&d.push("<span "+t+" class='fancytree-expander fancytree-expander-fixed'></span>")):d.push("<span "+t+" class='fancytree-expander'></span>"),(l=h.evalOption("checkbox",r,r,s,!1))&&!r.isStatusNode()&&(n="fancytree-checkbox",("radio"===l||r.parent&&r.parent.radiogroup)&&(n+=" fancytree-radio"),d.push("<span "+(t=a?" role='checkbox'":"")+" class='"+n+"'></span>")),void 0!==r.data.iconClass&&(r.icon?k.error("'iconClass' node option is deprecated since v2.14.0: use 'icon' only instead"):(r.warn("'iconClass' node option is deprecated since v2.14.0: use 'icon' instead"),r.icon=r.data.iconClass)),!1!==(n=h.evalOption("icon",r,r,s,!0))&&(t=a?" role='presentation'":"",i=(i=h.evalOption("iconTooltip",r,r,s,null))?" title='"+P(i)+"'":"","string"==typeof n?c.test(n)?(n="/"===n.charAt(0)?n:(s.imagePath||"")+n,d.push("<img src='"+n+"' class='fancytree-icon'"+i+" alt='' />")):d.push("<span "+t+" class='fancytree-custom-icon "+n+"'"+i+"></span>"):n.text?d.push("<span "+t+" class='fancytree-custom-icon "+(n.addClass||"")+"'"+i+">"+h.escapeHtml(n.text)+"</span>"):n.html?d.push("<span "+t+" class='fancytree-custom-icon "+(n.addClass||"")+"'"+i+">"+n.html+"</span>"):d.push("<span "+t+" class='fancytree-icon'"+i+"></span>")),t="",t=(t=s.renderTitle?s.renderTitle.call(o,{type:"renderTitle"},e)||"":t)||"<span class='fancytree-title'"+(i=(i=!0===(i=h.evalOption("tooltip",r,r,s,null))?r.title:i)?" title='"+P(i)+"'":"")+(s.titlesTabbable?" tabindex='0'":"")+">"+(s.escapeTitles?h.escapeHtml(r.title):r.title)+"</span>",d.push(t),r.span.innerHTML=d.join(""),this.nodeRenderStatus(e),s.enhanceTitle&&(e.$title=k(">span.fancytree-title",r.span),t=s.enhanceTitle.call(o,{type:"enhanceTitle"},e)||""))},nodeRenderStatus:function(e){var t,n=e.node,i=e.tree,r=e.options,o=n.hasChildren(),s=n.isLastSibling(),a=r.aria,l=r._classNames,d=[],e=n[i.statusClassPropName];e&&!1!==i._enableUpdate&&(a&&(t=k(n.tr||n.li)),d.push(l.node),i.activeNode===n&&d.push(l.active),i.focusNode===n&&d.push(l.focused),n.expanded&&d.push(l.expanded),a&&(!1===o?t.removeAttr("aria-expanded"):t.attr("aria-expanded",Boolean(n.expanded))),n.folder&&d.push(l.folder),!1!==o&&d.push(l.hasChildren),s&&d.push(l.lastsib),n.lazy&&null==n.children&&d.push(l.lazy),n.partload&&d.push(l.partload),n.partsel&&d.push(l.partsel),h.evalOption("unselectable",n,n,r,!1)&&d.push(l.unselectable),n._isLoading&&d.push(l.loading),n._error&&d.push(l.error),n.statusNodeType&&d.push(l.statusNodePrefix+n.statusNodeType),n.selected?(d.push(l.selected),a&&t.attr("aria-selected",!0)):a&&t.attr("aria-selected",!1),n.extraClasses&&d.push(n.extraClasses),!1===o?d.push(l.combinedExpanderPrefix+"n"+(s?"l":"")):d.push(l.combinedExpanderPrefix+(n.expanded?"e":"c")+(n.lazy&&null==n.children?"d":"")+(s?"l":"")),d.push(l.combinedIconPrefix+(n.expanded?"e":"c")+(n.folder?"f":"")),e.className=d.join(" "),n.li&&k(n.li).toggleClass(l.lastsib,s))},nodeSetActive:function(e,t,n){var i=e.node,r=e.tree,o=e.options,s=!0===(n=n||{}).noEvents,a=!0===n.noFocus,n=!1!==n.scrollIntoView;return i===r.activeNode===(t=!1!==t)?T(i):(n&&e.originalEvent&&k(e.originalEvent.target).is("a,:checkbox")&&(i.info("Not scrolling while clicking an embedded link."),n=!1),t&&!s&&!1===this._triggerNodeEvent("beforeActivate",i,e.originalEvent)?L(i,["rejected"]):(t?(r.activeNode&&(_(r.activeNode!==i,"node was active (inconsistency)"),t=k.extend({},e,{node:r.activeNode}),r.nodeSetActive(t,!1),_(null===r.activeNode,"deactivate was out of sync?")),o.activeVisible&&i.makeVisible({scrollIntoView:n}),r.activeNode=i,r.nodeRenderStatus(e),a||r.nodeSetFocus(e),s||r._triggerNodeEvent("activate",i,e.originalEvent)):(_(r.activeNode===i,"node was not active (inconsistency)"),r.activeNode=null,this.nodeRenderStatus(e),s||e.tree._triggerNodeEvent("deactivate",i,e.originalEvent)),T(i)))},nodeSetExpanded:function(i,r,e){var t,n,o,s,a,l,d=i.node,c=i.tree,u=i.options,h=!0===(e=e||{}).noAnimation,f=!0===e.noEvents;if(r=!1!==r,k(d.li).hasClass(u._classNames.animating))return d.warn("setExpanded("+r+") while animating: ignored."),L(d,["recursion"]);if(d.expanded&&r||!d.expanded&&!r)return T(d);if(r&&!d.lazy&&!d.hasChildren())return T(d);if(!r&&d.getLevel()<u.minExpandLevel)return L(d,["locked"]);if(!f&&!1===this._triggerNodeEvent("beforeExpand",d,i.originalEvent))return L(d,["rejected"]);if(h||d.isVisible()||(h=e.noAnimation=!0),n=new k.Deferred,r&&!d.expanded&&u.autoCollapse){a=d.getParentList(!1,!0),l=u.autoCollapse;try{for(u.autoCollapse=!1,o=0,s=a.length;o<s;o++)this._callHook("nodeCollapseSiblings",a[o],e)}finally{u.autoCollapse=l}}return n.done(function(){var e=d.getLastChild();r&&u.autoScroll&&!h&&e&&c._enableUpdate?e.scrollIntoView(!0,{topNode:d}).always(function(){f||i.tree._triggerNodeEvent(r?"expand":"collapse",i)}):f||i.tree._triggerNodeEvent(r?"expand":"collapse",i)}),t=function(e){var t=u._classNames,n=u.toggleEffect;if(d.expanded=r,c._callHook("treeStructureChanged",i,r?"expand":"collapse"),c._callHook("nodeRender",i,!1,!1,!0),d.ul)if("none"!==d.ul.style.display==!!d.expanded)d.warn("nodeSetExpanded: UL.style.display already set");else{if(n&&!h)return k(d.li).addClass(t.animating),void(w(k(d.ul)[n.effect])?k(d.ul)[n.effect]({duration:n.duration,always:function(){k(this).removeClass(t.animating),k(d.li).removeClass(t.animating),e()}}):(k(d.ul).stop(!0,!0),k(d.ul).parent().find(".ui-effects-placeholder").remove(),k(d.ul).toggle(n.effect,n.options,n.duration,function(){k(this).removeClass(t.animating),k(d.li).removeClass(t.animating),e()})));d.ul.style.display=d.expanded||!parent?"":"none"}e()},r&&d.lazy&&void 0===d.hasChildren()?d.load().done(function(){n.notifyWith&&n.notifyWith(d,["loaded"]),t(function(){n.resolveWith(d)})}).fail(function(e){t(function(){n.rejectWith(d,["load failed ("+e+")"])})}):t(function(){n.resolveWith(d)}),n.promise()},nodeSetFocus:function(e,t){var n,i=e.tree,r=e.node,o=i.options,s=!!e.originalEvent&&k(e.originalEvent.target).is(":input");if(t=!1!==t,i.focusNode){if(i.focusNode===r&&t)return;n=k.extend({},e,{node:i.focusNode}),i.focusNode=null,this._triggerNodeEvent("blur",n),this._callHook("nodeRenderStatus",n)}t&&(this.hasFocus()||(r.debug("nodeSetFocus: forcing container focus"),this._callHook("treeSetFocus",e,!0,{calledByNode:!0})),r.makeVisible({scrollIntoView:!1}),i.focusNode=r,o.titlesTabbable&&(s||k(r.span).find(".fancytree-title").focus()),o.aria&&k(i.$container).attr("aria-activedescendant",k(r.tr||r.li).uniqueId().attr("id")),this._triggerNodeEvent("focus",e),document.activeElement===i.$container.get(0)||1<=k(document.activeElement,i.$container).length||k(i.$container).focus(),o.autoScroll&&r.scrollIntoView(),this._callHook("nodeRenderStatus",e))},nodeSetSelected:function(e,t,n){var i=e.node,r=e.tree,o=e.options,s=!0===(n=n||{}).noEvents,a=i.parent;if(t=!1!==t,!h.evalOption("unselectable",i,i,o,!1))return i._lastSelectIntent=t,!!i.selected!==t||3===o.selectMode&&i.partsel&&!t?s||!1!==this._triggerNodeEvent("beforeSelect",i,e.originalEvent)?(t&&1===o.selectMode?(r.lastSelectedNode&&r.lastSelectedNode.setSelected(!1),i.selected=t):3!==o.selectMode||!a||a.radiogroup||i.radiogroup?a&&a.radiogroup?i.visitSiblings(function(e){e._changeSelectStatusAttrs(t&&e===i)},!0):i.selected=t:(i.selected=t,i.fixSelection3AfterClick(n)),this.nodeRenderStatus(e),r.lastSelectedNode=t?i:null,void(s||r._triggerNodeEvent("select",e))):!!i.selected:t},nodeSetStatus:function(i,e,t,n){var r=i.node,o=i.tree;function s(e,t){var n=r.children?r.children[0]:null;return n&&n.isStatusNode()?(k.extend(n,e),n.statusNodeType=t,o._callHook("nodeRenderTitle",n)):(r._setChildren([e]),o._callHook("treeStructureChanged",i,"setStatusNode"),r.children[0].statusNodeType=t,o.render()),r.children[0]}switch(e){case"ok":!function(){var e=r.children?r.children[0]:null;if(e&&e.isStatusNode()){try{r.ul&&(r.ul.removeChild(e.li),e.li=null)}catch(e){}1===r.children.length?r.children=[]:r.children.shift(),o._callHook("treeStructureChanged",i,"clearStatusNode")}}(),r._isLoading=!1,r._error=null,r.renderStatus();break;case"loading":r.parent||s({title:o.options.strings.loading+(t?" ("+t+")":""),checkbox:!1,tooltip:n},e),r._isLoading=!0,r._error=null,r.renderStatus();break;case"error":s({title:o.options.strings.loadError+(t?" ("+t+")":""),checkbox:!1,tooltip:n},e),r._isLoading=!1,r._error={message:t,details:n},r.renderStatus();break;case"nodata":s({title:t||o.options.strings.noData,checkbox:!1,tooltip:n},e),r._isLoading=!1,r._error=null,r.renderStatus();break;default:k.error("invalid node status "+e)}},nodeToggleExpanded:function(e){return this.nodeSetExpanded(e,!e.node.expanded)},nodeToggleSelected:function(e){var t=e.node,n=!t.selected;return t.partsel&&!t.selected&&!0===t._lastSelectIntent&&(t.selected=!(n=!1)),t._lastSelectIntent=n,this.nodeSetSelected(e,n)},treeClear:function(e){var t=e.tree;t.activeNode=null,t.focusNode=null,t.$div.find(">ul.fancytree-container").empty(),t.rootNode.children=null,t._callHook("treeStructureChanged",e,"clear")},treeCreate:function(e){},treeDestroy:function(e){this.$div.find(">ul.fancytree-container").remove(),this.$source&&this.$source.removeClass("fancytree-helper-hidden")},treeInit:function(e){var n=e.tree,i=n.options;n.$container.attr("tabindex",i.tabindex),k.each(b,function(e,t){void 0!==i[t]&&(n.info("Move option "+t+" to tree"),n[t]=i[t],delete i[t])}),i.checkboxAutoHide&&n.$container.addClass("fancytree-checkbox-auto-hide"),i.rtl?n.$container.attr("DIR","RTL").addClass("fancytree-rtl"):n.$container.removeAttr("DIR").removeClass("fancytree-rtl"),i.aria&&(n.$container.attr("role","tree"),1!==i.selectMode&&n.$container.attr("aria-multiselectable",!0)),this.treeLoad(e)},treeLoad:function(e,t){var n,i,r,o=e.tree,s=e.widget.element,a=k.extend({},e,{node:this.rootNode});if(o.rootNode.children&&this.treeClear(e),t=t||this.options.source)"string"==typeof t&&k.error("Not implemented");else switch(i=s.data("type")||"html"){case"html":(r=s.find(">ul").not(".fancytree-container").first()).length?(r.addClass("ui-fancytree-source fancytree-helper-hidden"),t=k.ui.fancytree.parseHtml(r),this.data=k.extend(this.data,H(r))):(h.warn("No `source` option was passed and container does not contain `<ul>`: assuming `source: []`."),t=[]);break;case"json":t=k.parseJSON(s.text()),s.contents().filter(function(){return 3===this.nodeType}).remove(),k.isPlainObject(t)&&(_(N(t.children),"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"),t=(n=t).children,delete n.children,k.each(b,function(e,t){void 0!==n[t]&&(o[t]=n[t],delete n[t])}),k.extend(o.data,n));break;default:k.error("Invalid data-type: "+i)}return o._triggerTreeEvent("preInit",null),this.nodeLoadChildren(a,t).done(function(){o._callHook("treeStructureChanged",e,"loadChildren"),o.render(),3===e.options.selectMode&&o.rootNode.fixSelection3FromEndNodes(),o.activeNode&&o.options.activeVisible&&o.activeNode.makeVisible(),o._triggerTreeEvent("init",null,{status:!0})}).fail(function(){o.render(),o._triggerTreeEvent("init",null,{status:!1})})},treeRegisterNode:function(e,t,n){e.tree._callHook("treeStructureChanged",e,t?"addNode":"removeNode")},treeSetFocus:function(e,t,n){var i;(t=!1!==t)!==this.hasFocus()&&(!(this._hasFocus=t)&&this.focusNode?this.focusNode.setFocus(!1):!t||n&&n.calledByNode||k(this.$container).focus(),this.$container.toggleClass("fancytree-treefocus",t),this._triggerTreeEvent(t?"focusTree":"blurTree"),t&&!this.activeNode&&(i=this._lastMousedownNode||this.getFirstChild())&&i.setFocus())},treeSetOption:function(e,t,n){var i=e.tree,r=!0,o=!1,s=!1;switch(t){case"aria":case"checkbox":case"icon":case"minExpandLevel":case"tabindex":s=o=!0;break;case"checkboxAutoHide":i.$container.toggleClass("fancytree-checkbox-auto-hide",!!n);break;case"escapeTitles":case"tooltip":s=!0;break;case"rtl":!1===n?i.$container.removeAttr("DIR").removeClass("fancytree-rtl"):i.$container.attr("DIR","RTL").addClass("fancytree-rtl"),s=!0;break;case"source":r=!1,i._callHook("treeLoad",i,n),s=!0}i.debug("set option "+t+"="+n+" <"+typeof n+">"),r&&(this.widget._super||k.Widget.prototype._setOption).call(this.widget,t,n),o&&i._callHook("treeCreate",i),s&&i.render(!0,!1)},treeStructureChanged:function(e,t){}}),k.widget("ui.fancytree",{options:{activeVisible:!0,ajax:{type:"GET",cache:!1,dataType:"json"},aria:!0,autoActivate:!0,autoCollapse:!1,autoScroll:!1,checkbox:!1,clickFolderMode:4,copyFunctionsToData:!1,debugLevel:null,disabled:!1,enableAspx:42,escapeTitles:!1,extensions:[],focusOnSelect:!1,generateIds:!1,icon:!0,idPrefix:"ft_",keyboard:!0,keyPathSeparator:"/",minExpandLevel:1,nodata:!0,quicksearch:!1,rtl:!1,scrollOfs:{top:0,bottom:0},scrollParent:null,selectMode:2,strings:{loading:"Loading...",loadError:"Load error!",moreData:"More...",noData:"No data."},tabindex:"0",titlesTabbable:!1,toggleEffect:{effect:"slideToggle",duration:200},tooltip:!1,treeId:null,_classNames:{active:"fancytree-active",animating:"fancytree-animating",combinedExpanderPrefix:"fancytree-exp-",combinedIconPrefix:"fancytree-ico-",error:"fancytree-error",expanded:"fancytree-expanded",focused:"fancytree-focused",folder:"fancytree-folder",hasChildren:"fancytree-has-children",lastsib:"fancytree-lastsib",lazy:"fancytree-lazy",loading:"fancytree-loading",node:"fancytree-node",partload:"fancytree-partload",partsel:"fancytree-partsel",radio:"fancytree-radio",selected:"fancytree-selected",statusNodePrefix:"fancytree-statusnode-",unselectable:"fancytree-unselectable"},lazyLoad:null,postProcess:null},_deprecationWarning:function(e){var t=this.tree;t&&3<=t.options.debugLevel&&t.warn("$().fancytree('"+e+"') is deprecated (see https://wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Widget.html")},_create:function(){this.tree=new F(this),this.$source=this.source||"json"===this.element.data("type")?this.element:this.element.find(">ul").first();for(var e,t,n=this.options,i=n.extensions,r=(this.tree,0);r<i.length;r++)t=i[r],(e=k.ui.fancytree._extensions[t])||k.error("Could not apply extension '"+t+"' (it is not registered, did you forget to include it?)"),this.tree.options[t]=function e(t){var n,i,r,o,s=t||{},a=1,l=arguments.length;if("object"==typeof s||w(s)||(s={}),a===l)throw Error("need at least two args");for(;a<l;a++)if(null!=(n=arguments[a]))for(i in n)C(n,i)&&(o=s[i],s!==(r=n[i])&&(r&&k.isPlainObject(r)?(o=o&&k.isPlainObject(o)?o:{},s[i]=e(o,r)):void 0!==r&&(s[i]=r)));return s}({},e.options,this.tree.options[t]),_(void 0===this.tree.ext[t],"Extension name must not exist as Fancytree.ext attribute: '"+t+"'"),this.tree.ext[t]={},function(e,t,n){for(var i in t)"function"==typeof t[i]?"function"==typeof e[i]?e[i]=E(i,e,0,t,n):"_"===i.charAt(0)?e.ext[n][i]=E(i,e,0,t,n):k.error("Could not override tree."+i+". Use prefix '_' to create tree."+n+"._"+i):"options"!==i&&(e.ext[n][i]=t[i])}(this.tree,e,t),0;void 0!==n.icons&&(!0===n.icon?(this.tree.warn("'icons' tree option is deprecated since v2.14.0: use 'icon' instead"),n.icon=n.icons):k.error("'icons' tree option is deprecated since v2.14.0: use 'icon' only instead")),void 0!==n.iconClass&&(n.icon?k.error("'iconClass' tree option is deprecated since v2.14.0: use 'icon' only instead"):(this.tree.warn("'iconClass' tree option is deprecated since v2.14.0: use 'icon' instead"),n.icon=n.iconClass)),void 0!==n.tabbable&&(n.tabindex=n.tabbable?"0":"-1",this.tree.warn("'tabbable' tree option is deprecated since v2.17.0: use 'tabindex='"+n.tabindex+"' instead")),this.tree._callHook("treeCreate",this.tree)},_init:function(){this.tree._callHook("treeInit",this.tree),this._bind()},_setOption:function(e,t){return this.tree._callHook("treeSetOption",this.tree,e,t)},_destroy:function(){this._unbind(),this.tree._callHook("treeDestroy",this.tree)},_unbind:function(){var e=this.tree._ns;this.element.off(e),this.tree.$container.off(e),k(document).off(e)},_bind:function(){var s=this,a=this.options,o=this.tree,e=o._ns;this._unbind(),o.$container.on("focusin"+e+" focusout"+e,function(e){var t=h.getNode(e),n="focusin"===e.type;if(!n&&t&&k(e.target).is("a"))t.debug("Ignored focusout on embedded <a> element.");else{if(n){if(o._getExpiringValue("focusin"))return void o.debug("Ignored double focusin.");o._setExpiringValue("focusin",!0,50),t||(t=o._getExpiringValue("mouseDownNode"))&&o.debug("Reconstruct mouse target for focusin from recent event.")}t?o._callHook("nodeSetFocus",o._makeHookContext(t,e),n):o.tbody&&k(e.target).parents("table.fancytree-container > thead").length?o.debug("Ignore focus event outside table body.",e):o._callHook("treeSetFocus",o,n)}}).on("selectstart"+e,"span.fancytree-title",function(e){e.preventDefault()}).on("keydown"+e,function(e){if(a.disabled||!1===a.keyboard)return!0;var t,n=o.focusNode,i=o._makeHookContext(n||o,e),r=o.phase;try{return o.phase="userEvent","preventNav"===(t=n?o._triggerNodeEvent("keydown",n,e):o._triggerTreeEvent("keydown",e))?t=!0:!1!==t&&(t=o._callHook("nodeKeydown",i)),t}finally{o.phase=r}}).on("mousedown"+e,function(e){e=h.getEventTarget(e);o._lastMousedownNode=e?e.node:null,o._setExpiringValue("mouseDownNode",o._lastMousedownNode)}).on("click"+e+" dblclick"+e,function(e){if(a.disabled)return!0;var t,n=h.getEventTarget(e),i=n.node,r=s.tree,o=r.phase;if(!i)return!0;t=r._makeHookContext(i,e);try{switch(r.phase="userEvent",e.type){case"click":return t.targetType=n.type,i.isPagingNode()?!0===r._triggerNodeEvent("clickPaging",t,e):!1!==r._triggerNodeEvent("click",t,e)&&r._callHook("nodeClick",t);case"dblclick":return t.targetType=n.type,!1!==r._triggerNodeEvent("dblclick",t,e)&&r._callHook("nodeDblclick",t)}}finally{r.phase=o}})},getActiveNode:function(){return this._deprecationWarning("getActiveNode"),this.tree.activeNode},getNodeByKey:function(e){return this._deprecationWarning("getNodeByKey"),this.tree.getNodeByKey(e)},getRootNode:function(){return this._deprecationWarning("getRootNode"),this.tree.rootNode},getTree:function(){return this._deprecationWarning("getTree"),this.tree}}),h=k.ui.fancytree,k.extend(k.ui.fancytree,{version:"2.38.3",buildType: "production",debugLevel: 3,_nextId:1,_nextNodeKey:1,_extensions:{},_FancytreeClass:F,_FancytreeNodeClass:I,jquerySupports:{positionMyOfs:function(e){for(var t,n,i=k.map(S(e).split("."),function(e){return parseInt(e,10)}),r=k.map(Array.prototype.slice.call(arguments,1),function(e){return parseInt(e,10)}),o=0;o<r.length;o++)if((t=i[o]||0)!==(n=r[o]||0))return n<t;return!0}(k.ui.version,1,9)},assert:_,createTree:function(e,t){t=k(e).fancytree(t);return h.getTree(t)},debounce:function(t,n,i,r){var o;return 3===arguments.length&&"boolean"!=typeof i&&(r=i,i=!1),function(){var e=arguments;r=r||this,i&&!o&&n.apply(r,e),clearTimeout(o),o=setTimeout(function(){i||n.apply(r,e),o=null},t)}},debug:function(e){4<=k.ui.fancytree.debugLevel&&d("log",arguments)},error:function(e){1<=k.ui.fancytree.debugLevel&&d("error",arguments)},escapeHtml:function(e){return(""+e).replace(t,function(e){return i[e]})},fixPositionOptions:function(e){var t,n,i,r;return(e.offset||0<=(""+e.my+e.at).indexOf("%"))&&k.error("expected new position syntax (but '%' is not supported)"),k.ui.fancytree.jquerySupports.positionMyOfs||(t=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(e.my),n=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(e.at),i=(t[2]?+t[2]:0)+(n[2]?+n[2]:0),r=(t[4]?+t[4]:0)+(n[4]?+n[4]:0),e=k.extend({},e,{my:t[1]+" "+t[3],at:n[1]+" "+n[3]}),(i||r)&&(e.offset=i+" "+r)),e},getEventTarget:function(e){var t=e&&e.target?e.target.className:"",n={node:this.getNode(e.target),type:void 0};return/\bfancytree-title\b/.test(t)?n.type="title":/\bfancytree-expander\b/.test(t)?n.type=!1===n.node.hasChildren()?"prefix":"expander":/\bfancytree-checkbox\b/.test(t)?n.type="checkbox":/\bfancytree(-custom)?-icon\b/.test(t)?n.type="icon":/\bfancytree-node\b/.test(t)?n.type="title":e&&e.target&&((e=k(e.target)).is("ul[role=group]")?((n.node&&n.node.tree||h).debug("Ignoring click on outer UL."),n.node=null):e.closest(".fancytree-title").length?n.type="title":e.closest(".fancytree-checkbox").length?n.type="checkbox":e.closest(".fancytree-expander").length&&(n.type="expander")),n},getEventTargetType:function(e){return this.getEventTarget(e).type},getNode:function(e){if(e instanceof I)return e;for(e instanceof k?e=e[0]:void 0!==e.originalEvent&&(e=e.target);e;){if(e.ftnode)return e.ftnode;e=e.parentNode}return null},getTree:function(e){var t=e;return e instanceof F?e:("number"==typeof(e=void 0===e?0:e)?e=k(".fancytree-container").eq(e):"string"==typeof e?(e=k("#ft-id-"+t).eq(0)).length||(e=k(t).eq(0)):e instanceof Element||e instanceof HTMLDocument?e=k(e):e instanceof k?e=e.eq(0):void 0!==e.originalEvent&&(e=k(e.target)),(e=(e=e.closest(":ui-fancytree")).data("ui-fancytree")||e.data("fancytree"))?e.tree:null)},evalOption:function(e,t,n,i,r){var o,s=t.tree,i=i[e],n=n[e];return w(i)?(o={node:t,tree:s,widget:s.widget,options:s.widget.options,typeInfo:s.types[t.type]||{}},null==(o=i.call(s,{type:e},o))&&(o=n)):o=null==n?i:n,o=null==o?r:o},setSpanIcon:function(e,t,n){var i=k(e);"string"==typeof n?i.attr("class",t+" "+n):(n.text?i.text(""+n.text):n.html&&(e.innerHTML=n.html),i.attr("class",t+" "+(n.addClass||"")))},eventToString:function(e){var t=e.which,n=e.type,i=[];return e.altKey&&i.push("alt"),e.ctrlKey&&i.push("ctrl"),e.metaKey&&i.push("meta"),e.shiftKey&&i.push("shift"),"click"===n||"dblclick"===n?i.push(o[e.button]+n):"wheel"===n?i.push(n):r[t]||i.push(u[t]||String.fromCharCode(t).toLowerCase()),i.join("+")},info:function(e){3<=k.ui.fancytree.debugLevel&&d("info",arguments)},keyEventToString:function(e){return this.warn("keyEventToString() is deprecated: use eventToString()"),this.eventToString(e)},overrideMethod:function(e,t,n,i){var r,o=e[t]||k.noop;e[t]=function(){var e=i||this;try{return r=e._super,e._super=o,n.apply(e,arguments)}finally{e._super=r}}},parseHtml:function(s){var a,l,d,c,u,h,f,p,e=s.find(">li"),g=[];return e.each(function(){var e,t,n=k(this),i=n.find(">span",this).first(),r=i.length?null:n.find(">a").first(),o={tooltip:null,data:{}};for(i.length?o.title=i.html():r&&r.length?(o.title=r.html(),o.data.href=r.attr("href"),o.data.target=r.attr("target"),o.tooltip=r.attr("title")):(o.title=n.html(),0<=(u=o.title.search(/<ul/i))&&(o.title=o.title.substring(0,u))),o.title=S(o.title),c=0,h=v.length;c<h;c++)o[v[c]]=void 0;for(a=this.className.split(" "),d=[],c=0,h=a.length;c<h;c++)l=a[c],y[l]?o[l]=!0:d.push(l);if(o.extraClasses=d.join(" "),(f=n.attr("title"))&&(o.tooltip=f),(f=n.attr("id"))&&(o.key=f),n.attr("hideCheckbox")&&(o.checkbox=!1),(e=H(n))&&!k.isEmptyObject(e)){for(t in x)C(e,t)&&(e[x[t]]=e[t],delete e[t]);for(c=0,h=m.length;c<h;c++)f=m[c],null!=(p=e[f])&&(delete e[f],o[f]=p);k.extend(o.data,e)}(s=n.find(">ul").first()).length?o.children=k.ui.fancytree.parseHtml(s):o.children=o.lazy?void 0:null,g.push(o)}),g},registerExtension:function(e){_(null!=e.name,"extensions must have a `name` property."),_(null!=e.version,"extensions must have a `version` property."),k.ui.fancytree._extensions[e.name]=e},trim:S,unescapeHtml:function(e){var t=document.createElement("div");return t.innerHTML=e,0===t.childNodes.length?"":t.childNodes[0].nodeValue},warn:function(e){2<=k.ui.fancytree.debugLevel&&d("warn",arguments)}}),k.ui.fancytree}function _(e,t){e||(k.ui.fancytree.error(t="Fancytree assertion failed"+(t=t?": "+t:"")),k.error(t))}function C(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function w(e){return"function"==typeof e}function S(e){return null==e?"":e.trim()}function d(t,n){var i,r,t=window.console?window.console[t]:null;if(t)try{t.apply(window.console,n)}catch(e){for(r="",i=0;i<n.length;i++)r+=n[i];t(r)}}function E(e,i,t,n,r){var o,s,a;function l(){return o.apply(i,arguments)}function d(e){return o.apply(i,e)}return o=i[e],s=n[e],a=i.ext[r],function(){var e=i._local,t=i._super,n=i._superApply;try{return i._local=a,i._super=l,i._superApply=d,s.apply(i,arguments)}finally{i._local=e,i._super=t,i._superApply=n}}}function T(e,t){return(void 0===e?k.Deferred(function(){this.resolve()}):k.Deferred(function(){this.resolveWith(e,t)})).promise()}function L(e,t){return(void 0===e?k.Deferred(function(){this.reject()}):k.Deferred(function(){this.rejectWith(e,t)})).promise()}function A(e,t){return function(){e.resolveWith(t)}}function H(e){var t=k.extend({},e.data()),e=t.json;return delete t.fancytree,delete t.uiFancytree,e&&(delete t.json,t=k.extend(t,e)),t}function P(e){return(""+e).replace(n,function(e){return i[e]})}function R(t){return t=t.toLowerCase(),function(e){return 0<=e.title.toLowerCase().indexOf(t)}}function I(e,t){var n,i,r;for(this.parent=e,this.tree=e.tree,this.ul=null,this.li=null,this.statusNodeType=null,this._isLoading=!1,this._error=null,this.data={},n=0,i=m.length;n<i;n++)this[r=m[n]]=t[r];for(r in null==this.unselectableIgnore&&null==this.unselectableStatus||(this.unselectable=!0),t.hideCheckbox&&k.error("'hideCheckbox' node option was removed in v2.23.0: use 'checkbox: false'"),t.data&&k.extend(this.data,t.data),t)s[r]||!this.tree.options.copyFunctionsToData&&w(t[r])||a[r]||(this.data[r]=t[r]);null==this.key?this.tree.options.defaultKey?(this.key=""+this.tree.options.defaultKey(this),_(this.key,"defaultKey() must return a unique key")):this.key="_"+h._nextNodeKey++:this.key=""+this.key,t.active&&(_(null===this.tree.activeNode,"only one active node allowed"),this.tree.activeNode=this),t.selected&&(this.tree.lastSelectedNode=this),(e=t.children)?e.length?this._setChildren(e):this.children=this.lazy?[]:null:this.children=null,this.tree._callHook("treeRegisterNode",this.tree,!0,this)}function F(e){this.widget=e,this.$div=e.element,this.options=e.options,this.options&&(void 0!==this.options.lazyload&&k.error("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."),void 0!==this.options.loaderror&&k.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."),void 0!==this.options.fx&&k.error("The 'fx' option was replaced by 'toggleEffect' since 2014-11-30."),void 0!==this.options.removeNode&&k.error("The 'removeNode' event was replaced by 'modifyChild' since 2.20 (2016-09-10).")),this.ext={},this.types={},this.columns={},this.data=H(this.$div),this._id=""+(this.options.treeId||k.ui.fancytree._nextId++),this._ns=".fancytree-"+this._id,this.activeNode=null,this.focusNode=null,this._hasFocus=null,this._tempCache={},this._lastMousedownNode=null,this._enableUpdate=!0,this.lastSelectedNode=null,this.systemFocusElement=null,this.lastQuicksearchTerm="",this.lastQuicksearchTime=0,this.viewport=null,this.statusClassPropName="span",this.ariaPropName="li",this.nodeContainerAttrName="li",this.$div.find(">ul.fancytree-container").remove(),this.rootNode=new I({tree:this},{title:"root",key:"root_"+this._id,children:null,expanded:!0}),this.rootNode.parent=null,e=k("<ul>",{id:"ft-id-"+this._id,class:"ui-fancytree fancytree-container fancytree-plain"}).appendTo(this.$div),this.$container=e,this.rootNode.ul=e[0],null==this.options.debugLevel&&(this.options.debugLevel=h.debugLevel)}k.ui.fancytree.warn("Fancytree: ignored duplicate include")}); \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.ariagrid.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.ariagrid.js
new file mode 100644
index 0000000..37ff6d9
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.ariagrid.js
@@ -0,0 +1,714 @@
+/*!
+ * jquery.fancytree.ariagrid.js
+ *
+ * Support ARIA compliant markup and keyboard navigation for tree grids with
+ * embedded input controls.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @requires ext-table
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([
+ "jquery",
+ "./jquery.fancytree",
+ "./jquery.fancytree.table",
+ ], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree.table"); // core + table
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ // Allow these navigation keys even when input controls are focused
+
+ var FT = $.ui.fancytree,
+ clsFancytreeActiveCell = "fancytree-active-cell",
+ clsFancytreeCellMode = "fancytree-cell-mode",
+ clsFancytreeCellNavMode = "fancytree-cell-nav-mode",
+ VALID_MODES = ["allow", "force", "start", "off"],
+ // Define which keys are handled by embedded <input> control, and should
+ // *not* be passed to tree navigation handler in cell-edit mode:
+ INPUT_KEYS = {
+ text: ["left", "right", "home", "end", "backspace"],
+ number: ["up", "down", "left", "right", "home", "end", "backspace"],
+ checkbox: [],
+ link: [],
+ radiobutton: ["up", "down"],
+ "select-one": ["up", "down"],
+ "select-multiple": ["up", "down"],
+ },
+ NAV_KEYS = ["up", "down", "left", "right", "home", "end"];
+
+ /* Set aria-activedescendant on container to active cell's ID (generate one if required).*/
+ function setActiveDescendant(tree, $target) {
+ var id = $target ? $target.uniqueId().attr("id") : "";
+
+ tree.$container.attr("aria-activedescendant", id);
+ }
+
+ /* Calculate TD column index (considering colspans).*/
+ function getColIdx($tr, $td) {
+ var colspan,
+ td = $td.get(0),
+ idx = 0;
+
+ $tr.children().each(function () {
+ if (this === td) {
+ return false;
+ }
+ colspan = $(this).prop("colspan");
+ idx += colspan ? colspan : 1;
+ });
+ return idx;
+ }
+
+ /* Find TD at given column index (considering colspans).*/
+ function findTdAtColIdx($tr, colIdx) {
+ var colspan,
+ res = null,
+ idx = 0;
+
+ $tr.children().each(function () {
+ if (idx >= colIdx) {
+ res = $(this);
+ return false;
+ }
+ colspan = $(this).prop("colspan");
+ idx += colspan ? colspan : 1;
+ });
+ return res;
+ }
+
+ /* Find adjacent cell for a given direction. Skip empty cells and consider merged cells */
+ function findNeighbourTd(tree, $target, keyCode) {
+ var nextNode,
+ node,
+ navMap = { "ctrl+home": "first", "ctrl+end": "last" },
+ $td = $target.closest("td"),
+ $tr = $td.parent(),
+ treeOpts = tree.options,
+ colIdx = getColIdx($tr, $td),
+ $tdNext = null;
+
+ keyCode = navMap[keyCode] || keyCode;
+
+ switch (keyCode) {
+ case "left":
+ $tdNext = treeOpts.rtl ? $td.next() : $td.prev();
+ break;
+ case "right":
+ $tdNext = treeOpts.rtl ? $td.prev() : $td.next();
+ break;
+ case "up":
+ case "down":
+ case "ctrl+home":
+ case "ctrl+end":
+ node = $tr[0].ftnode;
+ nextNode = tree.findRelatedNode(node, keyCode);
+ if (nextNode) {
+ nextNode.makeVisible();
+ nextNode.setActive();
+ $tdNext = findTdAtColIdx($(nextNode.tr), colIdx);
+ }
+ break;
+ case "home":
+ $tdNext = treeOpts.rtl
+ ? $tr.children("td").last()
+ : $tr.children("td").first();
+ break;
+ case "end":
+ $tdNext = treeOpts.rtl
+ ? $tr.children("td").first()
+ : $tr.children("td").last();
+ break;
+ }
+ return $tdNext && $tdNext.length ? $tdNext : null;
+ }
+
+ /* Return a descriptive string of the current mode. */
+ function getGridNavMode(tree) {
+ if (tree.$activeTd) {
+ return tree.forceNavMode ? "cell-nav" : "cell-edit";
+ }
+ return "row";
+ }
+
+ /* .*/
+ function activateEmbeddedLink($td) {
+ // $td.find( "a" )[ 0 ].trigger("click"); // does not work (always)?
+ // $td.find( "a" ).trigger("click");
+ var event = document.createEvent("MouseEvent"),
+ a = $td.find("a")[0]; // document.getElementById('nameOfID');
+
+ event = new CustomEvent("click");
+ a.dispatchEvent(event);
+ }
+
+ /**
+ * [ext-ariagrid] Set active cell and activate cell-nav or cell-edit mode if needed.
+ * Pass $td=null to enter row-mode.
+ *
+ * See also FancytreeNode#setActive(flag, {cell: idx})
+ *
+ * @param {jQuery | Element | integer} [$td]
+ * @param {Event|null} [orgEvent=null]
+ * @alias Fancytree#activateCell
+ * @requires jquery.fancytree.ariagrid.js
+ * @since 2.23
+ */
+ $.ui.fancytree._FancytreeClass.prototype.activateCell = function (
+ $td,
+ orgEvent
+ ) {
+ var colIdx,
+ $input,
+ $tr,
+ res,
+ tree = this,
+ $prevTd = this.$activeTd || null,
+ newNode = $td ? FT.getNode($td) : null,
+ prevNode = $prevTd ? FT.getNode($prevTd) : null,
+ anyNode = newNode || prevNode,
+ $prevTr = $prevTd ? $prevTd.closest("tr") : null;
+
+ anyNode.debug(
+ "activateCell(" +
+ ($prevTd ? $prevTd.text() : "null") +
+ ") -> " +
+ ($td ? $td.text() : "OFF")
+ );
+
+ // Make available as event
+
+ if ($td) {
+ FT.assert($td.length, "Invalid active cell");
+ colIdx = getColIdx($(newNode.tr), $td);
+ res = this._triggerNodeEvent("activateCell", newNode, orgEvent, {
+ activeTd: tree.$activeTd,
+ colIdx: colIdx,
+ mode: null, // editMode ? "cell-edit" : "cell-nav"
+ });
+ if (res === false) {
+ return false;
+ }
+ this.$container.addClass(clsFancytreeCellMode);
+ this.$container.toggleClass(
+ clsFancytreeCellNavMode,
+ !!this.forceNavMode
+ );
+ $tr = $td.closest("tr");
+ if ($prevTd) {
+ // cell-mode => cell-mode
+ if ($prevTd.is($td)) {
+ return;
+ }
+ $prevTd
+ .removeAttr("tabindex")
+ .removeClass(clsFancytreeActiveCell);
+
+ if (!$prevTr.is($tr)) {
+ // We are moving to a different row: only the inputs in the
+ // active row should be tabbable
+ $prevTr.find(">td :input,a").attr("tabindex", "-1");
+ }
+ }
+ $tr.find(">td :input:enabled,a").attr("tabindex", "0");
+ newNode.setActive();
+ $td.addClass(clsFancytreeActiveCell);
+ this.$activeTd = $td;
+
+ $input = $td.find(":input:enabled,a");
+ this.debug("Focus input", $input);
+ if ($input.length) {
+ $input.focus();
+ setActiveDescendant(this, $input);
+ } else {
+ $td.attr("tabindex", "-1").focus();
+ setActiveDescendant(this, $td);
+ }
+ } else {
+ res = this._triggerNodeEvent("activateCell", prevNode, orgEvent, {
+ activeTd: null,
+ colIdx: null,
+ mode: "row",
+ });
+ if (res === false) {
+ return false;
+ }
+ // $td == null: switch back to row-mode
+ this.$container.removeClass(
+ clsFancytreeCellMode + " " + clsFancytreeCellNavMode
+ );
+ // console.log("activateCell: set row-mode for " + this.activeNode, $prevTd);
+ if ($prevTd) {
+ // cell-mode => row-mode
+ $prevTd
+ .removeAttr("tabindex")
+ .removeClass(clsFancytreeActiveCell);
+ // In row-mode, only embedded inputs of the active row are tabbable
+ $prevTr
+ .find("td")
+ .blur() // we need to blur first, because otherwise the focus frame is not reliably removed(?)
+ .removeAttr("tabindex");
+ $prevTr.find(">td :input,a").attr("tabindex", "-1");
+ this.$activeTd = null;
+ // The cell lost focus, but the tree still needs to capture keys:
+ this.activeNode.setFocus();
+ setActiveDescendant(this, $tr);
+ } else {
+ // row-mode => row-mode (nothing to do)
+ }
+ }
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "ariagrid",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ // Internal behavior flags
+ activateCellOnDoubelclick: true,
+ cellFocus: "allow",
+ // TODO: use a global tree option `name` or `title` instead?:
+ label: "Tree Grid", // Added as `aria-label` attribute
+ },
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ treeOpts = ctx.options,
+ opts = treeOpts.ariagrid;
+
+ // ariagrid requires the table extension to be loaded before itself
+ if (tree.ext.grid) {
+ this._requireExtension("grid", true, true);
+ } else {
+ this._requireExtension("table", true, true);
+ }
+ if (!treeOpts.aria) {
+ $.error("ext-ariagrid requires `aria: true`");
+ }
+ if ($.inArray(opts.cellFocus, VALID_MODES) < 0) {
+ $.error("Invalid `cellFocus` option");
+ }
+ this._superApply(arguments);
+
+ // The combination of $activeTd and forceNavMode determines the current
+ // navigation mode:
+ this.$activeTd = null; // active cell (null in row-mode)
+ this.forceNavMode = true;
+
+ this.$container
+ .addClass("fancytree-ext-ariagrid")
+ .toggleClass(clsFancytreeCellNavMode, !!this.forceNavMode)
+ .attr("aria-label", "" + opts.label);
+ this.$container
+ .find("thead > tr > th")
+ .attr("role", "columnheader");
+
+ // Store table options for easier evaluation of default actions
+ // depending of active cell column
+ this.nodeColumnIdx = treeOpts.table.nodeColumnIdx;
+ this.checkboxColumnIdx = treeOpts.table.checkboxColumnIdx;
+ if (this.checkboxColumnIdx == null) {
+ this.checkboxColumnIdx = this.nodeColumnIdx;
+ }
+
+ this.$container
+ .on("focusin", function (event) {
+ // Activate node if embedded input gets focus (due to a click)
+ var node = FT.getNode(event.target),
+ $td = $(event.target).closest("td");
+
+ // tree.debug( "focusin: " + ( node ? node.title : "null" ) +
+ // ", target: " + ( $td ? $td.text() : null ) +
+ // ", node was active: " + ( node && node.isActive() ) +
+ // ", last cell: " + ( tree.$activeTd ? tree.$activeTd.text() : null ) );
+ // tree.debug( "focusin: target", event.target );
+
+ // TODO: add ":input" as delegate filter instead of testing here
+ if (
+ node &&
+ !$td.is(tree.$activeTd) &&
+ $(event.target).is(":input")
+ ) {
+ node.debug("Activate cell on INPUT focus event");
+ tree.activateCell($td);
+ }
+ })
+ .on("fancytreeinit", function (event, data) {
+ if (
+ opts.cellFocus === "start" ||
+ opts.cellFocus === "force"
+ ) {
+ tree.debug("Enforce cell-mode on init");
+ tree.debug(
+ "init",
+ tree.getActiveNode() || tree.getFirstChild()
+ );
+ (
+ tree.getActiveNode() || tree.getFirstChild()
+ ).setActive(true, { cell: tree.nodeColumnIdx });
+ tree.debug(
+ "init2",
+ tree.getActiveNode() || tree.getFirstChild()
+ );
+ }
+ })
+ .on("fancytreefocustree", function (event, data) {
+ // Enforce cell-mode when container gets focus
+ if (opts.cellFocus === "force" && !tree.$activeTd) {
+ var node = tree.getActiveNode() || tree.getFirstChild();
+ tree.debug("Enforce cell-mode on focusTree event");
+ node.setActive(true, { cell: 0 });
+ }
+ })
+ // .on("fancytreeupdateviewport", function(event, data) {
+ // tree.debug(event.type, data);
+ // })
+ .on("fancytreebeforeupdateviewport", function (event, data) {
+ // When scrolling, the TR may be re-used by another node, so the
+ // active cell marker an
+ // tree.debug(event.type, data);
+ if (tree.viewport && tree.$activeTd) {
+ tree.info("Cancel cell-mode due to scroll event.");
+ tree.activateCell(null);
+ }
+ });
+ },
+ nodeClick: function (ctx) {
+ var targetType = ctx.targetType,
+ tree = ctx.tree,
+ node = ctx.node,
+ event = ctx.originalEvent,
+ $target = $(event.target),
+ $td = $target.closest("td");
+
+ tree.debug(
+ "nodeClick: node: " +
+ (node ? node.title : "null") +
+ ", targetType: " +
+ targetType +
+ ", target: " +
+ ($td.length ? $td.text() : null) +
+ ", node was active: " +
+ (node && node.isActive()) +
+ ", last cell: " +
+ (tree.$activeTd ? tree.$activeTd.text() : null)
+ );
+
+ if (tree.$activeTd) {
+ // If already in cell-mode, activate new cell
+ tree.activateCell($td);
+ if ($target.is(":input")) {
+ return;
+ } else if (
+ $target.is(".fancytree-checkbox") ||
+ $target.is(".fancytree-expander")
+ ) {
+ return this._superApply(arguments);
+ }
+ return false;
+ }
+ return this._superApply(arguments);
+ },
+ nodeDblclick: function (ctx) {
+ var tree = ctx.tree,
+ treeOpts = ctx.options,
+ opts = treeOpts.ariagrid,
+ event = ctx.originalEvent,
+ $td = $(event.target).closest("td");
+
+ // console.log("nodeDblclick", tree.$activeTd, ctx.options.ariagrid.cellFocus)
+ if (
+ opts.activateCellOnDoubelclick &&
+ !tree.$activeTd &&
+ opts.cellFocus === "allow"
+ ) {
+ // If in row-mode, activate new cell
+ tree.activateCell($td);
+ return false;
+ }
+ return this._superApply(arguments);
+ },
+ nodeRenderStatus: function (ctx) {
+ // Set classes for current status
+ var res,
+ node = ctx.node,
+ $tr = $(node.tr);
+
+ res = this._super(ctx);
+
+ if (node.parent) {
+ $tr.attr("aria-level", node.getLevel())
+ .attr("aria-setsize", node.parent.children.length)
+ .attr("aria-posinset", node.getIndex() + 1);
+
+ // 2018-06-24: not required according to
+ // https://github.com/w3c/aria-practices/issues/132#issuecomment-397698250
+ // if ( $tr.is( ":hidden" ) ) {
+ // $tr.attr( "aria-hidden", true );
+ // } else {
+ // $tr.removeAttr( "aria-hidden" );
+ // }
+
+ // this.debug("nodeRenderStatus: " + this.$activeTd + ", " + $tr.attr("aria-expanded"));
+ // In cell-mode, move aria-expanded attribute from TR to first child TD
+ if (this.$activeTd && $tr.attr("aria-expanded") != null) {
+ $tr.remove("aria-expanded");
+ $tr.find("td")
+ .eq(this.nodeColumnIdx)
+ .attr("aria-expanded", node.isExpanded());
+ } else {
+ $tr.find("td")
+ .eq(this.nodeColumnIdx)
+ .removeAttr("aria-expanded");
+ }
+ }
+ return res;
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var $td,
+ node = ctx.node,
+ tree = ctx.tree,
+ $tr = $(node.tr);
+
+ flag = flag !== false;
+ node.debug("nodeSetActive(" + flag + ")", callOpts);
+ // Support custom `cell` option
+ if (flag && callOpts && callOpts.cell != null) {
+ // `cell` may be a col-index, <td>, or `$(td)`
+ if (typeof callOpts.cell === "number") {
+ $td = findTdAtColIdx($tr, callOpts.cell);
+ } else {
+ $td = $(callOpts.cell);
+ }
+ tree.activateCell($td);
+ return;
+ }
+ // tree.debug( "nodeSetActive: activeNode " + this.activeNode );
+ return this._superApply(arguments);
+ },
+ nodeKeydown: function (ctx) {
+ var handleKeys,
+ inputType,
+ res,
+ $td,
+ $embeddedCheckbox = null,
+ tree = ctx.tree,
+ node = ctx.node,
+ treeOpts = ctx.options,
+ opts = treeOpts.ariagrid,
+ event = ctx.originalEvent,
+ eventString = FT.eventToString(event),
+ $target = $(event.target),
+ $activeTd = this.$activeTd,
+ $activeTr = $activeTd ? $activeTd.closest("tr") : null,
+ colIdx = $activeTd ? getColIdx($activeTr, $activeTd) : -1,
+ forceNav =
+ $activeTd &&
+ tree.forceNavMode &&
+ $.inArray(eventString, NAV_KEYS) >= 0;
+
+ if (opts.cellFocus === "off") {
+ return this._superApply(arguments);
+ }
+
+ if ($target.is(":input:enabled")) {
+ inputType = $target.prop("type");
+ } else if ($target.is("a")) {
+ inputType = "link";
+ }
+ if ($activeTd && $activeTd.find(":checkbox:enabled").length === 1) {
+ $embeddedCheckbox = $activeTd.find(":checkbox:enabled");
+ inputType = "checkbox";
+ }
+ tree.debug(
+ "nodeKeydown(" +
+ eventString +
+ "), activeTd: '" +
+ ($activeTd && $activeTd.text()) +
+ "', inputType: " +
+ inputType
+ );
+
+ if (inputType && eventString !== "esc" && !forceNav) {
+ handleKeys = INPUT_KEYS[inputType];
+ if (handleKeys && $.inArray(eventString, handleKeys) >= 0) {
+ return; // Let input control handle the key
+ }
+ }
+
+ switch (eventString) {
+ case "right":
+ if ($activeTd) {
+ // Cell mode: move to neighbour (stop on right border)
+ $td = findNeighbourTd(tree, $activeTd, eventString);
+ if ($td) {
+ tree.activateCell($td);
+ }
+ } else if (
+ node &&
+ !node.isExpanded() &&
+ node.hasChildren() !== false
+ ) {
+ // Row mode and current node can be expanded:
+ // default handling will expand.
+ break;
+ } else {
+ // Row mode: switch to cell-mode
+ $td = $(node.tr).find(">td").first();
+ tree.activateCell($td);
+ }
+ return false; // no default handling
+
+ case "left":
+ case "home":
+ case "end":
+ case "ctrl+home":
+ case "ctrl+end":
+ case "up":
+ case "down":
+ if ($activeTd) {
+ // Cell mode: move to neighbour
+ $td = findNeighbourTd(tree, $activeTd, eventString);
+ // Note: $td may be null if we move outside bounds. In this case
+ // we switch back to row-mode (i.e. call activateCell(null) ).
+ if (!$td && "left right".indexOf(eventString) < 0) {
+ // Only switch to row-mode if left/right hits the bounds
+ return false;
+ }
+ if ($td || opts.cellFocus !== "force") {
+ tree.activateCell($td);
+ }
+ return false;
+ }
+ break;
+
+ case "esc":
+ if ($activeTd && !tree.forceNavMode) {
+ // Switch from cell-edit-mode to cell-nav-mode
+ // $target.closest( "td" ).focus();
+ tree.forceNavMode = true;
+ tree.debug("Enter cell-nav-mode");
+ tree.$container.toggleClass(
+ clsFancytreeCellNavMode,
+ !!tree.forceNavMode
+ );
+ return false;
+ } else if ($activeTd && opts.cellFocus !== "force") {
+ // Switch back from cell-mode to row-mode
+ tree.activateCell(null);
+ return false;
+ }
+ // tree.$container.toggleClass( clsFancytreeCellNavMode, !!tree.forceNavMode );
+ break;
+
+ case "return":
+ // Let user override the default action.
+ // This event is triggered in row-mode and cell-mode
+ res = tree._triggerNodeEvent(
+ "defaultGridAction",
+ node,
+ event,
+ {
+ activeTd: tree.$activeTd ? tree.$activeTd[0] : null,
+ colIdx: colIdx,
+ mode: getGridNavMode(tree),
+ }
+ );
+ if (res === false) {
+ return false;
+ }
+ // Implement default actions (for cell-mode only).
+ if ($activeTd) {
+ // Apply 'default action' for embedded cell control
+ if (colIdx === this.nodeColumnIdx) {
+ node.toggleExpanded();
+ } else if (colIdx === this.checkboxColumnIdx) {
+ // TODO: only in checkbox mode!
+ node.toggleSelected();
+ } else if ($embeddedCheckbox) {
+ // Embedded checkboxes are always toggled (ignoring `autoFocusInput`)
+ $embeddedCheckbox.prop(
+ "checked",
+ !$embeddedCheckbox.prop("checked")
+ );
+ } else if (tree.forceNavMode && $target.is(":input")) {
+ tree.forceNavMode = false;
+ tree.$container.removeClass(
+ clsFancytreeCellNavMode
+ );
+ tree.debug("enable cell-edit-mode");
+ } else if ($activeTd.find("a").length === 1) {
+ activateEmbeddedLink($activeTd);
+ }
+ } else {
+ // ENTER in row-mode: Switch from row-mode to cell-mode
+ // TODO: it was also suggested to expand/collapse instead
+ // https://github.com/w3c/aria-practices/issues/132#issuecomment-407634891
+ $td = $(node.tr).find(">td").nth(this.nodeColumnIdx);
+ tree.activateCell($td);
+ }
+ return false; // no default handling
+
+ case "space":
+ if ($activeTd) {
+ if (colIdx === this.checkboxColumnIdx) {
+ node.toggleSelected();
+ } else if ($embeddedCheckbox) {
+ $embeddedCheckbox.prop(
+ "checked",
+ !$embeddedCheckbox.prop("checked")
+ );
+ }
+ return false; // no default handling
+ }
+ break;
+
+ default:
+ // Allow to focus input by typing alphanum keys
+ }
+ return this._superApply(arguments);
+ },
+ treeSetOption: function (ctx, key, value) {
+ var tree = ctx.tree,
+ opts = tree.options.ariagrid;
+
+ if (key === "ariagrid") {
+ // User called `$().fancytree("option", "ariagrid.SUBKEY", VALUE)`
+ if (value.cellFocus !== opts.cellFocus) {
+ if ($.inArray(value.cellFocus, VALID_MODES) < 0) {
+ $.error("Invalid `cellFocus` option");
+ }
+ // TODO: fix current focus and mode
+ }
+ }
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.childcounter.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.childcounter.js
new file mode 100644
index 0000000..216b124
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.childcounter.js
@@ -0,0 +1,241 @@
+// Extending Fancytree
+// ===================
+//
+// See also the [live demo](https://wwWendt.de/tech/fancytree/demo/sample-ext-childcounter.html) of this code.
+//
+// Every extension should have a comment header containing some information
+// about the author, copyright and licensing. Also a pointer to the latest
+// source code.
+// Prefix with `/*!` so the comment is not removed by the minifier.
+
+/*!
+ * jquery.fancytree.childcounter.js
+ *
+ * Add a child counter bubble to tree nodes.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+// To keep the global namespace clean, we wrap everything in a closure.
+// The UMD wrapper pattern defines the dependencies on jQuery and the
+// Fancytree core module, and makes sure that we can use the `require()`
+// syntax with package loaders.
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ // Consider to use [strict mode](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
+ "use strict";
+
+ // The [coding guidelines](http://contribute.jquery.org/style-guide/js/)
+ // require jshint /eslint compliance.
+ // But for this sample, we want to allow unused variables for demonstration purpose.
+
+ /*eslint-disable no-unused-vars */
+
+ // Adding methods
+ // --------------
+
+ // New member functions can be added to the `Fancytree` class.
+ // This function will be available for every tree instance:
+ //
+ // var tree = $.ui.fancytree.getTree("#tree");
+ // tree.countSelected(false);
+
+ $.ui.fancytree._FancytreeClass.prototype.countSelected = function (
+ topOnly
+ ) {
+ var tree = this,
+ treeOptions = tree.options;
+
+ return tree.getSelectedNodes(topOnly).length;
+ };
+
+ // The `FancytreeNode` class can also be easily extended. This would be called
+ // like
+ // node.updateCounters();
+ //
+ // It is also good practice to add a docstring comment.
+ /**
+ * [ext-childcounter] Update counter badges for `node` and its parents.
+ * May be called in the `loadChildren` event, to update parents of lazy loaded
+ * nodes.
+ * @alias FancytreeNode#updateCounters
+ * @requires jquery.fancytree.childcounters.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.updateCounters = function () {
+ var node = this,
+ $badge = $("span.fancytree-childcounter", node.span),
+ extOpts = node.tree.options.childcounter,
+ count = node.countChildren(extOpts.deep);
+
+ node.data.childCounter = count;
+ if (
+ (count || !extOpts.hideZeros) &&
+ (!node.isExpanded() || !extOpts.hideExpanded)
+ ) {
+ if (!$badge.length) {
+ $badge = $("<span class='fancytree-childcounter'/>").appendTo(
+ $(
+ "span.fancytree-icon,span.fancytree-custom-icon",
+ node.span
+ )
+ );
+ }
+ $badge.text(count);
+ } else {
+ $badge.remove();
+ }
+ if (extOpts.deep && !node.isTopLevel() && !node.isRootNode()) {
+ node.parent.updateCounters();
+ }
+ };
+
+ // Finally, we can extend the widget API and create functions that are called
+ // like so:
+ //
+ // $("#tree").fancytree("widgetMethod1", "abc");
+
+ $.ui.fancytree.prototype.widgetMethod1 = function (arg1) {
+ var tree = this.tree;
+ return arg1;
+ };
+
+ // Register a Fancytree extension
+ // ------------------------------
+ // A full blown extension, extension is available for all trees and can be
+ // enabled like so (see also the [live demo](https://wwWendt.de/tech/fancytree/demo/sample-ext-childcounter.html)):
+ //
+ // <script src="../src/jquery.fancytree.js"></script>
+ // <script src="../src/jquery.fancytree.childcounter.js"></script>
+ // ...
+ //
+ // $("#tree").fancytree({
+ // extensions: ["childcounter"],
+ // childcounter: {
+ // hideExpanded: true
+ // },
+ // ...
+ // });
+ //
+
+ /* 'childcounter' extension */
+ $.ui.fancytree.registerExtension({
+ // Every extension must be registered by a unique name.
+ name: "childcounter",
+ // Version information should be compliant with [semver](http://semver.org)
+ version: "2.38.3",
+
+ // Extension specific options and their defaults.
+ // This options will be available as `tree.options.childcounter.hideExpanded`
+
+ options: {
+ deep: true,
+ hideZeros: true,
+ hideExpanded: false,
+ },
+
+ // Attributes other than `options` (or functions) can be defined here, and
+ // will be added to the tree.ext.EXTNAME namespace, in this case `tree.ext.childcounter.foo`.
+ // They can also be accessed as `this._local.foo` from within the extension
+ // methods.
+ foo: 42,
+
+ // Local functions are prefixed with an underscore '_'.
+ // Callable as `this._local._appendCounter()`.
+
+ _appendCounter: function (bar) {
+ var tree = this;
+ },
+
+ // **Override virtual methods for this extension.**
+ //
+ // Fancytree implements a number of 'hook methods', prefixed by 'node...' or 'tree...'.
+ // with a `ctx` argument (see [EventData](https://wwWendt.de/tech/fancytree/doc/jsdoc/global.html#EventData)
+ // for details) and an extended calling context:<br>
+ // `this` : the Fancytree instance<br>
+ // `this._local`: the namespace that contains extension attributes and private methods (same as this.ext.EXTNAME)<br>
+ // `this._super`: the virtual function that was overridden (member of previous extension or Fancytree)
+ //
+ // See also the [complete list of available hook functions](https://wwWendt.de/tech/fancytree/doc/jsdoc/Fancytree_Hooks.html).
+
+ /* Init */
+ // `treeInit` is triggered when a tree is initalized. We can set up classes or
+ // bind event handlers here...
+ treeInit: function (ctx) {
+ var tree = this, // same as ctx.tree,
+ opts = ctx.options,
+ extOpts = ctx.options.childcounter;
+ // Optionally check for dependencies with other extensions
+ /* this._requireExtension("glyph", false, false); */
+ // Call the base implementation
+ this._superApply(arguments);
+ // Add a class to the tree container
+ this.$container.addClass("fancytree-ext-childcounter");
+ },
+
+ // Destroy this tree instance (we only call the default implementation, so
+ // this method could as well be omitted).
+
+ treeDestroy: function (ctx) {
+ this._superApply(arguments);
+ },
+
+ // Overload the `renderTitle` hook, to append a counter badge
+ nodeRenderTitle: function (ctx, title) {
+ var node = ctx.node,
+ extOpts = ctx.options.childcounter,
+ count =
+ node.data.childCounter == null
+ ? node.countChildren(extOpts.deep)
+ : +node.data.childCounter;
+ // Let the base implementation render the title
+ // We use `_super()` instead of `_superApply()` here, since it is a little bit
+ // more performant when called often
+ this._super(ctx, title);
+ // Append a counter badge
+ if (
+ (count || !extOpts.hideZeros) &&
+ (!node.isExpanded() || !extOpts.hideExpanded)
+ ) {
+ $(
+ "span.fancytree-icon,span.fancytree-custom-icon",
+ node.span
+ ).append(
+ $("<span class='fancytree-childcounter'/>").text(count)
+ );
+ }
+ },
+ // Overload the `setExpanded` hook, so the counters are updated
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var tree = ctx.tree,
+ node = ctx.node;
+ // Let the base implementation expand/collapse the node, then redraw the title
+ // after the animation has finished
+ return this._superApply(arguments).always(function () {
+ tree.nodeRenderTitle(ctx);
+ });
+ },
+
+ // End of extension definition
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.clones.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.clones.js
new file mode 100644
index 0000000..08f8f2b
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.clones.js
@@ -0,0 +1,514 @@
+/*!
+ *
+ * jquery.fancytree.clones.js
+ * Support faster lookup of nodes by key and shared ref-ids.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ var _assert = $.ui.fancytree.assert;
+
+ /* Return first occurrence of member from array. */
+ function _removeArrayMember(arr, elem) {
+ // TODO: use Array.indexOf for IE >= 9
+ var i;
+ for (i = arr.length - 1; i >= 0; i--) {
+ if (arr[i] === elem) {
+ arr.splice(i, 1);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
+ *
+ * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
+ * @see http://github.com/garycourt/murmurhash-js
+ * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
+ * @see http://sites.google.com/site/murmurhash/
+ *
+ * @param {string} key ASCII only
+ * @param {boolean} [asString=false]
+ * @param {number} seed Positive integer only
+ * @return {number} 32-bit positive integer hash
+ */
+ function hashMurmur3(key, asString, seed) {
+ /*eslint-disable no-bitwise */
+ var h1b,
+ k1,
+ remainder = key.length & 3,
+ bytes = key.length - remainder,
+ h1 = seed,
+ c1 = 0xcc9e2d51,
+ c2 = 0x1b873593,
+ i = 0;
+
+ while (i < bytes) {
+ k1 =
+ (key.charCodeAt(i) & 0xff) |
+ ((key.charCodeAt(++i) & 0xff) << 8) |
+ ((key.charCodeAt(++i) & 0xff) << 16) |
+ ((key.charCodeAt(++i) & 0xff) << 24);
+ ++i;
+
+ k1 =
+ ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) &
+ 0xffffffff;
+ k1 = (k1 << 15) | (k1 >>> 17);
+ k1 =
+ ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) &
+ 0xffffffff;
+
+ h1 ^= k1;
+ h1 = (h1 << 13) | (h1 >>> 19);
+ h1b =
+ ((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 =
+ (h1b & 0xffff) +
+ 0x6b64 +
+ ((((h1b >>> 16) + 0xe654) & 0xffff) << 16);
+ }
+
+ k1 = 0;
+
+ switch (remainder) {
+ case 3:
+ k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
+ // fall through
+ case 2:
+ k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
+ // fall through
+ case 1:
+ k1 ^= key.charCodeAt(i) & 0xff;
+
+ k1 =
+ ((k1 & 0xffff) * c1 +
+ ((((k1 >>> 16) * c1) & 0xffff) << 16)) &
+ 0xffffffff;
+ k1 = (k1 << 15) | (k1 >>> 17);
+ k1 =
+ ((k1 & 0xffff) * c2 +
+ ((((k1 >>> 16) * c2) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 ^= k1;
+ }
+
+ h1 ^= key.length;
+
+ h1 ^= h1 >>> 16;
+ h1 =
+ ((h1 & 0xffff) * 0x85ebca6b +
+ ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 ^= h1 >>> 13;
+ h1 =
+ ((h1 & 0xffff) * 0xc2b2ae35 +
+ ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) &
+ 0xffffffff;
+ h1 ^= h1 >>> 16;
+
+ if (asString) {
+ // Convert to 8 digit hex string
+ return ("0000000" + (h1 >>> 0).toString(16)).substr(-8);
+ }
+ return h1 >>> 0;
+ /*eslint-enable no-bitwise */
+ }
+
+ /*
+ * Return a unique key for node by calculating the hash of the parents refKey-list.
+ */
+ function calcUniqueKey(node) {
+ var key,
+ h1,
+ path = $.map(node.getParentList(false, true), function (e) {
+ return e.refKey || e.key;
+ });
+
+ path = path.join("/");
+ // 32-bit has a high probability of collisions, so we pump up to 64-bit
+ // https://security.stackexchange.com/q/209882/207588
+
+ h1 = hashMurmur3(path, true);
+ key = "id_" + h1 + hashMurmur3(h1 + path, true);
+
+ return key;
+ }
+
+ /**
+ * [ext-clones] Return a list of clone-nodes (i.e. same refKey) or null.
+ * @param {boolean} [includeSelf=false]
+ * @returns {FancytreeNode[] | null}
+ *
+ * @alias FancytreeNode#getCloneList
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.getCloneList = function (
+ includeSelf
+ ) {
+ var key,
+ tree = this.tree,
+ refList = tree.refMap[this.refKey] || null,
+ keyMap = tree.keyMap;
+
+ if (refList) {
+ key = this.key;
+ // Convert key list to node list
+ if (includeSelf) {
+ refList = $.map(refList, function (val) {
+ return keyMap[val];
+ });
+ } else {
+ refList = $.map(refList, function (val) {
+ return val === key ? null : keyMap[val];
+ });
+ if (refList.length < 1) {
+ refList = null;
+ }
+ }
+ }
+ return refList;
+ };
+
+ /**
+ * [ext-clones] Return true if this node has at least another clone with same refKey.
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#isClone
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.isClone = function () {
+ var refKey = this.refKey || null,
+ refList = (refKey && this.tree.refMap[refKey]) || null;
+ return !!(refList && refList.length > 1);
+ };
+
+ /**
+ * [ext-clones] Update key and/or refKey for an existing node.
+ * @param {string} key
+ * @param {string} refKey
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#reRegister
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.reRegister = function (
+ key,
+ refKey
+ ) {
+ key = key == null ? null : "" + key;
+ refKey = refKey == null ? null : "" + refKey;
+ // this.debug("reRegister", key, refKey);
+
+ var tree = this.tree,
+ prevKey = this.key,
+ prevRefKey = this.refKey,
+ keyMap = tree.keyMap,
+ refMap = tree.refMap,
+ refList = refMap[prevRefKey] || null,
+ // curCloneKeys = refList ? node.getCloneList(true),
+ modified = false;
+
+ // Key has changed: update all references
+ if (key != null && key !== this.key) {
+ if (keyMap[key]) {
+ $.error(
+ "[ext-clones] reRegister(" +
+ key +
+ "): already exists: " +
+ this
+ );
+ }
+ // Update keyMap
+ delete keyMap[prevKey];
+ keyMap[key] = this;
+ // Update refMap
+ if (refList) {
+ refMap[prevRefKey] = $.map(refList, function (e) {
+ return e === prevKey ? key : e;
+ });
+ }
+ this.key = key;
+ modified = true;
+ }
+
+ // refKey has changed
+ if (refKey != null && refKey !== this.refKey) {
+ // Remove previous refKeys
+ if (refList) {
+ if (refList.length === 1) {
+ delete refMap[prevRefKey];
+ } else {
+ refMap[prevRefKey] = $.map(refList, function (e) {
+ return e === prevKey ? null : e;
+ });
+ }
+ }
+ // Add refKey
+ if (refMap[refKey]) {
+ refMap[refKey].append(key);
+ } else {
+ refMap[refKey] = [this.key];
+ }
+ this.refKey = refKey;
+ modified = true;
+ }
+ return modified;
+ };
+
+ /**
+ * [ext-clones] Define a refKey for an existing node.
+ * @param {string} refKey
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#setRefKey
+ * @requires jquery.fancytree.clones.js
+ * @since 2.16
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.setRefKey = function (refKey) {
+ return this.reRegister(null, refKey);
+ };
+
+ /**
+ * [ext-clones] Return all nodes with a given refKey (null if not found).
+ * @param {string} refKey
+ * @param {FancytreeNode} [rootNode] optionally restrict results to descendants of this node
+ * @returns {FancytreeNode[] | null}
+ * @alias Fancytree#getNodesByRef
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.getNodesByRef = function (
+ refKey,
+ rootNode
+ ) {
+ var keyMap = this.keyMap,
+ refList = this.refMap[refKey] || null;
+
+ if (refList) {
+ // Convert key list to node list
+ if (rootNode) {
+ refList = $.map(refList, function (val) {
+ var node = keyMap[val];
+ return node.isDescendantOf(rootNode) ? node : null;
+ });
+ } else {
+ refList = $.map(refList, function (val) {
+ return keyMap[val];
+ });
+ }
+ if (refList.length < 1) {
+ refList = null;
+ }
+ }
+ return refList;
+ };
+
+ /**
+ * [ext-clones] Replace a refKey with a new one.
+ * @param {string} oldRefKey
+ * @param {string} newRefKey
+ * @alias Fancytree#changeRefKey
+ * @requires jquery.fancytree.clones.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.changeRefKey = function (
+ oldRefKey,
+ newRefKey
+ ) {
+ var i,
+ node,
+ keyMap = this.keyMap,
+ refList = this.refMap[oldRefKey] || null;
+
+ if (refList) {
+ for (i = 0; i < refList.length; i++) {
+ node = keyMap[refList[i]];
+ node.refKey = newRefKey;
+ }
+ delete this.refMap[oldRefKey];
+ this.refMap[newRefKey] = refList;
+ }
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "clones",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers
+ highlightClones: false, // set 'fancytree-clone' class on any node that has at least one clone
+ },
+
+ treeCreate: function (ctx) {
+ this._superApply(arguments);
+ ctx.tree.refMap = {};
+ ctx.tree.keyMap = {};
+ },
+ treeInit: function (ctx) {
+ this.$container.addClass("fancytree-ext-clones");
+ _assert(ctx.options.defaultKey == null);
+ // Generate unique / reproducible default keys
+ ctx.options.defaultKey = function (node) {
+ return calcUniqueKey(node);
+ };
+ // The default implementation loads initial data
+ this._superApply(arguments);
+ },
+ treeClear: function (ctx) {
+ ctx.tree.refMap = {};
+ ctx.tree.keyMap = {};
+ return this._superApply(arguments);
+ },
+ treeRegisterNode: function (ctx, add, node) {
+ var refList,
+ len,
+ tree = ctx.tree,
+ keyMap = tree.keyMap,
+ refMap = tree.refMap,
+ key = node.key,
+ refKey = node && node.refKey != null ? "" + node.refKey : null;
+
+ // ctx.tree.debug("clones.treeRegisterNode", add, node);
+
+ if (node.isStatusNode()) {
+ return this._super(ctx, add, node);
+ }
+
+ if (add) {
+ if (keyMap[node.key] != null) {
+ var other = keyMap[node.key],
+ msg =
+ "clones.treeRegisterNode: duplicate key '" +
+ node.key +
+ "': /" +
+ node.getPath(true) +
+ " => " +
+ other.getPath(true);
+ // Sometimes this exception is not visible in the console,
+ // so we also write it:
+ tree.error(msg);
+ $.error(msg);
+ }
+ keyMap[key] = node;
+
+ if (refKey) {
+ refList = refMap[refKey];
+ if (refList) {
+ refList.push(key);
+ if (
+ refList.length === 2 &&
+ ctx.options.clones.highlightClones
+ ) {
+ // Mark peer node, if it just became a clone (no need to
+ // mark current node, since it will be rendered later anyway)
+ keyMap[refList[0]].renderStatus();
+ }
+ } else {
+ refMap[refKey] = [key];
+ }
+ // node.debug("clones.treeRegisterNode: add clone =>", refMap[refKey]);
+ }
+ } else {
+ if (keyMap[key] == null) {
+ $.error(
+ "clones.treeRegisterNode: node.key not registered: " +
+ node.key
+ );
+ }
+ delete keyMap[key];
+ if (refKey) {
+ refList = refMap[refKey];
+ // node.debug("clones.treeRegisterNode: remove clone BEFORE =>", refMap[refKey]);
+ if (refList) {
+ len = refList.length;
+ if (len <= 1) {
+ _assert(len === 1);
+ _assert(refList[0] === key);
+ delete refMap[refKey];
+ } else {
+ _removeArrayMember(refList, key);
+ // Unmark peer node, if this was the only clone
+ if (
+ len === 2 &&
+ ctx.options.clones.highlightClones
+ ) {
+ // node.debug("clones.treeRegisterNode: last =>", node.getCloneList());
+ keyMap[refList[0]].renderStatus();
+ }
+ }
+ // node.debug("clones.treeRegisterNode: remove clone =>", refMap[refKey]);
+ }
+ }
+ }
+ return this._super(ctx, add, node);
+ },
+ nodeRenderStatus: function (ctx) {
+ var $span,
+ res,
+ node = ctx.node;
+
+ res = this._super(ctx);
+
+ if (ctx.options.clones.highlightClones) {
+ $span = $(node[ctx.tree.statusClassPropName]);
+ // Only if span already exists
+ if ($span.length && node.isClone()) {
+ // node.debug("clones.nodeRenderStatus: ", ctx.options.clones.highlightClones);
+ $span.addClass("fancytree-clone");
+ }
+ }
+ return res;
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var res,
+ scpn = ctx.tree.statusClassPropName,
+ node = ctx.node;
+
+ res = this._superApply(arguments);
+
+ if (ctx.options.clones.highlightActiveClones && node.isClone()) {
+ $.each(node.getCloneList(true), function (idx, n) {
+ // n.debug("clones.nodeSetActive: ", flag !== false);
+ $(n[scpn]).toggleClass(
+ "fancytree-active-clone",
+ flag !== false
+ );
+ });
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.columnview.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.columnview.js
new file mode 100644
index 0000000..98afd52
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.columnview.js
@@ -0,0 +1,205 @@
+/*!
+ * jquery.fancytree.columnview.js
+ *
+ * Render tree like a Mac Finder's column view.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+ var _assert = $.ui.fancytree.assert,
+ FT = $.ui.fancytree;
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+ $.ui.fancytree.registerExtension({
+ name: "columnview",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {},
+ // Overide virtual methods for this extension.
+ // `this` : is this extension object
+ // `this._base` : the Fancytree instance
+ // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
+ treeInit: function (ctx) {
+ var $tdFirst,
+ $ul,
+ tree = ctx.tree,
+ $table = tree.widget.element;
+
+ tree.tr = $("tbody tr", $table)[0];
+ tree.$tdList = $(">td", tree.tr);
+ tree.columnCount = tree.$tdList.length;
+ // Perform default behavior
+ this._superApply(arguments);
+ // Standard Fancytree created a root <ul>. Now move this into first table cell
+ $ul = $(tree.rootNode.ul);
+ $tdFirst = tree.$tdList.eq(0);
+
+ _assert(
+ $.inArray("table", this.options.extensions) < 0,
+ "columnview extensions must not use ext-table"
+ );
+ _assert(
+ tree.columnCount >= 2,
+ "columnview target must be a table with at least two columns"
+ );
+
+ $ul.removeClass("fancytree-container").removeAttr("tabindex");
+ tree.$container = $table;
+ $table
+ .addClass("fancytree-container fancytree-ext-columnview")
+ .attr("tabindex", "0");
+
+ $tdFirst.empty();
+ $ul.detach().appendTo($tdFirst);
+
+ // Force some required options
+ tree.widget.options.autoCollapse = true;
+ // tree.widget.options.autoActivate = true;
+ tree.widget.options.toggleEffect = false;
+ tree.widget.options.clickFolderMode = 1;
+
+ $table
+ // Make sure that only active path is expanded when a node is activated:
+ .on("fancytreeactivate", function (event, data) {
+ var node = data.node,
+ tree = data.tree,
+ level = node.getLevel();
+
+ tree._callHook("nodeCollapseSiblings", node);
+ // Clear right neighbours
+ if (!node.expanded) {
+ tree.$tdList.eq(level).nextAll().empty();
+ }
+ // Expand nodes on activate, so we populate the right neighbor cell
+ if (!node.expanded && (node.children || node.lazy)) {
+ node.setExpanded();
+ }
+ })
+ // Adjust keyboard behaviour:
+ .on("fancytreekeydown", function (event, data) {
+ var next = null,
+ handled = true,
+ node = data.node || data.tree.getFirstChild();
+
+ if (node.getLevel() >= tree.columnCount) {
+ return;
+ }
+ switch (FT.eventToString(event)) {
+ case "down":
+ next = node.getNextSibling();
+ break;
+ case "left":
+ if (!node.isTopLevel()) {
+ next = node.getParent();
+ }
+ break;
+ case "right":
+ next = node.getFirstChild();
+ if (!next) {
+ // default processing: expand or ignore
+ return;
+ }
+ // Prefer an expanded child if any
+ next.visitSiblings(function (n) {
+ if (n.expanded) {
+ next = n;
+ return false;
+ }
+ }, true);
+ break;
+ case "up":
+ next = node.getPrevSibling();
+ break;
+ default:
+ handled = false;
+ }
+ if (next) {
+ next.setActive();
+ }
+ return !handled;
+ });
+ },
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var $wait,
+ node = ctx.node,
+ tree = ctx.tree,
+ level = node.getLevel();
+
+ if (flag !== false && !node.expanded && node.isUndefined()) {
+ $wait = $(
+ "<span class='fancytree-icon fancytree-icon-loading'>"
+ );
+ tree.$tdList.eq(level).empty().append($wait);
+ }
+ return this._superApply(arguments);
+ },
+ nodeRemoveChildren: function (ctx) {
+ // #899: node's children removed: remove child marker...
+ $(ctx.node.span).find("span.fancytree-cv-right").remove();
+ // ...and clear right columns
+ ctx.tree.$tdList.eq(ctx.node.getLevel()).nextAll().empty();
+ return this._superApply(arguments);
+ },
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ // Render standard nested <ul> - <li> hierarchy
+ this._super(ctx, force, deep, collapsed, _recursive);
+ // Remove expander and add a trailing triangle instead
+ var level,
+ $tdChild,
+ $ul,
+ tree = ctx.tree,
+ node = ctx.node,
+ $span = $(node.span);
+
+ $span.find("span.fancytree-expander").remove();
+ if (
+ node.hasChildren() !== false &&
+ !$span.find("span.fancytree-cv-right").length
+ ) {
+ $span.append(
+ $("<span class='fancytree-icon fancytree-cv-right'>")
+ );
+ }
+ // Move <ul> with children into the appropriate <td>
+ if (node.ul && node.expanded) {
+ node.ul.style.display = ""; // might be hidden if RIGHT was pressed
+ level = node.getLevel();
+ if (level < tree.columnCount) {
+ // only if we are not in the last column
+ $tdChild = tree.$tdList.eq(level);
+ $ul = $(node.ul).detach();
+ $tdChild.empty().append($ul);
+ }
+ }
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.dnd.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.dnd.js
new file mode 100644
index 0000000..e9f68ad
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.dnd.js
@@ -0,0 +1,798 @@
+/*!
+ * jquery.fancytree.dnd.js
+ *
+ * Drag-and-drop support (jQuery UI draggable/droppable).
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([
+ "jquery",
+ "jquery-ui/ui/widgets/draggable",
+ "jquery-ui/ui/widgets/droppable",
+ "./jquery.fancytree",
+ ], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var didRegisterDnd = false,
+ classDropAccept = "fancytree-drop-accept",
+ classDropAfter = "fancytree-drop-after",
+ classDropBefore = "fancytree-drop-before",
+ classDropOver = "fancytree-drop-over",
+ classDropReject = "fancytree-drop-reject",
+ classDropTarget = "fancytree-drop-target";
+
+ /* Convert number to string and prepend +/-; return empty string for 0.*/
+ function offsetString(n) {
+ // eslint-disable-next-line no-nested-ternary
+ return n === 0 ? "" : n > 0 ? "+" + n : "" + n;
+ }
+
+ //--- Extend ui.draggable event handling --------------------------------------
+
+ function _registerDnd() {
+ if (didRegisterDnd) {
+ return;
+ }
+
+ // Register proxy-functions for draggable.start/drag/stop
+
+ $.ui.plugin.add("draggable", "connectToFancytree", {
+ start: function (event, ui) {
+ // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
+ var draggable =
+ $(this).data("ui-draggable") ||
+ $(this).data("draggable"),
+ sourceNode = ui.helper.data("ftSourceNode") || null;
+
+ if (sourceNode) {
+ // Adjust helper offset, so cursor is slightly outside top/left corner
+ draggable.offset.click.top = -2;
+ draggable.offset.click.left = +16;
+ // Trigger dragStart event
+ // TODO: when called as connectTo..., the return value is ignored(?)
+ return sourceNode.tree.ext.dnd._onDragEvent(
+ "start",
+ sourceNode,
+ null,
+ event,
+ ui,
+ draggable
+ );
+ }
+ },
+ drag: function (event, ui) {
+ var ctx,
+ isHelper,
+ logObject,
+ // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
+ draggable =
+ $(this).data("ui-draggable") ||
+ $(this).data("draggable"),
+ sourceNode = ui.helper.data("ftSourceNode") || null,
+ prevTargetNode = ui.helper.data("ftTargetNode") || null,
+ targetNode = $.ui.fancytree.getNode(event.target),
+ dndOpts = sourceNode && sourceNode.tree.options.dnd;
+
+ // logObject = sourceNode || prevTargetNode || $.ui.fancytree;
+ // logObject.debug("Drag event:", event, event.shiftKey);
+ if (event.target && !targetNode) {
+ // We got a drag event, but the targetNode could not be found
+ // at the event location. This may happen,
+ // 1. if the mouse jumped over the drag helper,
+ // 2. or if a non-fancytree element is dragged
+ // We ignore it:
+ isHelper =
+ $(event.target).closest(
+ "div.fancytree-drag-helper,#fancytree-drop-marker"
+ ).length > 0;
+ if (isHelper) {
+ logObject =
+ sourceNode || prevTargetNode || $.ui.fancytree;
+ logObject.debug("Drag event over helper: ignored.");
+ return;
+ }
+ }
+ ui.helper.data("ftTargetNode", targetNode);
+
+ if (dndOpts && dndOpts.updateHelper) {
+ ctx = sourceNode.tree._makeHookContext(sourceNode, event, {
+ otherNode: targetNode,
+ ui: ui,
+ draggable: draggable,
+ dropMarker: $("#fancytree-drop-marker"),
+ });
+ dndOpts.updateHelper.call(sourceNode.tree, sourceNode, ctx);
+ }
+
+ // Leaving a tree node
+ if (prevTargetNode && prevTargetNode !== targetNode) {
+ prevTargetNode.tree.ext.dnd._onDragEvent(
+ "leave",
+ prevTargetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ }
+ if (targetNode) {
+ if (!targetNode.tree.options.dnd.dragDrop) {
+ // not enabled as drop target
+ } else if (targetNode === prevTargetNode) {
+ // Moving over same node
+ targetNode.tree.ext.dnd._onDragEvent(
+ "over",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ } else {
+ // Entering this node first time
+ targetNode.tree.ext.dnd._onDragEvent(
+ "enter",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ targetNode.tree.ext.dnd._onDragEvent(
+ "over",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ }
+ }
+ // else go ahead with standard event handling
+ },
+ stop: function (event, ui) {
+ var logObject,
+ // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10:
+ draggable =
+ $(this).data("ui-draggable") ||
+ $(this).data("draggable"),
+ sourceNode = ui.helper.data("ftSourceNode") || null,
+ targetNode = ui.helper.data("ftTargetNode") || null,
+ dropped = event.type === "mouseup" && event.which === 1;
+
+ if (!dropped) {
+ logObject = sourceNode || targetNode || $.ui.fancytree;
+ logObject.debug("Drag was cancelled");
+ }
+ if (targetNode) {
+ if (dropped) {
+ targetNode.tree.ext.dnd._onDragEvent(
+ "drop",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ }
+ targetNode.tree.ext.dnd._onDragEvent(
+ "leave",
+ targetNode,
+ sourceNode,
+ event,
+ ui,
+ draggable
+ );
+ }
+ if (sourceNode) {
+ sourceNode.tree.ext.dnd._onDragEvent(
+ "stop",
+ sourceNode,
+ null,
+ event,
+ ui,
+ draggable
+ );
+ }
+ },
+ });
+
+ didRegisterDnd = true;
+ }
+
+ /******************************************************************************
+ * Drag and drop support
+ */
+ function _initDragAndDrop(tree) {
+ var dnd = tree.options.dnd || null,
+ glyph = tree.options.glyph || null;
+
+ // Register 'connectToFancytree' option with ui.draggable
+ if (dnd) {
+ _registerDnd();
+ }
+ // Attach ui.draggable to this Fancytree instance
+ if (dnd && dnd.dragStart) {
+ tree.widget.element.draggable(
+ $.extend(
+ {
+ addClasses: false,
+ // DT issue 244: helper should be child of scrollParent:
+ appendTo: tree.$container,
+ // appendTo: "body",
+ containment: false,
+ // containment: "parent",
+ delay: 0,
+ distance: 4,
+ revert: false,
+ scroll: true, // to disable, also set css 'position: inherit' on ul.fancytree-container
+ scrollSpeed: 7,
+ scrollSensitivity: 10,
+ // Delegate draggable.start, drag, and stop events to our handler
+ connectToFancytree: true,
+ // Let source tree create the helper element
+ helper: function (event) {
+ var $helper,
+ $nodeTag,
+ opts,
+ sourceNode = $.ui.fancytree.getNode(
+ event.target
+ );
+
+ if (!sourceNode) {
+ // #405, DT issue 211: might happen, if dragging a table *header*
+ return "<div>ERROR?: helper requested but sourceNode not found</div>";
+ }
+ opts = sourceNode.tree.options.dnd;
+ $nodeTag = $(sourceNode.span);
+ // Only event and node argument is available
+ $helper = $(
+ "<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>"
+ )
+ .css({ zIndex: 3, position: "relative" }) // so it appears above ext-wide selection bar
+ .append(
+ $nodeTag
+ .find("span.fancytree-title")
+ .clone()
+ );
+
+ // Attach node reference to helper object
+ $helper.data("ftSourceNode", sourceNode);
+
+ // Support glyph symbols instead of icons
+ if (glyph) {
+ $helper
+ .find(".fancytree-drag-helper-img")
+ .addClass(
+ glyph.map._addClass +
+ " " +
+ glyph.map.dragHelper
+ );
+ }
+ // Allow to modify the helper, e.g. to add multi-node-drag feedback
+ if (opts.initHelper) {
+ opts.initHelper.call(
+ sourceNode.tree,
+ sourceNode,
+ {
+ node: sourceNode,
+ tree: sourceNode.tree,
+ originalEvent: event,
+ ui: { helper: $helper },
+ }
+ );
+ }
+ // We return an unconnected element, so `draggable` will add this
+ // to the parent specified as `appendTo` option
+ return $helper;
+ },
+ start: function (event, ui) {
+ var sourceNode = ui.helper.data("ftSourceNode");
+ return !!sourceNode; // Abort dragging if no node could be found
+ },
+ },
+ tree.options.dnd.draggable
+ )
+ );
+ }
+ // Attach ui.droppable to this Fancytree instance
+ if (dnd && dnd.dragDrop) {
+ tree.widget.element.droppable(
+ $.extend(
+ {
+ addClasses: false,
+ tolerance: "intersect",
+ greedy: false,
+ /*
+ activate: function(event, ui) {
+ tree.debug("droppable - activate", event, ui, this);
+ },
+ create: function(event, ui) {
+ tree.debug("droppable - create", event, ui);
+ },
+ deactivate: function(event, ui) {
+ tree.debug("droppable - deactivate", event, ui);
+ },
+ drop: function(event, ui) {
+ tree.debug("droppable - drop", event, ui);
+ },
+ out: function(event, ui) {
+ tree.debug("droppable - out", event, ui);
+ },
+ over: function(event, ui) {
+ tree.debug("droppable - over", event, ui);
+ }
+*/
+ },
+ tree.options.dnd.droppable
+ )
+ );
+ }
+ }
+
+ /******************************************************************************
+ *
+ */
+
+ $.ui.fancytree.registerExtension({
+ name: "dnd",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ // Make tree nodes accept draggables
+ autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
+ draggable: null, // Additional options passed to jQuery draggable
+ droppable: null, // Additional options passed to jQuery droppable
+ focusOnClick: false, // Focus, although draggable cancels mousedown event (#270)
+ preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
+ preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
+ smartRevert: true, // set draggable.revert = true if drop was rejected
+ dropMarkerOffsetX: -24, // absolute position offset for .fancytree-drop-marker relatively to ..fancytree-title (icon/img near a node accepting drop)
+ dropMarkerInsertOffsetX: -16, // additional offset for drop-marker with hitMode = "before"/"after"
+ // Events (drag support)
+ dragStart: null, // Callback(sourceNode, data), return true, to enable dnd
+ dragStop: null, // Callback(sourceNode, data)
+ initHelper: null, // Callback(sourceNode, data)
+ updateHelper: null, // Callback(sourceNode, data)
+ // Events (drop support)
+ dragEnter: null, // Callback(targetNode, data)
+ dragOver: null, // Callback(targetNode, data)
+ dragExpand: null, // Callback(targetNode, data), return false to prevent autoExpand
+ dragDrop: null, // Callback(targetNode, data)
+ dragLeave: null, // Callback(targetNode, data)
+ },
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree;
+ this._superApply(arguments);
+ // issue #270: draggable eats mousedown events
+ if (tree.options.dnd.dragStart) {
+ tree.$container.on("mousedown", function (event) {
+ // if( !tree.hasFocus() && ctx.options.dnd.focusOnClick ) {
+ if (ctx.options.dnd.focusOnClick) {
+ // #270
+ var node = $.ui.fancytree.getNode(event);
+ if (node) {
+ node.debug(
+ "Re-enable focus that was prevented by jQuery UI draggable."
+ );
+ // node.setFocus();
+ // $(node.span).closest(":tabbable").focus();
+ // $(event.target).trigger("focus");
+ // $(event.target).closest(":tabbable").trigger("focus");
+ }
+ setTimeout(function () {
+ // #300
+ $(event.target).closest(":tabbable").focus();
+ }, 10);
+ }
+ });
+ }
+ _initDragAndDrop(tree);
+ },
+ /* Display drop marker according to hitMode ('after', 'before', 'over'). */
+ _setDndStatus: function (
+ sourceNode,
+ targetNode,
+ helper,
+ hitMode,
+ accept
+ ) {
+ var markerOffsetX,
+ pos,
+ markerAt = "center",
+ instData = this._local,
+ dndOpt = this.options.dnd,
+ glyphOpt = this.options.glyph,
+ $source = sourceNode ? $(sourceNode.span) : null,
+ $target = $(targetNode.span),
+ $targetTitle = $target.find("span.fancytree-title");
+
+ if (!instData.$dropMarker) {
+ instData.$dropMarker = $(
+ "<div id='fancytree-drop-marker'></div>"
+ )
+ .hide()
+ .css({ "z-index": 1000 })
+ .prependTo($(this.$div).parent());
+ // .prependTo("body");
+
+ if (glyphOpt) {
+ instData.$dropMarker.addClass(
+ glyphOpt.map._addClass + " " + glyphOpt.map.dropMarker
+ );
+ }
+ }
+ if (
+ hitMode === "after" ||
+ hitMode === "before" ||
+ hitMode === "over"
+ ) {
+ markerOffsetX = dndOpt.dropMarkerOffsetX || 0;
+ switch (hitMode) {
+ case "before":
+ markerAt = "top";
+ markerOffsetX += dndOpt.dropMarkerInsertOffsetX || 0;
+ break;
+ case "after":
+ markerAt = "bottom";
+ markerOffsetX += dndOpt.dropMarkerInsertOffsetX || 0;
+ break;
+ }
+
+ pos = {
+ my: "left" + offsetString(markerOffsetX) + " center",
+ at: "left " + markerAt,
+ of: $targetTitle,
+ };
+ if (this.options.rtl) {
+ pos.my = "right" + offsetString(-markerOffsetX) + " center";
+ pos.at = "right " + markerAt;
+ }
+ instData.$dropMarker
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropOver, hitMode === "over")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .toggleClass("fancytree-rtl", !!this.options.rtl)
+ .show()
+ .position($.ui.fancytree.fixPositionOptions(pos));
+ } else {
+ instData.$dropMarker.hide();
+ }
+ if ($source) {
+ $source
+ .toggleClass(classDropAccept, accept === true)
+ .toggleClass(classDropReject, accept === false);
+ }
+ $target
+ .toggleClass(
+ classDropTarget,
+ hitMode === "after" ||
+ hitMode === "before" ||
+ hitMode === "over"
+ )
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .toggleClass(classDropAccept, accept === true)
+ .toggleClass(classDropReject, accept === false);
+
+ helper
+ .toggleClass(classDropAccept, accept === true)
+ .toggleClass(classDropReject, accept === false);
+ },
+
+ /*
+ * Handles drag'n'drop functionality.
+ *
+ * A standard jQuery drag-and-drop process may generate these calls:
+ *
+ * start:
+ * _onDragEvent("start", sourceNode, null, event, ui, draggable);
+ * drag:
+ * _onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
+ * _onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
+ * _onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
+ * stop:
+ * _onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
+ * _onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
+ * _onDragEvent("stop", sourceNode, null, event, ui, draggable);
+ */
+ _onDragEvent: function (
+ eventName,
+ node,
+ otherNode,
+ event,
+ ui,
+ draggable
+ ) {
+ // if(eventName !== "over"){
+ // this.debug("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o", eventName, node, otherNode, this);
+ // }
+ var accept,
+ nodeOfs,
+ parentRect,
+ rect,
+ relPos,
+ relPos2,
+ enterResponse,
+ hitMode,
+ r,
+ opts = this.options,
+ dnd = opts.dnd,
+ ctx = this._makeHookContext(node, event, {
+ otherNode: otherNode,
+ ui: ui,
+ draggable: draggable,
+ }),
+ res = null,
+ self = this,
+ $nodeTag = $(node.span);
+
+ if (dnd.smartRevert) {
+ draggable.options.revert = "invalid";
+ }
+
+ switch (eventName) {
+ case "start":
+ if (node.isStatusNode()) {
+ res = false;
+ } else if (dnd.dragStart) {
+ res = dnd.dragStart(node, ctx);
+ }
+ if (res === false) {
+ this.debug("tree.dragStart() cancelled");
+ //draggable._clear();
+ // NOTE: the return value seems to be ignored (drag is not cancelled, when false is returned)
+ // TODO: call this._cancelDrag()?
+ ui.helper.trigger("mouseup").hide();
+ } else {
+ if (dnd.smartRevert) {
+ // #567, #593: fix revert position
+ // rect = node.li.getBoundingClientRect();
+ rect =
+ node[
+ ctx.tree.nodeContainerAttrName
+ ].getBoundingClientRect();
+ parentRect = $(
+ draggable.options.appendTo
+ )[0].getBoundingClientRect();
+ draggable.originalPosition.left = Math.max(
+ 0,
+ rect.left - parentRect.left
+ );
+ draggable.originalPosition.top = Math.max(
+ 0,
+ rect.top - parentRect.top
+ );
+ }
+ $nodeTag.addClass("fancytree-drag-source");
+ // Register global handlers to allow cancel
+ $(document).on(
+ "keydown.fancytree-dnd,mousedown.fancytree-dnd",
+ function (event) {
+ // node.tree.debug("dnd global event", event.type, event.which);
+ if (
+ event.type === "keydown" &&
+ event.which === $.ui.keyCode.ESCAPE
+ ) {
+ self.ext.dnd._cancelDrag();
+ } else if (event.type === "mousedown") {
+ self.ext.dnd._cancelDrag();
+ }
+ }
+ );
+ }
+ break;
+
+ case "enter":
+ if (
+ dnd.preventRecursiveMoves &&
+ node.isDescendantOf(otherNode)
+ ) {
+ r = false;
+ } else {
+ r = dnd.dragEnter ? dnd.dragEnter(node, ctx) : null;
+ }
+ if (!r) {
+ // convert null, undefined, false to false
+ res = false;
+ } else if (Array.isArray(r)) {
+ // TODO: also accept passing an object of this format directly
+ res = {
+ over: $.inArray("over", r) >= 0,
+ before: $.inArray("before", r) >= 0,
+ after: $.inArray("after", r) >= 0,
+ };
+ } else {
+ res = {
+ over: r === true || r === "over",
+ before: r === true || r === "before",
+ after: r === true || r === "after",
+ };
+ }
+ ui.helper.data("enterResponse", res);
+ // this.debug("helper.enterResponse: %o", res);
+ break;
+
+ case "over":
+ enterResponse = ui.helper.data("enterResponse");
+ hitMode = null;
+ if (enterResponse === false) {
+ // Don't call dragOver if onEnter returned false.
+ // break;
+ } else if (typeof enterResponse === "string") {
+ // Use hitMode from onEnter if provided.
+ hitMode = enterResponse;
+ } else {
+ // Calculate hitMode from relative cursor position.
+ nodeOfs = $nodeTag.offset();
+ relPos = {
+ x: event.pageX - nodeOfs.left,
+ y: event.pageY - nodeOfs.top,
+ };
+ relPos2 = {
+ x: relPos.x / $nodeTag.width(),
+ y: relPos.y / $nodeTag.height(),
+ };
+
+ if (enterResponse.after && relPos2.y > 0.75) {
+ hitMode = "after";
+ } else if (
+ !enterResponse.over &&
+ enterResponse.after &&
+ relPos2.y > 0.5
+ ) {
+ hitMode = "after";
+ } else if (enterResponse.before && relPos2.y <= 0.25) {
+ hitMode = "before";
+ } else if (
+ !enterResponse.over &&
+ enterResponse.before &&
+ relPos2.y <= 0.5
+ ) {
+ hitMode = "before";
+ } else if (enterResponse.over) {
+ hitMode = "over";
+ }
+ // Prevent no-ops like 'before source node'
+ // TODO: these are no-ops when moving nodes, but not in copy mode
+ if (dnd.preventVoidMoves) {
+ if (node === otherNode) {
+ this.debug(
+ " drop over source node prevented"
+ );
+ hitMode = null;
+ } else if (
+ hitMode === "before" &&
+ otherNode &&
+ node === otherNode.getNextSibling()
+ ) {
+ this.debug(
+ " drop after source node prevented"
+ );
+ hitMode = null;
+ } else if (
+ hitMode === "after" &&
+ otherNode &&
+ node === otherNode.getPrevSibling()
+ ) {
+ this.debug(
+ " drop before source node prevented"
+ );
+ hitMode = null;
+ } else if (
+ hitMode === "over" &&
+ otherNode &&
+ otherNode.parent === node &&
+ otherNode.isLastSibling()
+ ) {
+ this.debug(
+ " drop last child over own parent prevented"
+ );
+ hitMode = null;
+ }
+ }
+ // this.debug("hitMode: %s - %s - %s", hitMode, (node.parent === otherNode), node.isLastSibling());
+ ui.helper.data("hitMode", hitMode);
+ }
+ // Auto-expand node (only when 'over' the node, not 'before', or 'after')
+ if (
+ hitMode !== "before" &&
+ hitMode !== "after" &&
+ dnd.autoExpandMS &&
+ node.hasChildren() !== false &&
+ !node.expanded &&
+ (!dnd.dragExpand || dnd.dragExpand(node, ctx) !== false)
+ ) {
+ node.scheduleAction("expand", dnd.autoExpandMS);
+ }
+ if (hitMode && dnd.dragOver) {
+ // TODO: http://code.google.com/p/dynatree/source/detail?r=625
+ ctx.hitMode = hitMode;
+ res = dnd.dragOver(node, ctx);
+ }
+ accept = res !== false && hitMode !== null;
+ if (dnd.smartRevert) {
+ draggable.options.revert = !accept;
+ }
+ this._local._setDndStatus(
+ otherNode,
+ node,
+ ui.helper,
+ hitMode,
+ accept
+ );
+ break;
+
+ case "drop":
+ hitMode = ui.helper.data("hitMode");
+ if (hitMode && dnd.dragDrop) {
+ ctx.hitMode = hitMode;
+ dnd.dragDrop(node, ctx);
+ }
+ break;
+
+ case "leave":
+ // Cancel pending expand request
+ node.scheduleAction("cancel");
+ ui.helper.data("enterResponse", null);
+ ui.helper.data("hitMode", null);
+ this._local._setDndStatus(
+ otherNode,
+ node,
+ ui.helper,
+ "out",
+ undefined
+ );
+ if (dnd.dragLeave) {
+ dnd.dragLeave(node, ctx);
+ }
+ break;
+
+ case "stop":
+ $nodeTag.removeClass("fancytree-drag-source");
+ $(document).off(".fancytree-dnd");
+ if (dnd.dragStop) {
+ dnd.dragStop(node, ctx);
+ }
+ break;
+
+ default:
+ $.error("Unsupported drag event: " + eventName);
+ }
+ return res;
+ },
+
+ _cancelDrag: function () {
+ var dd = $.ui.ddmanager.current;
+ if (dd) {
+ dd.cancel();
+ }
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.dnd5.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.dnd5.js
new file mode 100644
index 0000000..328cef5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.dnd5.js
@@ -0,0 +1,1157 @@
+/*!
+ * jquery.fancytree.dnd5.js
+ *
+ * Drag-and-drop support (native HTML5).
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+/*
+ #TODO
+ Compatiblity when dragging between *separate* windows:
+
+ Drag from Chrome Edge FF IE11 Safari
+ To Chrome ok ok ok NO ?
+ Edge ok ok ok NO ?
+ FF ok ok ok NO ?
+ IE 11 ok ok ok ok ?
+ Safari ? ? ? ? ok
+
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var FT = $.ui.fancytree,
+ isMac = /Mac/.test(navigator.platform),
+ classDragSource = "fancytree-drag-source",
+ classDragRemove = "fancytree-drag-remove",
+ classDropAccept = "fancytree-drop-accept",
+ classDropAfter = "fancytree-drop-after",
+ classDropBefore = "fancytree-drop-before",
+ classDropOver = "fancytree-drop-over",
+ classDropReject = "fancytree-drop-reject",
+ classDropTarget = "fancytree-drop-target",
+ nodeMimeType = "application/x-fancytree-node",
+ $dropMarker = null,
+ $dragImage,
+ $extraHelper,
+ SOURCE_NODE = null,
+ SOURCE_NODE_LIST = null,
+ $sourceList = null,
+ DRAG_ENTER_RESPONSE = null,
+ // SESSION_DATA = null, // plain object passed to events as `data`
+ SUGGESTED_DROP_EFFECT = null,
+ REQUESTED_DROP_EFFECT = null,
+ REQUESTED_EFFECT_ALLOWED = null,
+ LAST_HIT_MODE = null,
+ DRAG_OVER_STAMP = null; // Time when a node entered the 'over' hitmode
+
+ /* */
+ function _clearGlobals() {
+ DRAG_ENTER_RESPONSE = null;
+ DRAG_OVER_STAMP = null;
+ REQUESTED_DROP_EFFECT = null;
+ REQUESTED_EFFECT_ALLOWED = null;
+ SUGGESTED_DROP_EFFECT = null;
+ SOURCE_NODE = null;
+ SOURCE_NODE_LIST = null;
+ if ($sourceList) {
+ $sourceList.removeClass(classDragSource + " " + classDragRemove);
+ }
+ $sourceList = null;
+ if ($dropMarker) {
+ $dropMarker.hide();
+ }
+ // Take this badge off of me - I can't use it anymore:
+ if ($extraHelper) {
+ $extraHelper.remove();
+ $extraHelper = null;
+ }
+ }
+
+ /* Convert number to string and prepend +/-; return empty string for 0.*/
+ function offsetString(n) {
+ // eslint-disable-next-line no-nested-ternary
+ return n === 0 ? "" : n > 0 ? "+" + n : "" + n;
+ }
+
+ /* Convert a dragEnter() or dragOver() response to a canonical form.
+ * Return false or plain object
+ * @param {string|object|boolean} r
+ * @return {object|false}
+ */
+ function normalizeDragEnterResponse(r) {
+ var res;
+
+ if (!r) {
+ return false;
+ }
+ if ($.isPlainObject(r)) {
+ res = {
+ over: !!r.over,
+ before: !!r.before,
+ after: !!r.after,
+ };
+ } else if (Array.isArray(r)) {
+ res = {
+ over: $.inArray("over", r) >= 0,
+ before: $.inArray("before", r) >= 0,
+ after: $.inArray("after", r) >= 0,
+ };
+ } else {
+ res = {
+ over: r === true || r === "over",
+ before: r === true || r === "before",
+ after: r === true || r === "after",
+ };
+ }
+ if (Object.keys(res).length === 0) {
+ return false;
+ }
+ // if( Object.keys(res).length === 1 ) {
+ // res.unique = res[0];
+ // }
+ return res;
+ }
+
+ /* Convert a dataTransfer.effectAllowed to a canonical form.
+ * Return false or plain object
+ * @param {string|boolean} r
+ * @return {object|false}
+ */
+ // function normalizeEffectAllowed(r) {
+ // if (!r || r === "none") {
+ // return false;
+ // }
+ // var all = r === "all",
+ // res = {
+ // copy: all || /copy/i.test(r),
+ // link: all || /link/i.test(r),
+ // move: all || /move/i.test(r),
+ // };
+
+ // return res;
+ // }
+
+ /* Implement auto scrolling when drag cursor is in top/bottom area of scroll parent. */
+ function autoScroll(tree, event) {
+ var spOfs,
+ scrollTop,
+ delta,
+ dndOpts = tree.options.dnd5,
+ sp = tree.$scrollParent[0],
+ sensitivity = dndOpts.scrollSensitivity,
+ speed = dndOpts.scrollSpeed,
+ scrolled = 0;
+
+ if (sp !== document && sp.tagName !== "HTML") {
+ spOfs = tree.$scrollParent.offset();
+ scrollTop = sp.scrollTop;
+ if (spOfs.top + sp.offsetHeight - event.pageY < sensitivity) {
+ delta =
+ sp.scrollHeight -
+ tree.$scrollParent.innerHeight() -
+ scrollTop;
+ // console.log ("sp.offsetHeight: " + sp.offsetHeight
+ // + ", spOfs.top: " + spOfs.top
+ // + ", scrollTop: " + scrollTop
+ // + ", innerHeight: " + tree.$scrollParent.innerHeight()
+ // + ", scrollHeight: " + sp.scrollHeight
+ // + ", delta: " + delta
+ // );
+ if (delta > 0) {
+ sp.scrollTop = scrolled = scrollTop + speed;
+ }
+ } else if (scrollTop > 0 && event.pageY - spOfs.top < sensitivity) {
+ sp.scrollTop = scrolled = scrollTop - speed;
+ }
+ } else {
+ scrollTop = $(document).scrollTop();
+ if (scrollTop > 0 && event.pageY - scrollTop < sensitivity) {
+ scrolled = scrollTop - speed;
+ $(document).scrollTop(scrolled);
+ } else if (
+ $(window).height() - (event.pageY - scrollTop) <
+ sensitivity
+ ) {
+ scrolled = scrollTop + speed;
+ $(document).scrollTop(scrolled);
+ }
+ }
+ if (scrolled) {
+ tree.debug("autoScroll: " + scrolled + "px");
+ }
+ return scrolled;
+ }
+
+ /* Guess dropEffect from modifier keys.
+ * Using rules suggested here:
+ * https://ux.stackexchange.com/a/83769
+ * @returns
+ * 'copy', 'link', 'move', or 'none'
+ */
+ function evalEffectModifiers(tree, event, effectDefault) {
+ var res = effectDefault;
+
+ if (isMac) {
+ if (event.metaKey && event.altKey) {
+ // Mac: [Control] + [Option]
+ res = "link";
+ } else if (event.ctrlKey) {
+ // Chrome on Mac: [Control]
+ res = "link";
+ } else if (event.metaKey) {
+ // Mac: [Command]
+ res = "move";
+ } else if (event.altKey) {
+ // Mac: [Option]
+ res = "copy";
+ }
+ } else {
+ if (event.ctrlKey) {
+ // Windows: [Ctrl]
+ res = "copy";
+ } else if (event.shiftKey) {
+ // Windows: [Shift]
+ res = "move";
+ } else if (event.altKey) {
+ // Windows: [Alt]
+ res = "link";
+ }
+ }
+ if (res !== SUGGESTED_DROP_EFFECT) {
+ tree.info(
+ "evalEffectModifiers: " +
+ event.type +
+ " - evalEffectModifiers(): " +
+ SUGGESTED_DROP_EFFECT +
+ " -> " +
+ res
+ );
+ }
+ SUGGESTED_DROP_EFFECT = res;
+ // tree.debug("evalEffectModifiers: " + res);
+ return res;
+ }
+ /*
+ * Check if the previous callback (dragEnter, dragOver, ...) has changed
+ * the `data` object and apply those settings.
+ *
+ * Safari:
+ * It seems that `dataTransfer.dropEffect` can only be set on dragStart, and will remain
+ * even if the cursor changes when [Alt] or [Ctrl] are pressed (?)
+ * Using rules suggested here:
+ * https://ux.stackexchange.com/a/83769
+ * @returns
+ * 'copy', 'link', 'move', or 'none'
+ */
+ function prepareDropEffectCallback(event, data) {
+ var tree = data.tree,
+ dataTransfer = data.dataTransfer;
+
+ if (event.type === "dragstart") {
+ data.effectAllowed = tree.options.dnd5.effectAllowed;
+ data.dropEffect = tree.options.dnd5.dropEffectDefault;
+ } else {
+ data.effectAllowed = REQUESTED_EFFECT_ALLOWED;
+ data.dropEffect = REQUESTED_DROP_EFFECT;
+ }
+ data.dropEffectSuggested = evalEffectModifiers(
+ tree,
+ event,
+ tree.options.dnd5.dropEffectDefault
+ );
+ data.isMove = data.dropEffect === "move";
+ data.files = dataTransfer.files || [];
+
+ // if (REQUESTED_EFFECT_ALLOWED !== dataTransfer.effectAllowed) {
+ // tree.warn(
+ // "prepareDropEffectCallback(" +
+ // event.type +
+ // "): dataTransfer.effectAllowed changed from " +
+ // REQUESTED_EFFECT_ALLOWED +
+ // " -> " +
+ // dataTransfer.effectAllowed
+ // );
+ // }
+ // if (REQUESTED_DROP_EFFECT !== dataTransfer.dropEffect) {
+ // tree.warn(
+ // "prepareDropEffectCallback(" +
+ // event.type +
+ // "): dataTransfer.dropEffect changed from requested " +
+ // REQUESTED_DROP_EFFECT +
+ // " to " +
+ // dataTransfer.dropEffect
+ // );
+ // }
+ }
+
+ function applyDropEffectCallback(event, data, allowDrop) {
+ var tree = data.tree,
+ dataTransfer = data.dataTransfer;
+
+ if (
+ event.type !== "dragstart" &&
+ REQUESTED_EFFECT_ALLOWED !== data.effectAllowed
+ ) {
+ tree.warn(
+ "effectAllowed should only be changed in dragstart event: " +
+ event.type +
+ ": data.effectAllowed changed from " +
+ REQUESTED_EFFECT_ALLOWED +
+ " -> " +
+ data.effectAllowed
+ );
+ }
+
+ if (allowDrop === false) {
+ tree.info("applyDropEffectCallback: allowDrop === false");
+ data.effectAllowed = "none";
+ data.dropEffect = "none";
+ }
+ // if (REQUESTED_DROP_EFFECT !== data.dropEffect) {
+ // tree.debug(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): data.dropEffect changed from previous " +
+ // REQUESTED_DROP_EFFECT +
+ // " to " +
+ // data.dropEffect
+ // );
+ // }
+
+ data.isMove = data.dropEffect === "move";
+ // data.isMove = data.dropEffectSuggested === "move";
+
+ // `effectAllowed` must only be defined in dragstart event, so we
+ // store it in a global variable for reference
+ if (event.type === "dragstart") {
+ REQUESTED_EFFECT_ALLOWED = data.effectAllowed;
+ REQUESTED_DROP_EFFECT = data.dropEffect;
+ }
+
+ // if (REQUESTED_DROP_EFFECT !== dataTransfer.dropEffect) {
+ // data.tree.info(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): dataTransfer.dropEffect changed from " +
+ // REQUESTED_DROP_EFFECT +
+ // " -> " +
+ // dataTransfer.dropEffect
+ // );
+ // }
+ dataTransfer.effectAllowed = REQUESTED_EFFECT_ALLOWED;
+ dataTransfer.dropEffect = REQUESTED_DROP_EFFECT;
+
+ // tree.debug(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): set " +
+ // dataTransfer.dropEffect +
+ // "/" +
+ // dataTransfer.effectAllowed
+ // );
+ // if (REQUESTED_DROP_EFFECT !== dataTransfer.dropEffect) {
+ // data.tree.warn(
+ // "applyDropEffectCallback(" +
+ // event.type +
+ // "): could not set dataTransfer.dropEffect to " +
+ // REQUESTED_DROP_EFFECT +
+ // ": got " +
+ // dataTransfer.dropEffect
+ // );
+ // }
+ return REQUESTED_DROP_EFFECT;
+ }
+
+ /* Handle dragover event (fired every x ms) on valid drop targets.
+ *
+ * - Auto-scroll when cursor is in border regions
+ * - Apply restrictioan like 'preventVoidMoves'
+ * - Calculate hit mode
+ * - Calculate drop effect
+ * - Trigger dragOver() callback to let user modify hit mode and drop effect
+ * - Adjust the drop marker accordingly
+ *
+ * @returns hitMode
+ */
+ function handleDragOver(event, data) {
+ // Implement auto-scrolling
+ if (data.options.dnd5.scroll) {
+ autoScroll(data.tree, event);
+ }
+ // Bail out with previous response if we get an invalid dragover
+ if (!data.node) {
+ data.tree.warn("Ignored dragover for non-node"); //, event, data);
+ return LAST_HIT_MODE;
+ }
+
+ var markerOffsetX,
+ nodeOfs,
+ pos,
+ relPosY,
+ hitMode = null,
+ tree = data.tree,
+ options = tree.options,
+ dndOpts = options.dnd5,
+ targetNode = data.node,
+ sourceNode = data.otherNode,
+ markerAt = "center",
+ $target = $(targetNode.span),
+ $targetTitle = $target.find("span.fancytree-title");
+
+ if (DRAG_ENTER_RESPONSE === false) {
+ tree.debug("Ignored dragover, since dragenter returned false.");
+ return false;
+ } else if (typeof DRAG_ENTER_RESPONSE === "string") {
+ $.error("assert failed: dragenter returned string");
+ }
+ // Calculate hitMode from relative cursor position.
+ nodeOfs = $target.offset();
+ relPosY = (event.pageY - nodeOfs.top) / $target.height();
+ if (event.pageY === undefined) {
+ tree.warn("event.pageY is undefined: see issue #1013.");
+ }
+
+ if (DRAG_ENTER_RESPONSE.after && relPosY > 0.75) {
+ hitMode = "after";
+ } else if (
+ !DRAG_ENTER_RESPONSE.over &&
+ DRAG_ENTER_RESPONSE.after &&
+ relPosY > 0.5
+ ) {
+ hitMode = "after";
+ } else if (DRAG_ENTER_RESPONSE.before && relPosY <= 0.25) {
+ hitMode = "before";
+ } else if (
+ !DRAG_ENTER_RESPONSE.over &&
+ DRAG_ENTER_RESPONSE.before &&
+ relPosY <= 0.5
+ ) {
+ hitMode = "before";
+ } else if (DRAG_ENTER_RESPONSE.over) {
+ hitMode = "over";
+ }
+ // Prevent no-ops like 'before source node'
+ // TODO: these are no-ops when moving nodes, but not in copy mode
+ if (dndOpts.preventVoidMoves && data.dropEffect === "move") {
+ if (targetNode === sourceNode) {
+ targetNode.debug("Drop over source node prevented.");
+ hitMode = null;
+ } else if (
+ hitMode === "before" &&
+ sourceNode &&
+ targetNode === sourceNode.getNextSibling()
+ ) {
+ targetNode.debug("Drop after source node prevented.");
+ hitMode = null;
+ } else if (
+ hitMode === "after" &&
+ sourceNode &&
+ targetNode === sourceNode.getPrevSibling()
+ ) {
+ targetNode.debug("Drop before source node prevented.");
+ hitMode = null;
+ } else if (
+ hitMode === "over" &&
+ sourceNode &&
+ sourceNode.parent === targetNode &&
+ sourceNode.isLastSibling()
+ ) {
+ targetNode.debug("Drop last child over own parent prevented.");
+ hitMode = null;
+ }
+ }
+ // Let callback modify the calculated hitMode
+ data.hitMode = hitMode;
+ if (hitMode && dndOpts.dragOver) {
+ prepareDropEffectCallback(event, data);
+ dndOpts.dragOver(targetNode, data);
+ var allowDrop = !!hitMode;
+ applyDropEffectCallback(event, data, allowDrop);
+ hitMode = data.hitMode;
+ }
+ LAST_HIT_MODE = hitMode;
+ //
+ if (hitMode === "after" || hitMode === "before" || hitMode === "over") {
+ markerOffsetX = dndOpts.dropMarkerOffsetX || 0;
+ switch (hitMode) {
+ case "before":
+ markerAt = "top";
+ markerOffsetX += dndOpts.dropMarkerInsertOffsetX || 0;
+ break;
+ case "after":
+ markerAt = "bottom";
+ markerOffsetX += dndOpts.dropMarkerInsertOffsetX || 0;
+ break;
+ }
+
+ pos = {
+ my: "left" + offsetString(markerOffsetX) + " center",
+ at: "left " + markerAt,
+ of: $targetTitle,
+ };
+ if (options.rtl) {
+ pos.my = "right" + offsetString(-markerOffsetX) + " center";
+ pos.at = "right " + markerAt;
+ // console.log("rtl", pos);
+ }
+ $dropMarker
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropOver, hitMode === "over")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .show()
+ .position(FT.fixPositionOptions(pos));
+ } else {
+ $dropMarker.hide();
+ // console.log("hide dropmarker")
+ }
+
+ $(targetNode.span)
+ .toggleClass(
+ classDropTarget,
+ hitMode === "after" ||
+ hitMode === "before" ||
+ hitMode === "over"
+ )
+ .toggleClass(classDropAfter, hitMode === "after")
+ .toggleClass(classDropBefore, hitMode === "before")
+ .toggleClass(classDropAccept, hitMode === "over")
+ .toggleClass(classDropReject, hitMode === false);
+
+ return hitMode;
+ }
+
+ /*
+ * Handle dragstart drag dragend events on the container
+ */
+ function onDragEvent(event) {
+ var json,
+ tree = this,
+ dndOpts = tree.options.dnd5,
+ node = FT.getNode(event),
+ dataTransfer =
+ event.dataTransfer || event.originalEvent.dataTransfer,
+ data = {
+ tree: tree,
+ node: node,
+ options: tree.options,
+ originalEvent: event.originalEvent,
+ widget: tree.widget,
+ dataTransfer: dataTransfer,
+ useDefaultImage: true,
+ dropEffect: undefined,
+ dropEffectSuggested: undefined,
+ effectAllowed: undefined, // set by dragstart
+ files: undefined, // only for drop events
+ isCancelled: undefined, // set by dragend
+ isMove: undefined,
+ };
+
+ switch (event.type) {
+ case "dragstart":
+ if (!node) {
+ tree.info("Ignored dragstart on a non-node.");
+ return false;
+ }
+ // Store current source node in different formats
+ SOURCE_NODE = node;
+
+ // Also optionally store selected nodes
+ if (dndOpts.multiSource === false) {
+ SOURCE_NODE_LIST = [node];
+ } else if (dndOpts.multiSource === true) {
+ if (node.isSelected()) {
+ SOURCE_NODE_LIST = tree.getSelectedNodes();
+ } else {
+ SOURCE_NODE_LIST = [node];
+ }
+ } else {
+ SOURCE_NODE_LIST = dndOpts.multiSource(node, data);
+ }
+ // Cache as array of jQuery objects for faster access:
+ $sourceList = $(
+ $.map(SOURCE_NODE_LIST, function (n) {
+ return n.span;
+ })
+ );
+ // Set visual feedback
+ $sourceList.addClass(classDragSource);
+
+ // Set payload
+ // Note:
+ // Transfer data is only accessible on dragstart and drop!
+ // For all other events the formats and kinds in the drag
+ // data store list of items representing dragged data can be
+ // enumerated, but the data itself is unavailable and no new
+ // data can be added.
+ var nodeData = node.toDict(true, dndOpts.sourceCopyHook);
+ nodeData.treeId = node.tree._id;
+ json = JSON.stringify(nodeData);
+ try {
+ dataTransfer.setData(nodeMimeType, json);
+ dataTransfer.setData("text/html", $(node.span).html());
+ dataTransfer.setData("text/plain", node.title);
+ } catch (ex) {
+ // IE only accepts 'text' type
+ tree.warn(
+ "Could not set data (IE only accepts 'text') - " + ex
+ );
+ }
+ // We always need to set the 'text' type if we want to drag
+ // Because IE 11 only accepts this single type.
+ // If we pass JSON here, IE can can access all node properties,
+ // even when the source lives in another window. (D'n'd inside
+ // the same window will always work.)
+ // The drawback is, that in this case ALL browsers will see
+ // the JSON representation as 'text', so dragging
+ // to a text field will insert the JSON string instead of
+ // the node title.
+ if (dndOpts.setTextTypeJson) {
+ dataTransfer.setData("text", json);
+ } else {
+ dataTransfer.setData("text", node.title);
+ }
+
+ // Set the allowed drag modes (combinations of move, copy, and link)
+ // (effectAllowed can only be set in the dragstart event.)
+ // This can be overridden in the dragStart() callback
+ prepareDropEffectCallback(event, data);
+
+ // Let user cancel or modify above settings
+ // Realize potential changes by previous callback
+ if (dndOpts.dragStart(node, data) === false) {
+ // Cancel dragging
+ // dataTransfer.dropEffect = "none";
+ _clearGlobals();
+ return false;
+ }
+ applyDropEffectCallback(event, data);
+
+ // Unless user set `data.useDefaultImage` to false in dragStart,
+ // generata a default drag image now:
+ $extraHelper = null;
+
+ if (data.useDefaultImage) {
+ // Set the title as drag image (otherwise it would contain the expander)
+ $dragImage = $(node.span).find(".fancytree-title");
+
+ if (SOURCE_NODE_LIST && SOURCE_NODE_LIST.length > 1) {
+ // Add a counter badge to node title if dragging more than one node.
+ // We want this, because the element that is used as drag image
+ // must be *visible* in the DOM, so we cannot create some hidden
+ // custom markup.
+ // See https://kryogenix.org/code/browser/custom-drag-image.html
+ // Also, since IE 11 and Edge don't support setDragImage() alltogether,
+ // it gives som feedback to the user.
+ // The badge will be removed later on drag end.
+ $extraHelper = $(
+ "<span class='fancytree-childcounter'/>"
+ )
+ .text("+" + (SOURCE_NODE_LIST.length - 1))
+ .appendTo($dragImage);
+ }
+ if (dataTransfer.setDragImage) {
+ // IE 11 and Edge do not support this
+ dataTransfer.setDragImage($dragImage[0], -10, -10);
+ }
+ }
+ return true;
+
+ case "drag":
+ // Called every few milliseconds (no matter if the
+ // cursor is over a valid drop target)
+ // data.tree.info("drag", SOURCE_NODE)
+ prepareDropEffectCallback(event, data);
+ dndOpts.dragDrag(node, data);
+ applyDropEffectCallback(event, data);
+
+ $sourceList.toggleClass(classDragRemove, data.isMove);
+ break;
+
+ case "dragend":
+ // Called at the end of a d'n'd process (after drop)
+ // Note caveat: If drop removed the dragged source element,
+ // we may not get this event, since the target does not exist
+ // anymore
+ prepareDropEffectCallback(event, data);
+
+ _clearGlobals();
+
+ data.isCancelled = !LAST_HIT_MODE;
+ dndOpts.dragEnd(node, data, !LAST_HIT_MODE);
+ // applyDropEffectCallback(event, data);
+ break;
+ }
+ }
+ /*
+ * Handle dragenter dragover dragleave drop events on the container
+ */
+ function onDropEvent(event) {
+ var json,
+ allowAutoExpand,
+ nodeData,
+ isSourceFtNode,
+ r,
+ res,
+ tree = this,
+ dndOpts = tree.options.dnd5,
+ allowDrop = null,
+ node = FT.getNode(event),
+ dataTransfer =
+ event.dataTransfer || event.originalEvent.dataTransfer,
+ data = {
+ tree: tree,
+ node: node,
+ options: tree.options,
+ originalEvent: event.originalEvent,
+ widget: tree.widget,
+ hitMode: DRAG_ENTER_RESPONSE,
+ dataTransfer: dataTransfer,
+ otherNode: SOURCE_NODE || null,
+ otherNodeList: SOURCE_NODE_LIST || null,
+ otherNodeData: null, // set by drop event
+ useDefaultImage: true,
+ dropEffect: undefined,
+ dropEffectSuggested: undefined,
+ effectAllowed: undefined, // set by dragstart
+ files: null, // list of File objects (may be [])
+ isCancelled: undefined, // set by drop event
+ isMove: undefined,
+ };
+
+ // data.isMove = dropEffect === "move";
+
+ switch (event.type) {
+ case "dragenter":
+ // The dragenter event is fired when a dragged element or
+ // text selection enters a valid drop target.
+
+ DRAG_OVER_STAMP = null;
+ if (!node) {
+ // Sometimes we get dragenter for the container element
+ tree.debug(
+ "Ignore non-node " +
+ event.type +
+ ": " +
+ event.target.tagName +
+ "." +
+ event.target.className
+ );
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ }
+
+ $(node.span)
+ .addClass(classDropOver)
+ .removeClass(classDropAccept + " " + classDropReject);
+
+ // Data is only readable in the dragstart and drop event,
+ // but we can check for the type:
+ isSourceFtNode =
+ $.inArray(nodeMimeType, dataTransfer.types) >= 0;
+
+ if (dndOpts.preventNonNodes && !isSourceFtNode) {
+ node.debug("Reject dropping a non-node.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (
+ dndOpts.preventForeignNodes &&
+ (!SOURCE_NODE || SOURCE_NODE.tree !== node.tree)
+ ) {
+ node.debug("Reject dropping a foreign node.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (
+ dndOpts.preventSameParent &&
+ data.otherNode &&
+ data.otherNode.tree === node.tree &&
+ node.parent === data.otherNode.parent
+ ) {
+ node.debug("Reject dropping as sibling (same parent).");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (
+ dndOpts.preventRecursion &&
+ data.otherNode &&
+ data.otherNode.tree === node.tree &&
+ node.isDescendantOf(data.otherNode)
+ ) {
+ node.debug("Reject dropping below own ancestor.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ } else if (dndOpts.preventLazyParents && !node.isLoaded()) {
+ node.warn("Drop over unloaded target node prevented.");
+ DRAG_ENTER_RESPONSE = false;
+ break;
+ }
+ $dropMarker.show();
+
+ // Call dragEnter() to figure out if (and where) dropping is allowed
+ prepareDropEffectCallback(event, data);
+ r = dndOpts.dragEnter(node, data);
+
+ res = normalizeDragEnterResponse(r);
+ // alert("res:" + JSON.stringify(res))
+ DRAG_ENTER_RESPONSE = res;
+
+ allowDrop = res && (res.over || res.before || res.after);
+
+ applyDropEffectCallback(event, data, allowDrop);
+ break;
+
+ case "dragover":
+ if (!node) {
+ tree.debug(
+ "Ignore non-node " +
+ event.type +
+ ": " +
+ event.target.tagName +
+ "." +
+ event.target.className
+ );
+ break;
+ }
+ // The dragover event is fired when an element or text
+ // selection is being dragged over a valid drop target
+ // (every few hundred milliseconds).
+ // tree.debug(
+ // event.type +
+ // ": dropEffect: " +
+ // dataTransfer.dropEffect
+ // );
+ prepareDropEffectCallback(event, data);
+ LAST_HIT_MODE = handleDragOver(event, data);
+
+ // The flag controls the preventDefault() below:
+ allowDrop = !!LAST_HIT_MODE;
+ allowAutoExpand =
+ LAST_HIT_MODE === "over" || LAST_HIT_MODE === false;
+
+ if (
+ allowAutoExpand &&
+ !node.expanded &&
+ node.hasChildren() !== false
+ ) {
+ if (!DRAG_OVER_STAMP) {
+ DRAG_OVER_STAMP = Date.now();
+ } else if (
+ dndOpts.autoExpandMS &&
+ Date.now() - DRAG_OVER_STAMP > dndOpts.autoExpandMS &&
+ !node.isLoading() &&
+ (!dndOpts.dragExpand ||
+ dndOpts.dragExpand(node, data) !== false)
+ ) {
+ node.setExpanded();
+ }
+ } else {
+ DRAG_OVER_STAMP = null;
+ }
+ break;
+
+ case "dragleave":
+ // NOTE: dragleave is fired AFTER the dragenter event of the
+ // FOLLOWING element.
+ if (!node) {
+ tree.debug(
+ "Ignore non-node " +
+ event.type +
+ ": " +
+ event.target.tagName +
+ "." +
+ event.target.className
+ );
+ break;
+ }
+ if (!$(node.span).hasClass(classDropOver)) {
+ node.debug("Ignore dragleave (multi).");
+ break;
+ }
+ $(node.span).removeClass(
+ classDropOver +
+ " " +
+ classDropAccept +
+ " " +
+ classDropReject
+ );
+ node.scheduleAction("cancel");
+ dndOpts.dragLeave(node, data);
+ $dropMarker.hide();
+ break;
+
+ case "drop":
+ // Data is only readable in the (dragstart and) drop event:
+
+ if ($.inArray(nodeMimeType, dataTransfer.types) >= 0) {
+ nodeData = dataTransfer.getData(nodeMimeType);
+ tree.info(
+ event.type +
+ ": getData('application/x-fancytree-node'): '" +
+ nodeData +
+ "'"
+ );
+ }
+ if (!nodeData) {
+ // 1. Source is not a Fancytree node, or
+ // 2. If the FT mime type was set, but returns '', this
+ // is probably IE 11 (which only supports 'text')
+ nodeData = dataTransfer.getData("text");
+ tree.info(
+ event.type + ": getData('text'): '" + nodeData + "'"
+ );
+ }
+ if (nodeData) {
+ try {
+ // 'text' type may contain JSON if IE is involved
+ // and setTextTypeJson option was set
+ json = JSON.parse(nodeData);
+ if (json.title !== undefined) {
+ data.otherNodeData = json;
+ }
+ } catch (ex) {
+ // assume 'text' type contains plain text, so `otherNodeData`
+ // should not be set
+ }
+ }
+ tree.debug(
+ event.type +
+ ": nodeData: '" +
+ nodeData +
+ "', otherNodeData: ",
+ data.otherNodeData
+ );
+
+ $(node.span).removeClass(
+ classDropOver +
+ " " +
+ classDropAccept +
+ " " +
+ classDropReject
+ );
+
+ // Let user implement the actual drop operation
+ data.hitMode = LAST_HIT_MODE;
+ prepareDropEffectCallback(event, data, !LAST_HIT_MODE);
+ data.isCancelled = !LAST_HIT_MODE;
+
+ var orgSourceElem = SOURCE_NODE && SOURCE_NODE.span,
+ orgSourceTree = SOURCE_NODE && SOURCE_NODE.tree;
+
+ dndOpts.dragDrop(node, data);
+ // applyDropEffectCallback(event, data);
+
+ // Prevent browser's default drop handling, i.e. open as link, ...
+ event.preventDefault();
+
+ if (orgSourceElem && !document.body.contains(orgSourceElem)) {
+ // The drop handler removed the original drag source from
+ // the DOM, so the dragend event will probaly not fire.
+ if (orgSourceTree === tree) {
+ tree.debug(
+ "Drop handler removed source element: generating dragEnd."
+ );
+ dndOpts.dragEnd(SOURCE_NODE, data);
+ } else {
+ tree.warn(
+ "Drop handler removed source element: dragend event may be lost."
+ );
+ }
+ }
+
+ _clearGlobals();
+
+ break;
+ }
+ // Dnd API madness: we must PREVENT default handling to enable dropping
+ if (allowDrop) {
+ event.preventDefault();
+ return false;
+ }
+ }
+
+ /** [ext-dnd5] Return a Fancytree instance, from element, index, event, or jQueryObject.
+ *
+ * @returns {FancytreeNode[]} List of nodes (empty if no drag operation)
+ * @example
+ * $.ui.fancytree.getDragNodeList();
+ *
+ * @alias Fancytree_Static#getDragNodeList
+ * @requires jquery.fancytree.dnd5.js
+ * @since 2.31
+ */
+ $.ui.fancytree.getDragNodeList = function () {
+ return SOURCE_NODE_LIST || [];
+ };
+
+ /** [ext-dnd5] Return the FancytreeNode that is currently being dragged.
+ *
+ * If multiple nodes are dragged, only the first is returned.
+ *
+ * @returns {FancytreeNode | null} dragged nodes or null if no drag operation
+ * @example
+ * $.ui.fancytree.getDragNode();
+ *
+ * @alias Fancytree_Static#getDragNode
+ * @requires jquery.fancytree.dnd5.js
+ * @since 2.31
+ */
+ $.ui.fancytree.getDragNode = function () {
+ return SOURCE_NODE;
+ };
+
+ /******************************************************************************
+ *
+ */
+
+ $.ui.fancytree.registerExtension({
+ name: "dnd5",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ autoExpandMS: 1500, // Expand nodes after n milliseconds of hovering
+ dropMarkerInsertOffsetX: -16, // Additional offset for drop-marker with hitMode = "before"/"after"
+ dropMarkerOffsetX: -24, // Absolute position offset for .fancytree-drop-marker relatively to ..fancytree-title (icon/img near a node accepting drop)
+ // #1021 `document.body` is not available yet
+ dropMarkerParent: "body", // Root Container used for drop marker (could be a shadow root)
+ multiSource: false, // true: Drag multiple (i.e. selected) nodes. Also a callback() is allowed
+ effectAllowed: "all", // Restrict the possible cursor shapes and modifier operations (can also be set in the dragStart event)
+ // dropEffect: "auto", // 'copy'|'link'|'move'|'auto'(calculate from `effectAllowed`+modifier keys) or callback(node, data) that returns such string.
+ dropEffectDefault: "move", // Default dropEffect ('copy', 'link', or 'move') when no modifier is pressed (overide in dragDrag, dragOver).
+ preventForeignNodes: false, // Prevent dropping nodes from different Fancytrees
+ preventLazyParents: true, // Prevent dropping items on unloaded lazy Fancytree nodes
+ preventNonNodes: false, // Prevent dropping items other than Fancytree nodes
+ preventRecursion: true, // Prevent dropping nodes on own descendants
+ preventSameParent: false, // Prevent dropping nodes under same direct parent
+ preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
+ scroll: true, // Enable auto-scrolling while dragging
+ scrollSensitivity: 20, // Active top/bottom margin in pixel
+ scrollSpeed: 5, // Pixel per event
+ setTextTypeJson: false, // Allow dragging of nodes to different IE windows
+ sourceCopyHook: null, // Optional callback passed to `toDict` on dragStart @since 2.38
+ // Events (drag support)
+ dragStart: null, // Callback(sourceNode, data), return true, to enable dnd drag
+ dragDrag: $.noop, // Callback(sourceNode, data)
+ dragEnd: $.noop, // Callback(sourceNode, data)
+ // Events (drop support)
+ dragEnter: null, // Callback(targetNode, data), return true, to enable dnd drop
+ dragOver: $.noop, // Callback(targetNode, data)
+ dragExpand: $.noop, // Callback(targetNode, data), return false to prevent autoExpand
+ dragDrop: $.noop, // Callback(targetNode, data)
+ dragLeave: $.noop, // Callback(targetNode, data)
+ },
+
+ treeInit: function (ctx) {
+ var $temp,
+ tree = ctx.tree,
+ opts = ctx.options,
+ glyph = opts.glyph || null,
+ dndOpts = opts.dnd5;
+
+ if ($.inArray("dnd", opts.extensions) >= 0) {
+ $.error("Extensions 'dnd' and 'dnd5' are mutually exclusive.");
+ }
+ if (dndOpts.dragStop) {
+ $.error(
+ "dragStop is not used by ext-dnd5. Use dragEnd instead."
+ );
+ }
+ if (dndOpts.preventRecursiveMoves != null) {
+ $.error(
+ "preventRecursiveMoves was renamed to preventRecursion."
+ );
+ }
+
+ // Implement `opts.createNode` event to add the 'draggable' attribute
+ // #680: this must happen before calling super.treeInit()
+ if (dndOpts.dragStart) {
+ FT.overrideMethod(
+ ctx.options,
+ "createNode",
+ function (event, data) {
+ // Default processing if any
+ this._super.apply(this, arguments);
+ if (data.node.span) {
+ data.node.span.draggable = true;
+ } else {
+ data.node.warn(
+ "Cannot add `draggable`: no span tag"
+ );
+ }
+ }
+ );
+ }
+ this._superApply(arguments);
+
+ this.$container.addClass("fancytree-ext-dnd5");
+
+ // Store the current scroll parent, which may be the tree
+ // container, any enclosing div, or the document.
+ // #761: scrollParent() always needs a container child
+ $temp = $("<span>").appendTo(this.$container);
+ this.$scrollParent = $temp.scrollParent();
+ $temp.remove();
+
+ $dropMarker = $("#fancytree-drop-marker");
+ if (!$dropMarker.length) {
+ $dropMarker = $("<div id='fancytree-drop-marker'></div>")
+ .hide()
+ .css({
+ "z-index": 1000,
+ // Drop marker should not steal dragenter/dragover events:
+ "pointer-events": "none",
+ })
+ .prependTo(dndOpts.dropMarkerParent);
+ if (glyph) {
+ FT.setSpanIcon(
+ $dropMarker[0],
+ glyph.map._addClass,
+ glyph.map.dropMarker
+ );
+ }
+ }
+ $dropMarker.toggleClass("fancytree-rtl", !!opts.rtl);
+
+ // Enable drag support if dragStart() is specified:
+ if (dndOpts.dragStart) {
+ // Bind drag event handlers
+ tree.$container.on(
+ "dragstart drag dragend",
+ onDragEvent.bind(tree)
+ );
+ }
+ // Enable drop support if dragEnter() is specified:
+ if (dndOpts.dragEnter) {
+ // Bind drop event handlers
+ tree.$container.on(
+ "dragenter dragover dragleave drop",
+ onDropEvent.bind(tree)
+ );
+ }
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.edit.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.edit.js
new file mode 100644
index 0000000..7ccd5df
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.edit.js
@@ -0,0 +1,403 @@
+/*!
+ * jquery.fancytree.edit.js
+ *
+ * Make node titles editable.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ var isMac = /Mac/.test(navigator.platform),
+ escapeHtml = $.ui.fancytree.escapeHtml,
+ trim = $.ui.fancytree.trim,
+ unescapeHtml = $.ui.fancytree.unescapeHtml;
+
+ /**
+ * [ext-edit] Start inline editing of current node title.
+ *
+ * @alias FancytreeNode#editStart
+ * @requires Fancytree
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.editStart = function () {
+ var $input,
+ node = this,
+ tree = this.tree,
+ local = tree.ext.edit,
+ instOpts = tree.options.edit,
+ $title = $(".fancytree-title", node.span),
+ eventData = {
+ node: node,
+ tree: tree,
+ options: tree.options,
+ isNew: $(node[tree.statusClassPropName]).hasClass(
+ "fancytree-edit-new"
+ ),
+ orgTitle: node.title,
+ input: null,
+ dirty: false,
+ };
+
+ // beforeEdit may want to modify the title before editing
+ if (
+ instOpts.beforeEdit.call(
+ node,
+ { type: "beforeEdit" },
+ eventData
+ ) === false
+ ) {
+ return false;
+ }
+ $.ui.fancytree.assert(!local.currentNode, "recursive edit");
+ local.currentNode = this;
+ local.eventData = eventData;
+
+ // Disable standard Fancytree mouse- and key handling
+ tree.widget._unbind();
+
+ local.lastDraggableAttrValue = node.span.draggable;
+ if (local.lastDraggableAttrValue) {
+ node.span.draggable = false;
+ }
+
+ // #116: ext-dnd prevents the blur event, so we have to catch outer clicks
+ $(document).on("mousedown.fancytree-edit", function (event) {
+ if (!$(event.target).hasClass("fancytree-edit-input")) {
+ node.editEnd(true, event);
+ }
+ });
+
+ // Replace node with <input>
+ $input = $("<input />", {
+ class: "fancytree-edit-input",
+ type: "text",
+ value: tree.options.escapeTitles
+ ? eventData.orgTitle
+ : unescapeHtml(eventData.orgTitle),
+ });
+ local.eventData.input = $input;
+ if (instOpts.adjustWidthOfs != null) {
+ $input.width($title.width() + instOpts.adjustWidthOfs);
+ }
+ if (instOpts.inputCss != null) {
+ $input.css(instOpts.inputCss);
+ }
+
+ $title.html($input);
+
+ // Focus <input> and bind keyboard handler
+ $input
+ .focus()
+ .change(function (event) {
+ $input.addClass("fancytree-edit-dirty");
+ })
+ .on("keydown", function (event) {
+ switch (event.which) {
+ case $.ui.keyCode.ESCAPE:
+ node.editEnd(false, event);
+ break;
+ case $.ui.keyCode.ENTER:
+ node.editEnd(true, event);
+ return false; // so we don't start editmode on Mac
+ }
+ event.stopPropagation();
+ })
+ .blur(function (event) {
+ return node.editEnd(true, event);
+ });
+
+ instOpts.edit.call(node, { type: "edit" }, eventData);
+ };
+
+ /**
+ * [ext-edit] Stop inline editing.
+ * @param {Boolean} [applyChanges=false] false: cancel edit, true: save (if modified)
+ * @alias FancytreeNode#editEnd
+ * @requires jquery.fancytree.edit.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.editEnd = function (
+ applyChanges,
+ _event
+ ) {
+ var newVal,
+ node = this,
+ tree = this.tree,
+ local = tree.ext.edit,
+ eventData = local.eventData,
+ instOpts = tree.options.edit,
+ $title = $(".fancytree-title", node.span),
+ $input = $title.find("input.fancytree-edit-input");
+
+ if (instOpts.trim) {
+ $input.val(trim($input.val()));
+ }
+ newVal = $input.val();
+
+ eventData.dirty = newVal !== node.title;
+ eventData.originalEvent = _event;
+
+ // Find out, if saving is required
+ if (applyChanges === false) {
+ // If true/false was passed, honor this (except in rename mode, if unchanged)
+ eventData.save = false;
+ } else if (eventData.isNew) {
+ // In create mode, we save everything, except for empty text
+ eventData.save = newVal !== "";
+ } else {
+ // In rename mode, we save everyting, except for empty or unchanged text
+ eventData.save = eventData.dirty && newVal !== "";
+ }
+ // Allow to break (keep editor open), modify input, or re-define data.save
+ if (
+ instOpts.beforeClose.call(
+ node,
+ { type: "beforeClose" },
+ eventData
+ ) === false
+ ) {
+ return false;
+ }
+ if (
+ eventData.save &&
+ instOpts.save.call(node, { type: "save" }, eventData) === false
+ ) {
+ return false;
+ }
+ $input.removeClass("fancytree-edit-dirty").off();
+ // Unbind outer-click handler
+ $(document).off(".fancytree-edit");
+
+ if (eventData.save) {
+ // # 171: escape user input (not required if global escaping is on)
+ node.setTitle(
+ tree.options.escapeTitles ? newVal : escapeHtml(newVal)
+ );
+ node.setFocus();
+ } else {
+ if (eventData.isNew) {
+ node.remove();
+ node = eventData.node = null;
+ local.relatedNode.setFocus();
+ } else {
+ node.renderTitle();
+ node.setFocus();
+ }
+ }
+ local.eventData = null;
+ local.currentNode = null;
+ local.relatedNode = null;
+ // Re-enable mouse and keyboard handling
+ tree.widget._bind();
+
+ if (node && local.lastDraggableAttrValue) {
+ node.span.draggable = true;
+ }
+
+ // Set keyboard focus, even if setFocus() claims 'nothing to do'
+ tree.$container.get(0).focus({ preventScroll: true });
+ eventData.input = null;
+ instOpts.close.call(node, { type: "close" }, eventData);
+ return true;
+ };
+
+ /**
+ * [ext-edit] Create a new child or sibling node and start edit mode.
+ *
+ * @param {String} [mode='child'] 'before', 'after', or 'child'
+ * @param {Object} [init] NodeData (or simple title string)
+ * @alias FancytreeNode#editCreateNode
+ * @requires jquery.fancytree.edit.js
+ * @since 2.4
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode = function (
+ mode,
+ init
+ ) {
+ var newNode,
+ tree = this.tree,
+ self = this;
+
+ mode = mode || "child";
+ if (init == null) {
+ init = { title: "" };
+ } else if (typeof init === "string") {
+ init = { title: init };
+ } else {
+ $.ui.fancytree.assert($.isPlainObject(init));
+ }
+ // Make sure node is expanded (and loaded) in 'child' mode
+ if (
+ mode === "child" &&
+ !this.isExpanded() &&
+ this.hasChildren() !== false
+ ) {
+ this.setExpanded().done(function () {
+ self.editCreateNode(mode, init);
+ });
+ return;
+ }
+ newNode = this.addNode(init, mode);
+
+ // #644: Don't filter new nodes.
+ newNode.match = true;
+ $(newNode[tree.statusClassPropName])
+ .removeClass("fancytree-hide")
+ .addClass("fancytree-match");
+
+ newNode.makeVisible(/*{noAnimation: true}*/).done(function () {
+ $(newNode[tree.statusClassPropName]).addClass("fancytree-edit-new");
+ self.tree.ext.edit.relatedNode = self;
+ newNode.editStart();
+ });
+ };
+
+ /**
+ * [ext-edit] Check if any node in this tree in edit mode.
+ *
+ * @returns {FancytreeNode | null}
+ * @alias Fancytree#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.isEditing = function () {
+ return this.ext.edit ? this.ext.edit.currentNode : null;
+ };
+
+ /**
+ * [ext-edit] Check if this node is in edit mode.
+ * @returns {Boolean} true if node is currently beeing edited
+ * @alias FancytreeNode#isEditing
+ * @requires jquery.fancytree.edit.js
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.isEditing = function () {
+ return this.tree.ext.edit
+ ? this.tree.ext.edit.currentNode === this
+ : false;
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "edit",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ adjustWidthOfs: 4, // null: don't adjust input size to content
+ allowEmpty: false, // Prevent empty input
+ inputCss: { minWidth: "3em" },
+ // triggerCancel: ["esc", "tab", "click"],
+ triggerStart: ["f2", "mac+enter", "shift+click"],
+ trim: true, // Trim whitespace before save
+ // Events:
+ beforeClose: $.noop, // Return false to prevent cancel/save (data.input is available)
+ beforeEdit: $.noop, // Return false to prevent edit mode
+ close: $.noop, // Editor was removed
+ edit: $.noop, // Editor was opened (available as data.input)
+ // keypress: $.noop, // Not yet implemented
+ save: $.noop, // Save data.input.val() or return false to keep editor open
+ },
+ // Local attributes
+ currentNode: null,
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree;
+
+ this._superApply(arguments);
+
+ this.$container
+ .addClass("fancytree-ext-edit")
+ .on("fancytreebeforeupdateviewport", function (event, data) {
+ var editNode = tree.isEditing();
+ // When scrolling, the TR may be re-used by another node, so the
+ // active cell marker an
+ if (editNode) {
+ editNode.info("Cancel edit due to scroll event.");
+ editNode.editEnd(false, event);
+ }
+ });
+ },
+ nodeClick: function (ctx) {
+ var eventStr = $.ui.fancytree.eventToString(ctx.originalEvent),
+ triggerStart = ctx.options.edit.triggerStart;
+
+ if (
+ eventStr === "shift+click" &&
+ $.inArray("shift+click", triggerStart) >= 0
+ ) {
+ if (ctx.originalEvent.shiftKey) {
+ ctx.node.editStart();
+ return false;
+ }
+ }
+ if (
+ eventStr === "click" &&
+ $.inArray("clickActive", triggerStart) >= 0
+ ) {
+ // Only when click was inside title text (not aynwhere else in the row)
+ if (
+ ctx.node.isActive() &&
+ !ctx.node.isEditing() &&
+ $(ctx.originalEvent.target).hasClass("fancytree-title")
+ ) {
+ ctx.node.editStart();
+ return false;
+ }
+ }
+ return this._superApply(arguments);
+ },
+ nodeDblclick: function (ctx) {
+ if ($.inArray("dblclick", ctx.options.edit.triggerStart) >= 0) {
+ ctx.node.editStart();
+ return false;
+ }
+ return this._superApply(arguments);
+ },
+ nodeKeydown: function (ctx) {
+ switch (ctx.originalEvent.which) {
+ case 113: // [F2]
+ if ($.inArray("f2", ctx.options.edit.triggerStart) >= 0) {
+ ctx.node.editStart();
+ return false;
+ }
+ break;
+ case $.ui.keyCode.ENTER:
+ if (
+ $.inArray("mac+enter", ctx.options.edit.triggerStart) >=
+ 0 &&
+ isMac
+ ) {
+ ctx.node.editStart();
+ return false;
+ }
+ break;
+ }
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.filter.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.filter.js
new file mode 100644
index 0000000..5eb2e5e
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.filter.js
@@ -0,0 +1,549 @@
+/*!
+ * jquery.fancytree.filter.js
+ *
+ * Remove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ var KeyNoData = "__not_found__",
+ escapeHtml = $.ui.fancytree.escapeHtml,
+ exoticStartChar = "\uFFF7",
+ exoticEndChar = "\uFFF8";
+ function _escapeRegex(str) {
+ return (str + "").replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
+ }
+
+ function extractHtmlText(s) {
+ if (s.indexOf(">") >= 0) {
+ return $("<div/>").html(s).text();
+ }
+ return s;
+ }
+
+ /**
+ * @description Marks the matching charecters of `text` either by `mark` or
+ * by exotic*Chars (if `escapeTitles` is `true`) based on `regexMatchArray`
+ * which is an array of matching groups.
+ * @param {string} text
+ * @param {RegExpMatchArray} regexMatchArray
+ */
+ function _markFuzzyMatchedChars(text, regexMatchArray, escapeTitles) {
+ // It is extremely infuriating that we can not use `let` or `const` or arrow functions.
+ // Damn you IE!!!
+ var matchingIndices = [];
+ // get the indices of matched characters (Iterate through `RegExpMatchArray`)
+ for (
+ var _matchingArrIdx = 1;
+ _matchingArrIdx < regexMatchArray.length;
+ _matchingArrIdx++
+ ) {
+ var _mIdx =
+ // get matching char index by cumulatively adding
+ // the matched group length
+ regexMatchArray[_matchingArrIdx].length +
+ (_matchingArrIdx === 1 ? 0 : 1) +
+ (matchingIndices[matchingIndices.length - 1] || 0);
+ matchingIndices.push(_mIdx);
+ }
+ // Map each `text` char to its position and store in `textPoses`.
+ var textPoses = text.split("");
+ if (escapeTitles) {
+ // If escaping the title, then wrap the matchng char within exotic chars
+ matchingIndices.forEach(function (v) {
+ textPoses[v] = exoticStartChar + textPoses[v] + exoticEndChar;
+ });
+ } else {
+ // Otherwise, Wrap the matching chars within `mark`.
+ matchingIndices.forEach(function (v) {
+ textPoses[v] = "<mark>" + textPoses[v] + "</mark>";
+ });
+ }
+ // Join back the modified `textPoses` to create final highlight markup.
+ return textPoses.join("");
+ }
+ $.ui.fancytree._FancytreeClass.prototype._applyFilterImpl = function (
+ filter,
+ branchMode,
+ _opts
+ ) {
+ var match,
+ statusNode,
+ re,
+ reHighlight,
+ reExoticStartChar,
+ reExoticEndChar,
+ temp,
+ prevEnableUpdate,
+ count = 0,
+ treeOpts = this.options,
+ escapeTitles = treeOpts.escapeTitles,
+ prevAutoCollapse = treeOpts.autoCollapse,
+ opts = $.extend({}, treeOpts.filter, _opts),
+ hideMode = opts.mode === "hide",
+ leavesOnly = !!opts.leavesOnly && !branchMode;
+
+ // Default to 'match title substring (not case sensitive)'
+ if (typeof filter === "string") {
+ if (filter === "") {
+ this.warn(
+ "Fancytree passing an empty string as a filter is handled as clearFilter()."
+ );
+ this.clearFilter();
+ return;
+ }
+ if (opts.fuzzy) {
+ // See https://codereview.stackexchange.com/questions/23899/faster-javascript-fuzzy-string-matching-function/23905#23905
+ // and http://www.quora.com/How-is-the-fuzzy-search-algorithm-in-Sublime-Text-designed
+ // and http://www.dustindiaz.com/autocomplete-fuzzy-matching
+ match = filter
+ .split("")
+ // Escaping the `filter` will not work because,
+ // it gets further split into individual characters. So,
+ // escape each character after splitting
+ .map(_escapeRegex)
+ .reduce(function (a, b) {
+ // create capture groups for parts that comes before
+ // the character
+ return a + "([^" + b + "]*)" + b;
+ }, "");
+ } else {
+ match = _escapeRegex(filter); // make sure a '.' is treated literally
+ }
+ re = new RegExp(match, "i");
+ reHighlight = new RegExp(_escapeRegex(filter), "gi");
+ if (escapeTitles) {
+ reExoticStartChar = new RegExp(
+ _escapeRegex(exoticStartChar),
+ "g"
+ );
+ reExoticEndChar = new RegExp(_escapeRegex(exoticEndChar), "g");
+ }
+ filter = function (node) {
+ if (!node.title) {
+ return false;
+ }
+ var text = escapeTitles
+ ? node.title
+ : extractHtmlText(node.title),
+ // `.match` instead of `.test` to get the capture groups
+ res = text.match(re);
+ if (res && opts.highlight) {
+ if (escapeTitles) {
+ if (opts.fuzzy) {
+ temp = _markFuzzyMatchedChars(
+ text,
+ res,
+ escapeTitles
+ );
+ } else {
+ // #740: we must not apply the marks to escaped entity names, e.g. `&quot;`
+ // Use some exotic characters to mark matches:
+ temp = text.replace(reHighlight, function (s) {
+ return exoticStartChar + s + exoticEndChar;
+ });
+ }
+ // now we can escape the title...
+ node.titleWithHighlight = escapeHtml(temp)
+ // ... and finally insert the desired `<mark>` tags
+ .replace(reExoticStartChar, "<mark>")
+ .replace(reExoticEndChar, "</mark>");
+ } else {
+ if (opts.fuzzy) {
+ node.titleWithHighlight = _markFuzzyMatchedChars(
+ text,
+ res
+ );
+ } else {
+ node.titleWithHighlight = text.replace(
+ reHighlight,
+ function (s) {
+ return "<mark>" + s + "</mark>";
+ }
+ );
+ }
+ }
+ // node.debug("filter", escapeTitles, text, node.titleWithHighlight);
+ }
+ return !!res;
+ };
+ }
+
+ this.enableFilter = true;
+ this.lastFilterArgs = arguments;
+
+ prevEnableUpdate = this.enableUpdate(false);
+
+ this.$div.addClass("fancytree-ext-filter");
+ if (hideMode) {
+ this.$div.addClass("fancytree-ext-filter-hide");
+ } else {
+ this.$div.addClass("fancytree-ext-filter-dimm");
+ }
+ this.$div.toggleClass(
+ "fancytree-ext-filter-hide-expanders",
+ !!opts.hideExpanders
+ );
+ // Reset current filter
+ this.rootNode.subMatchCount = 0;
+ this.visit(function (node) {
+ delete node.match;
+ delete node.titleWithHighlight;
+ node.subMatchCount = 0;
+ });
+ statusNode = this.getRootNode()._findDirectChild(KeyNoData);
+ if (statusNode) {
+ statusNode.remove();
+ }
+
+ // Adjust node.hide, .match, and .subMatchCount properties
+ treeOpts.autoCollapse = false; // #528
+
+ this.visit(function (node) {
+ if (leavesOnly && node.children != null) {
+ return;
+ }
+ var res = filter(node),
+ matchedByBranch = false;
+
+ if (res === "skip") {
+ node.visit(function (c) {
+ c.match = false;
+ }, true);
+ return "skip";
+ }
+ if (!res && (branchMode || res === "branch") && node.parent.match) {
+ res = true;
+ matchedByBranch = true;
+ }
+ if (res) {
+ count++;
+ node.match = true;
+ node.visitParents(function (p) {
+ if (p !== node) {
+ p.subMatchCount += 1;
+ }
+ // Expand match (unless this is no real match, but only a node in a matched branch)
+ if (opts.autoExpand && !matchedByBranch && !p.expanded) {
+ p.setExpanded(true, {
+ noAnimation: true,
+ noEvents: true,
+ scrollIntoView: false,
+ });
+ p._filterAutoExpanded = true;
+ }
+ }, true);
+ }
+ });
+ treeOpts.autoCollapse = prevAutoCollapse;
+
+ if (count === 0 && opts.nodata && hideMode) {
+ statusNode = opts.nodata;
+ if (typeof statusNode === "function") {
+ statusNode = statusNode();
+ }
+ if (statusNode === true) {
+ statusNode = {};
+ } else if (typeof statusNode === "string") {
+ statusNode = { title: statusNode };
+ }
+ statusNode = $.extend(
+ {
+ statusNodeType: "nodata",
+ key: KeyNoData,
+ title: this.options.strings.noData,
+ },
+ statusNode
+ );
+
+ this.getRootNode().addNode(statusNode).match = true;
+ }
+ // Redraw whole tree
+ this._callHook("treeStructureChanged", this, "applyFilter");
+ // this.render();
+ this.enableUpdate(prevEnableUpdate);
+ return count;
+ };
+
+ /**
+ * [ext-filter] Dimm or hide nodes.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false, leavesOnly: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterNodes
+ * @requires jquery.fancytree.filter.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.filterNodes = function (
+ filter,
+ opts
+ ) {
+ if (typeof opts === "boolean") {
+ opts = { leavesOnly: opts };
+ this.warn(
+ "Fancytree.filterNodes() leavesOnly option is deprecated since 2.9.0 / 2015-04-19. Use opts.leavesOnly instead."
+ );
+ }
+ return this._applyFilterImpl(filter, false, opts);
+ };
+
+ /**
+ * [ext-filter] Dimm or hide whole branches.
+ *
+ * @param {function | string} filter
+ * @param {boolean} [opts={autoExpand: false}]
+ * @returns {integer} count
+ * @alias Fancytree#filterBranches
+ * @requires jquery.fancytree.filter.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.filterBranches = function (
+ filter,
+ opts
+ ) {
+ return this._applyFilterImpl(filter, true, opts);
+ };
+
+ /**
+ * [ext-filter] Re-apply current filter.
+ *
+ * @returns {integer} count
+ * @alias Fancytree#updateFilter
+ * @requires jquery.fancytree.filter.js
+ * @since 2.38
+ */
+ $.ui.fancytree._FancytreeClass.prototype.updateFilter = function () {
+ if (
+ this.enableFilter &&
+ this.lastFilterArgs &&
+ this.options.filter.autoApply
+ ) {
+ this._applyFilterImpl.apply(this, this.lastFilterArgs);
+ } else {
+ this.warn("updateFilter(): no filter active.");
+ }
+ };
+
+ /**
+ * [ext-filter] Reset the filter.
+ *
+ * @alias Fancytree#clearFilter
+ * @requires jquery.fancytree.filter.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.clearFilter = function () {
+ var $title,
+ statusNode = this.getRootNode()._findDirectChild(KeyNoData),
+ escapeTitles = this.options.escapeTitles,
+ enhanceTitle = this.options.enhanceTitle,
+ prevEnableUpdate = this.enableUpdate(false);
+
+ if (statusNode) {
+ statusNode.remove();
+ }
+ // we also counted root node's subMatchCount
+ delete this.rootNode.match;
+ delete this.rootNode.subMatchCount;
+
+ this.visit(function (node) {
+ if (node.match && node.span) {
+ // #491, #601
+ $title = $(node.span).find(">span.fancytree-title");
+ if (escapeTitles) {
+ $title.text(node.title);
+ } else {
+ $title.html(node.title);
+ }
+ if (enhanceTitle) {
+ enhanceTitle(
+ { type: "enhanceTitle" },
+ { node: node, $title: $title }
+ );
+ }
+ }
+ delete node.match;
+ delete node.subMatchCount;
+ delete node.titleWithHighlight;
+ if (node.$subMatchBadge) {
+ node.$subMatchBadge.remove();
+ delete node.$subMatchBadge;
+ }
+ if (node._filterAutoExpanded && node.expanded) {
+ node.setExpanded(false, {
+ noAnimation: true,
+ noEvents: true,
+ scrollIntoView: false,
+ });
+ }
+ delete node._filterAutoExpanded;
+ });
+ this.enableFilter = false;
+ this.lastFilterArgs = null;
+ this.$div.removeClass(
+ "fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide"
+ );
+ this._callHook("treeStructureChanged", this, "clearFilter");
+ // this.render();
+ this.enableUpdate(prevEnableUpdate);
+ };
+
+ /**
+ * [ext-filter] Return true if a filter is currently applied.
+ *
+ * @returns {Boolean}
+ * @alias Fancytree#isFilterActive
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+ $.ui.fancytree._FancytreeClass.prototype.isFilterActive = function () {
+ return !!this.enableFilter;
+ };
+
+ /**
+ * [ext-filter] Return true if this node is matched by current filter (or no filter is active).
+ *
+ * @returns {Boolean}
+ * @alias FancytreeNode#isMatched
+ * @requires jquery.fancytree.filter.js
+ * @since 2.13
+ */
+ $.ui.fancytree._FancytreeNodeClass.prototype.isMatched = function () {
+ return !(this.tree.enableFilter && !this.match);
+ };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "filter",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ autoApply: true, // Re-apply last filter if lazy data is loaded
+ autoExpand: false, // Expand all branches that contain matches while filtered
+ counter: true, // Show a badge with number of matching child nodes near parent icons
+ fuzzy: false, // Match single characters in order, e.g. 'fb' will match 'FooBar'
+ hideExpandedCounter: true, // Hide counter badge if parent is expanded
+ hideExpanders: false, // Hide expanders if all child nodes are hidden by filter
+ highlight: true, // Highlight matches by wrapping inside <mark> tags
+ leavesOnly: false, // Match end nodes only
+ nodata: true, // Display a 'no data' status node if result is empty
+ mode: "dimm", // Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
+ },
+ nodeLoadChildren: function (ctx, source) {
+ var tree = ctx.tree;
+
+ return this._superApply(arguments).done(function () {
+ if (
+ tree.enableFilter &&
+ tree.lastFilterArgs &&
+ ctx.options.filter.autoApply
+ ) {
+ tree._applyFilterImpl.apply(tree, tree.lastFilterArgs);
+ }
+ });
+ },
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var node = ctx.node;
+
+ delete node._filterAutoExpanded;
+ // Make sure counter badge is displayed again, when node is beeing collapsed
+ if (
+ !flag &&
+ ctx.options.filter.hideExpandedCounter &&
+ node.$subMatchBadge
+ ) {
+ node.$subMatchBadge.show();
+ }
+ return this._superApply(arguments);
+ },
+ nodeRenderStatus: function (ctx) {
+ // Set classes for current status
+ var res,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options.filter,
+ $title = $(node.span).find("span.fancytree-title"),
+ $span = $(node[tree.statusClassPropName]),
+ enhanceTitle = ctx.options.enhanceTitle,
+ escapeTitles = ctx.options.escapeTitles;
+
+ res = this._super(ctx);
+ // nothing to do, if node was not yet rendered
+ if (!$span.length || !tree.enableFilter) {
+ return res;
+ }
+ $span
+ .toggleClass("fancytree-match", !!node.match)
+ .toggleClass("fancytree-submatch", !!node.subMatchCount)
+ .toggleClass(
+ "fancytree-hide",
+ !(node.match || node.subMatchCount)
+ );
+ // Add/update counter badge
+ if (
+ opts.counter &&
+ node.subMatchCount &&
+ (!node.isExpanded() || !opts.hideExpandedCounter)
+ ) {
+ if (!node.$subMatchBadge) {
+ node.$subMatchBadge = $(
+ "<span class='fancytree-childcounter'/>"
+ );
+ $(
+ "span.fancytree-icon, span.fancytree-custom-icon",
+ node.span
+ ).append(node.$subMatchBadge);
+ }
+ node.$subMatchBadge.show().text(node.subMatchCount);
+ } else if (node.$subMatchBadge) {
+ node.$subMatchBadge.hide();
+ }
+ // node.debug("nodeRenderStatus", node.titleWithHighlight, node.title)
+ // #601: also check for $title.length, because we don't need to render
+ // if node.span is null (i.e. not rendered)
+ if (node.span && (!node.isEditing || !node.isEditing.call(node))) {
+ if (node.titleWithHighlight) {
+ $title.html(node.titleWithHighlight);
+ } else if (escapeTitles) {
+ $title.text(node.title);
+ } else {
+ $title.html(node.title);
+ }
+ if (enhanceTitle) {
+ enhanceTitle(
+ { type: "enhanceTitle" },
+ { node: node, $title: $title }
+ );
+ }
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.fixed.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.fixed.js
new file mode 100644
index 0000000..7372f24
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.fixed.js
@@ -0,0 +1,674 @@
+/*!
+ * jquery.fancytree.fixed.js
+ *
+ * Add fixed colums and headers to ext.table.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+// Allow to use multiple var statements inside a function
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([
+ "jquery",
+ "./jquery.fancytree",
+ "./jquery.fancytree.table",
+ ], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree.table"); // core + table
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+
+ $.ui.fancytree.registerExtension({
+ name: "fixed",
+ version: "0.0.1",
+ // Default options for this extension.
+ options: {
+ fixCol: 1,
+ fixColWidths: null,
+ fixRows: true,
+ scrollSpeed: 50,
+ resizable: true,
+ classNames: {
+ table: "fancytree-ext-fixed",
+ wrapper: "fancytree-ext-fixed-wrapper",
+ topLeft: "fancytree-ext-fixed-wrapper-tl",
+ topRight: "fancytree-ext-fixed-wrapper-tr",
+ bottomLeft: "fancytree-ext-fixed-wrapper-bl",
+ bottomRight: "fancytree-ext-fixed-wrapper-br",
+ hidden: "fancytree-ext-fixed-hidden",
+ counterpart: "fancytree-ext-fixed-node-counterpart",
+ scrollBorderBottom: "fancytree-ext-fixed-scroll-border-bottom",
+ scrollBorderRight: "fancytree-ext-fixed-scroll-border-right",
+ hover: "fancytree-ext-fixed-hover",
+ },
+ },
+ // Overide virtual methods for this extension.
+ // `this` : is this extension object
+ // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
+ treeInit: function (ctx) {
+ this._requireExtension("table", true, true);
+ // 'fixed' requires the table extension to be loaded before itself
+
+ var res = this._superApply(arguments),
+ tree = ctx.tree,
+ options = this.options.fixed,
+ fcn = this.options.fixed.classNames,
+ $table = tree.widget.element,
+ fixedColCount = options.fixCols,
+ fixedRowCount = options.fixRows,
+ $tableWrapper = $table.parent(),
+ $topLeftWrapper = $("<div>").addClass(fcn.topLeft),
+ $topRightWrapper = $("<div>").addClass(fcn.topRight),
+ $bottomLeftWrapper = $("<div>").addClass(fcn.bottomLeft),
+ $bottomRightWrapper = $("<div>").addClass(fcn.bottomRight),
+ tableStyle = $table.attr("style"),
+ tableClass = $table.attr("class"),
+ $topLeftTable = $("<table>")
+ .attr("style", tableStyle)
+ .attr("class", tableClass),
+ $topRightTable = $("<table>")
+ .attr("style", tableStyle)
+ .attr("class", tableClass),
+ $bottomLeftTable = $table,
+ $bottomRightTable = $("<table>")
+ .attr("style", tableStyle)
+ .attr("class", tableClass),
+ $head = $table.find("thead"),
+ $colgroup = $table.find("colgroup"),
+ headRowCount = $head.find("tr").length;
+
+ this.$fixedWrapper = $tableWrapper;
+ $table.addClass(fcn.table);
+ $tableWrapper.addClass(fcn.wrapper);
+ $bottomRightTable.append($("<tbody>"));
+
+ if ($colgroup.length) {
+ $colgroup.remove();
+ }
+
+ if (typeof fixedRowCount === "boolean") {
+ fixedRowCount = fixedRowCount ? headRowCount : 0;
+ } else {
+ fixedRowCount = Math.max(
+ 0,
+ Math.min(fixedRowCount, headRowCount)
+ );
+ }
+
+ if (fixedRowCount) {
+ $topLeftTable.append($head.clone(true));
+ $topRightTable.append($head.clone(true));
+ $head.remove();
+ }
+
+ $topLeftTable.find("tr").each(function (idx) {
+ $(this).find("th").slice(fixedColCount).remove();
+ });
+
+ $topRightTable.find("tr").each(function (idx) {
+ $(this).find("th").slice(0, fixedColCount).remove();
+ });
+
+ this.$fixedWrapper = $tableWrapper;
+
+ $tableWrapper.append(
+ $topLeftWrapper.append($topLeftTable),
+ $topRightWrapper.append($topRightTable),
+ $bottomLeftWrapper.append($bottomLeftTable),
+ $bottomRightWrapper.append($bottomRightTable)
+ );
+
+ $bottomRightTable.on("keydown", function (evt) {
+ var node = tree.focusNode,
+ ctx = tree._makeHookContext(node || tree, evt),
+ res = tree._callHook("nodeKeydown", ctx);
+ return res;
+ });
+
+ $bottomRightTable.on("click dblclick", "tr", function (evt) {
+ var $trLeft = $(this),
+ $trRight = $trLeft.data(fcn.counterpart),
+ node = $.ui.fancytree.getNode($trRight),
+ ctx = tree._makeHookContext(node, evt),
+ et = $.ui.fancytree.getEventTarget(evt),
+ prevPhase = tree.phase;
+
+ try {
+ tree.phase = "userEvent";
+ switch (evt.type) {
+ case "click":
+ ctx.targetType = et.type;
+ if (node.isPagingNode()) {
+ return (
+ tree._triggerNodeEvent(
+ "clickPaging",
+ ctx,
+ evt
+ ) === true
+ );
+ }
+ return tree._triggerNodeEvent("click", ctx, evt) ===
+ false
+ ? false
+ : tree._callHook("nodeClick", ctx);
+ case "dblclick":
+ ctx.targetType = et.type;
+ return tree._triggerNodeEvent(
+ "dblclick",
+ ctx,
+ evt
+ ) === false
+ ? false
+ : tree._callHook("nodeDblclick", ctx);
+ }
+ } finally {
+ tree.phase = prevPhase;
+ }
+ });
+
+ $tableWrapper
+ .on(
+ "mouseenter",
+ "." +
+ fcn.bottomRight +
+ " table tr, ." +
+ fcn.bottomLeft +
+ " table tr",
+ function (evt) {
+ var $tr = $(this),
+ $trOther = $tr.data(fcn.counterpart);
+ $tr.addClass(fcn.hover);
+ $trOther.addClass(fcn.hover);
+ }
+ )
+ .on(
+ "mouseleave",
+ "." +
+ fcn.bottomRight +
+ " table tr, ." +
+ fcn.bottomLeft +
+ " table tr",
+ function (evt) {
+ var $tr = $(this),
+ $trOther = $tr.data(fcn.counterpart);
+ $tr.removeClass(fcn.hover);
+ $trOther.removeClass(fcn.hover);
+ }
+ );
+
+ $bottomLeftWrapper.on(
+ "mousewheel DOMMouseScroll",
+ function (event) {
+ var $this = $(this),
+ newScroll = $this.scrollTop(),
+ scrollUp =
+ event.originalEvent.wheelDelta > 0 ||
+ event.originalEvent.detail < 0;
+
+ newScroll += scrollUp
+ ? -options.scrollSpeed
+ : options.scrollSpeed;
+ $this.scrollTop(newScroll);
+ $bottomRightWrapper.scrollTop(newScroll);
+ event.preventDefault();
+ }
+ );
+
+ $bottomRightWrapper.scroll(function () {
+ var $this = $(this),
+ scrollLeft = $this.scrollLeft(),
+ scrollTop = $this.scrollTop();
+
+ $topLeftWrapper
+ .toggleClass(fcn.scrollBorderBottom, scrollTop > 0)
+ .toggleClass(fcn.scrollBorderRight, scrollLeft > 0);
+ $topRightWrapper
+ .toggleClass(fcn.scrollBorderBottom, scrollTop > 0)
+ .scrollLeft(scrollLeft);
+ $bottomLeftWrapper
+ .toggleClass(fcn.scrollBorderRight, scrollLeft > 0)
+ .scrollTop(scrollTop);
+ });
+
+ $.ui.fancytree.overrideMethod(
+ $.ui.fancytree._FancytreeNodeClass.prototype,
+ "scrollIntoView",
+ function (effects, options) {
+ var $prevContainer = tree.$container;
+ tree.$container = $bottomRightWrapper;
+ return this._super
+ .apply(this, arguments)
+ .always(function () {
+ tree.$container = $prevContainer;
+ });
+ }
+ );
+ return res;
+ },
+
+ treeLoad: function (ctx) {
+ var self = this,
+ res = this._superApply(arguments);
+
+ res.done(function () {
+ self.ext.fixed._adjustLayout.call(self);
+ if (self.options.fixed.resizable) {
+ self.ext.fixed._makeTableResizable();
+ }
+ });
+ return res;
+ },
+
+ _makeTableResizable: function () {
+ var $wrapper = this.$fixedWrapper,
+ fcn = this.options.fixed.classNames,
+ $topLeftWrapper = $wrapper.find("div." + fcn.topLeft),
+ $topRightWrapper = $wrapper.find("div." + fcn.topRight),
+ $bottomLeftWrapper = $wrapper.find("div." + fcn.bottomLeft),
+ $bottomRightWrapper = $wrapper.find("div." + fcn.bottomRight);
+
+ function _makeResizable($table) {
+ $table.resizable({
+ handles: "e",
+ resize: function (evt, ui) {
+ var width = Math.max($table.width(), ui.size.width);
+ $bottomLeftWrapper.css("width", width);
+ $topLeftWrapper.css("width", width);
+ $bottomRightWrapper.css("left", width);
+ $topRightWrapper.css("left", width);
+ },
+ stop: function () {
+ $table.css("width", "100%");
+ },
+ });
+ }
+
+ _makeResizable($topLeftWrapper.find("table"));
+ _makeResizable($bottomLeftWrapper.find("table"));
+ },
+
+ /* Called by nodeRender to sync node order with tag order.*/
+ // nodeFixOrder: function(ctx) {
+ // },
+
+ nodeLoadChildren: function (ctx, source) {
+ return this._superApply(arguments);
+ },
+
+ nodeRemoveChildMarkup: function (ctx) {
+ var node = ctx.node;
+
+ function _removeChild(elem) {
+ var i,
+ child,
+ children = elem.children;
+ if (children) {
+ for (i = 0; i < children.length; i++) {
+ child = children[i];
+ if (child.trRight) {
+ $(child.trRight).remove();
+ }
+ _removeChild(child);
+ }
+ }
+ }
+
+ _removeChild(node);
+ return this._superApply(arguments);
+ },
+
+ nodeRemoveMarkup: function (ctx) {
+ var node = ctx.node;
+
+ if (node.trRight) {
+ $(node.trRight).remove();
+ }
+ return this._superApply(arguments);
+ },
+
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var node = ctx.node,
+ cn = this.options._classNames;
+
+ if (node.trRight) {
+ $(node.trRight)
+ .toggleClass(cn.active, flag)
+ .toggleClass(cn.focused, flag);
+ }
+ return this._superApply(arguments);
+ },
+
+ nodeKeydown: function (ctx) {
+ return this._superApply(arguments);
+ },
+
+ nodeSetFocus: function (ctx, flag) {
+ var node = ctx.node,
+ cn = this.options._classNames;
+
+ if (node.trRight) {
+ $(node.trRight).toggleClass(cn.focused, flag);
+ }
+ return this._superApply(arguments);
+ },
+
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ var res = this._superApply(arguments),
+ node = ctx.node,
+ isRootNode = !node.parent;
+
+ if (!isRootNode && this.$fixedWrapper) {
+ var $trLeft = $(node.tr),
+ fcn = this.options.fixed.classNames,
+ $trRight = $trLeft.data(fcn.counterpart);
+
+ if (!$trRight && $trLeft.length) {
+ var idx = $trLeft.index(),
+ fixedColCount = this.options.fixed.fixCols,
+ $blTableBody = this.$fixedWrapper.find(
+ "div." + fcn.bottomLeft + " table tbody"
+ ),
+ $brTableBody = this.$fixedWrapper.find(
+ "div." + fcn.bottomRight + " table tbody"
+ ),
+ $prevLeftNode = $blTableBody
+ .find("tr")
+ .eq(Math.max(idx + 1, 0)),
+ prevRightNode = $prevLeftNode.data(fcn.counterpart);
+
+ $trRight = $trLeft.clone(true);
+ var trRight = $trRight.get(0);
+
+ if (prevRightNode) {
+ $(prevRightNode).before($trRight);
+ } else {
+ $brTableBody.append($trRight);
+ }
+ $trRight.show();
+ trRight.ftnode = node;
+ node.trRight = trRight;
+
+ $trLeft.find("td").slice(fixedColCount).remove();
+ $trRight.find("td").slice(0, fixedColCount).remove();
+ $trLeft.data(fcn.counterpart, $trRight);
+ $trRight.data(fcn.counterpart, $trLeft);
+ }
+ }
+
+ return res;
+ },
+
+ nodeRenderTitle: function (ctx, title) {
+ return this._superApply(arguments);
+ },
+
+ nodeRenderStatus: function (ctx) {
+ var res = this._superApply(arguments),
+ node = ctx.node;
+
+ if (node.trRight) {
+ var $trRight = $(node.trRight),
+ $trLeft = $(node.tr),
+ fcn = this.options.fixed.classNames,
+ hovering = $trRight.hasClass(fcn.hover),
+ trClasses = $trLeft.attr("class");
+
+ $trRight.attr("class", trClasses);
+ if (hovering) {
+ $trRight.addClass(fcn.hover);
+ $trLeft.addClass(fcn.hover);
+ }
+ }
+ return res;
+ },
+
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var res,
+ self = this,
+ node = ctx.node,
+ $leftTr = $(node.tr),
+ fcn = this.options.fixed.classNames,
+ cn = this.options._classNames,
+ $rightTr = $leftTr.data(fcn.counterpart);
+
+ flag = typeof flag === "undefined" ? true : flag;
+
+ if (!$rightTr) {
+ return this._superApply(arguments);
+ }
+ $rightTr.toggleClass(cn.expanded, !!flag);
+ if (flag && !node.isExpanded()) {
+ res = this._superApply(arguments);
+ res.done(function () {
+ node.visit(function (child) {
+ var $trLeft = $(child.tr),
+ $trRight = $trLeft.data(fcn.counterpart);
+
+ self.ext.fixed._adjustRowHeight($trLeft, $trRight);
+ if (!child.expanded) {
+ return "skip";
+ }
+ });
+
+ self.ext.fixed._adjustColWidths();
+ self.ext.fixed._adjustWrapperLayout();
+ });
+ } else if (!flag && node.isExpanded()) {
+ node.visit(function (child) {
+ var $trLeft = $(child.tr),
+ $trRight = $trLeft.data(fcn.counterpart);
+ if ($trRight) {
+ if (!child.expanded) {
+ return "skip";
+ }
+ }
+ });
+
+ self.ext.fixed._adjustColWidths();
+ self.ext.fixed._adjustWrapperLayout();
+ res = this._superApply(arguments);
+ } else {
+ res = this._superApply(arguments);
+ }
+ return res;
+ },
+
+ nodeSetStatus: function (ctx, status, message, details) {
+ return this._superApply(arguments);
+ },
+
+ treeClear: function (ctx) {
+ var tree = ctx.tree,
+ $table = tree.widget.element,
+ $wrapper = this.$fixedWrapper,
+ fcn = this.options.fixed.classNames;
+
+ $table.find("tr, td, th, thead").removeClass(fcn.hidden).css({
+ "min-width": "auto",
+ height: "auto",
+ });
+ $wrapper.empty().append($table);
+ return this._superApply(arguments);
+ },
+
+ treeRegisterNode: function (ctx, add, node) {
+ return this._superApply(arguments);
+ },
+
+ treeDestroy: function (ctx) {
+ var tree = ctx.tree,
+ $table = tree.widget.element,
+ $wrapper = this.$fixedWrapper,
+ fcn = this.options.fixed.classNames;
+
+ $table.find("tr, td, th, thead").removeClass(fcn.hidden).css({
+ "min-width": "auto",
+ height: "auto",
+ });
+ $wrapper.empty().append($table);
+ return this._superApply(arguments);
+ },
+
+ _adjustColWidths: function () {
+ if (this.options.fixed.adjustColWidths) {
+ this.options.fixed.adjustColWidths.call(this);
+ return;
+ }
+
+ var $wrapper = this.$fixedWrapper,
+ fcn = this.options.fixed.classNames,
+ $tlWrapper = $wrapper.find("div." + fcn.topLeft),
+ $blWrapper = $wrapper.find("div." + fcn.bottomLeft),
+ $trWrapper = $wrapper.find("div." + fcn.topRight),
+ $brWrapper = $wrapper.find("div." + fcn.bottomRight);
+
+ function _adjust($topWrapper, $bottomWrapper) {
+ var $trTop = $topWrapper.find("thead tr").first(),
+ $trBottom = $bottomWrapper.find("tbody tr").first();
+
+ $trTop.find("th").each(function (idx) {
+ var $thTop = $(this),
+ $tdBottom = $trBottom.find("td").eq(idx),
+ thTopWidth = $thTop.width(),
+ thTopOuterWidth = $thTop.outerWidth(),
+ tdBottomWidth = $tdBottom.width(),
+ tdBottomOuterWidth = $tdBottom.outerWidth(),
+ newWidth = Math.max(
+ thTopOuterWidth,
+ tdBottomOuterWidth
+ );
+
+ $thTop.css(
+ "min-width",
+ newWidth - (thTopOuterWidth - thTopWidth)
+ );
+ $tdBottom.css(
+ "min-width",
+ newWidth - (tdBottomOuterWidth - tdBottomWidth)
+ );
+ });
+ }
+
+ _adjust($tlWrapper, $blWrapper);
+ _adjust($trWrapper, $brWrapper);
+ },
+
+ _adjustRowHeight: function ($tr1, $tr2) {
+ var fcn = this.options.fixed.classNames;
+ if (!$tr2) {
+ $tr2 = $tr1.data(fcn.counterpart);
+ }
+ $tr1.css("height", "auto");
+ $tr2.css("height", "auto");
+ var row1Height = $tr1.outerHeight(),
+ row2Height = $tr2.outerHeight(),
+ newHeight = Math.max(row1Height, row2Height);
+ $tr1.css("height", newHeight + 1);
+ $tr2.css("height", newHeight + 1);
+ },
+
+ _adjustWrapperLayout: function () {
+ var $wrapper = this.$fixedWrapper,
+ fcn = this.options.fixed.classNames,
+ $topLeftWrapper = $wrapper.find("div." + fcn.topLeft),
+ $topRightWrapper = $wrapper.find("div." + fcn.topRight),
+ $bottomLeftWrapper = $wrapper.find("div." + fcn.bottomLeft),
+ $bottomRightWrapper = $wrapper.find("div." + fcn.bottomRight),
+ $topLeftTable = $topLeftWrapper.find("table"),
+ $topRightTable = $topRightWrapper.find("table"),
+ // $bottomLeftTable = $bottomLeftWrapper.find("table"),
+ wrapperWidth = $wrapper.width(),
+ wrapperHeight = $wrapper.height(),
+ fixedWidth = Math.min(wrapperWidth, $topLeftTable.width()),
+ fixedHeight = Math.min(
+ wrapperHeight,
+ Math.max($topLeftTable.height(), $topRightTable.height())
+ );
+ // vScrollbar = $bottomRightWrapper.get(0).scrollHeight > (wrapperHeight - fixedHeight),
+ // hScrollbar = $bottomRightWrapper.get(0).scrollWidth > (wrapperWidth - fixedWidth);
+
+ $topLeftWrapper.css({
+ width: fixedWidth,
+ height: fixedHeight,
+ });
+ $topRightWrapper.css({
+ // width: wrapperWidth - fixedWidth - (vScrollbar ? 17 : 0),
+ // width: "calc(100% - " + (fixedWidth + (vScrollbar ? 17 : 0)) + "px)",
+ width: "calc(100% - " + (fixedWidth + 17) + "px)",
+ height: fixedHeight,
+ left: fixedWidth,
+ });
+ $bottomLeftWrapper.css({
+ width: fixedWidth,
+ // height: vScrollbar ? wrapperHeight - fixedHeight - (hScrollbar ? 17 : 0) : "auto",
+ // height: vScrollbar ? ("calc(100% - " + (fixedHeight + (hScrollbar ? 17 : 0)) + "px)") : "auto",
+ // height: vScrollbar ? ("calc(100% - " + (fixedHeight + 17) + "px)") : "auto",
+ height: "calc(100% - " + (fixedHeight + 17) + "px)",
+ top: fixedHeight,
+ });
+ $bottomRightWrapper.css({
+ // width: wrapperWidth - fixedWidth,
+ // height: vScrollbar ? wrapperHeight - fixedHeight : "auto",
+ width: "calc(100% - " + fixedWidth + "px)",
+ // height: vScrollbar ? ("calc(100% - " + fixedHeight + "px)") : "auto",
+ height: "calc(100% - " + fixedHeight + "px)",
+ top: fixedHeight,
+ left: fixedWidth,
+ });
+ },
+
+ _adjustLayout: function () {
+ var self = this,
+ $wrapper = this.$fixedWrapper,
+ fcn = this.options.fixed.classNames,
+ $topLeftWrapper = $wrapper.find("div." + fcn.topLeft),
+ $topRightWrapper = $wrapper.find("div." + fcn.topRight),
+ $bottomLeftWrapper = $wrapper.find("div." + fcn.bottomLeft);
+ // $bottomRightWrapper = $wrapper.find("div." + fcn.bottomRight)
+
+ $topLeftWrapper.find("table tr").each(function (idx) {
+ var $trRight = $topRightWrapper.find("tr").eq(idx);
+ self.ext.fixed._adjustRowHeight($(this), $trRight);
+ });
+
+ $bottomLeftWrapper
+ .find("table tbody")
+ .find("tr")
+ .each(function (idx) {
+ // var $trRight = $bottomRightWrapper.find("tbody").find("tr").eq(idx);
+ self.ext.fixed._adjustRowHeight($(this));
+ });
+
+ self.ext.fixed._adjustColWidths.call(this);
+ self.ext.fixed._adjustWrapperLayout.call(this);
+ },
+
+ // treeSetFocus: function(ctx, flag) {
+ //// alert("treeSetFocus" + ctx.tree.$container);
+ // ctx.tree.$container.focus();
+ // $.ui.fancytree.focusTree = ctx.tree;
+ // }
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.glyph.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.glyph.js
new file mode 100644
index 0000000..4771bee
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.glyph.js
@@ -0,0 +1,354 @@
+/*!
+ * jquery.fancytree.glyph.js
+ *
+ * Use glyph-fonts, ligature-fonts, or SVG icons instead of icon sprites.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+
+ var FT = $.ui.fancytree,
+ PRESETS = {
+ awesome3: {
+ // Outdated!
+ _addClass: "",
+ checkbox: "icon-check-empty",
+ checkboxSelected: "icon-check",
+ checkboxUnknown: "icon-check icon-muted",
+ dragHelper: "icon-caret-right",
+ dropMarker: "icon-caret-right",
+ error: "icon-exclamation-sign",
+ expanderClosed: "icon-caret-right",
+ expanderLazy: "icon-angle-right",
+ expanderOpen: "icon-caret-down",
+ loading: "icon-refresh icon-spin",
+ nodata: "icon-meh",
+ noExpander: "",
+ radio: "icon-circle-blank",
+ radioSelected: "icon-circle",
+ // radioUnknown: "icon-circle icon-muted",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "icon-file-alt",
+ docOpen: "icon-file-alt",
+ folder: "icon-folder-close-alt",
+ folderOpen: "icon-folder-open-alt",
+ },
+ awesome4: {
+ _addClass: "fa",
+ checkbox: "fa-square-o",
+ checkboxSelected: "fa-check-square-o",
+ checkboxUnknown: "fa-square fancytree-helper-indeterminate-cb",
+ dragHelper: "fa-arrow-right",
+ dropMarker: "fa-long-arrow-right",
+ error: "fa-warning",
+ expanderClosed: "fa-caret-right",
+ expanderLazy: "fa-angle-right",
+ expanderOpen: "fa-caret-down",
+ // We may prevent wobbling rotations on FF by creating a separate sub element:
+ loading: { html: "<span class='fa fa-spinner fa-pulse' />" },
+ nodata: "fa-meh-o",
+ noExpander: "",
+ radio: "fa-circle-thin", // "fa-circle-o"
+ radioSelected: "fa-circle",
+ // radioUnknown: "fa-dot-circle-o",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "fa-file-o",
+ docOpen: "fa-file-o",
+ folder: "fa-folder-o",
+ folderOpen: "fa-folder-open-o",
+ },
+ awesome5: {
+ // fontawesome 5 have several different base classes
+ // "far, fas, fal and fab" The rendered svg puts that prefix
+ // in a different location so we have to keep them separate here
+ _addClass: "",
+ checkbox: "far fa-square",
+ checkboxSelected: "far fa-check-square",
+ // checkboxUnknown: "far fa-window-close",
+ checkboxUnknown:
+ "fas fa-square fancytree-helper-indeterminate-cb",
+ radio: "far fa-circle",
+ radioSelected: "fas fa-circle",
+ radioUnknown: "far fa-dot-circle",
+ dragHelper: "fas fa-arrow-right",
+ dropMarker: "fas fa-long-arrow-alt-right",
+ error: "fas fa-exclamation-triangle",
+ expanderClosed: "fas fa-caret-right",
+ expanderLazy: "fas fa-angle-right",
+ expanderOpen: "fas fa-caret-down",
+ loading: "fas fa-spinner fa-pulse",
+ nodata: "far fa-meh",
+ noExpander: "",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "far fa-file",
+ docOpen: "far fa-file",
+ folder: "far fa-folder",
+ folderOpen: "far fa-folder-open",
+ },
+ bootstrap3: {
+ _addClass: "glyphicon",
+ checkbox: "glyphicon-unchecked",
+ checkboxSelected: "glyphicon-check",
+ checkboxUnknown:
+ "glyphicon-expand fancytree-helper-indeterminate-cb", // "glyphicon-share",
+ dragHelper: "glyphicon-play",
+ dropMarker: "glyphicon-arrow-right",
+ error: "glyphicon-warning-sign",
+ expanderClosed: "glyphicon-menu-right", // glyphicon-plus-sign
+ expanderLazy: "glyphicon-menu-right", // glyphicon-plus-sign
+ expanderOpen: "glyphicon-menu-down", // glyphicon-minus-sign
+ loading: "glyphicon-refresh fancytree-helper-spin",
+ nodata: "glyphicon-info-sign",
+ noExpander: "",
+ radio: "glyphicon-remove-circle", // "glyphicon-unchecked",
+ radioSelected: "glyphicon-ok-circle", // "glyphicon-check",
+ // radioUnknown: "glyphicon-ban-circle",
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: "glyphicon-file",
+ docOpen: "glyphicon-file",
+ folder: "glyphicon-folder-close",
+ folderOpen: "glyphicon-folder-open",
+ },
+ material: {
+ _addClass: "material-icons",
+ checkbox: { text: "check_box_outline_blank" },
+ checkboxSelected: { text: "check_box" },
+ checkboxUnknown: { text: "indeterminate_check_box" },
+ dragHelper: { text: "play_arrow" },
+ dropMarker: { text: "arrow-forward" },
+ error: { text: "warning" },
+ expanderClosed: { text: "chevron_right" },
+ expanderLazy: { text: "last_page" },
+ expanderOpen: { text: "expand_more" },
+ loading: {
+ text: "autorenew",
+ addClass: "fancytree-helper-spin",
+ },
+ nodata: { text: "info" },
+ noExpander: { text: "" },
+ radio: { text: "radio_button_unchecked" },
+ radioSelected: { text: "radio_button_checked" },
+ // Default node icons.
+ // (Use tree.options.icon callback to define custom icons based on node data)
+ doc: { text: "insert_drive_file" },
+ docOpen: { text: "insert_drive_file" },
+ folder: { text: "folder" },
+ folderOpen: { text: "folder_open" },
+ },
+ };
+
+ function setIcon(node, span, baseClass, opts, type) {
+ var map = opts.map,
+ icon = map[type],
+ $span = $(span),
+ $counter = $span.find(".fancytree-childcounter"),
+ setClass = baseClass + " " + (map._addClass || "");
+
+ // #871 Allow a callback
+ if (typeof icon === "function") {
+ icon = icon.call(this, node, span, type);
+ }
+ // node.debug( "setIcon(" + baseClass + ", " + type + "): " + "oldIcon" + " -> " + icon );
+ // #871: propsed this, but I am not sure how robust this is, e.g.
+ // the prefix (fas, far) class changes are not considered?
+ // if (span.tagName === "svg" && opts.preset === "awesome5") {
+ // // fa5 script converts <i> to <svg> so call a specific handler.
+ // var oldIcon = "fa-" + $span.data("icon");
+ // // node.debug( "setIcon(" + baseClass + ", " + type + "): " + oldIcon + " -> " + icon );
+ // if (typeof oldIcon === "string") {
+ // $span.removeClass(oldIcon);
+ // }
+ // if (typeof icon === "string") {
+ // $span.addClass(icon);
+ // }
+ // return;
+ // }
+ if (typeof icon === "string") {
+ // #883: remove inner html that may be added by prev. mode
+ span.innerHTML = "";
+ $span.attr("class", setClass + " " + icon).append($counter);
+ } else if (icon) {
+ if (icon.text) {
+ span.textContent = "" + icon.text;
+ } else if (icon.html) {
+ span.innerHTML = icon.html;
+ } else {
+ span.innerHTML = "";
+ }
+ $span
+ .attr("class", setClass + " " + (icon.addClass || ""))
+ .append($counter);
+ }
+ }
+
+ $.ui.fancytree.registerExtension({
+ name: "glyph",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ preset: null, // 'awesome3', 'awesome4', 'bootstrap3', 'material'
+ map: {},
+ },
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ opts = ctx.options.glyph;
+
+ if (opts.preset) {
+ FT.assert(
+ !!PRESETS[opts.preset],
+ "Invalid value for `options.glyph.preset`: " + opts.preset
+ );
+ opts.map = $.extend({}, PRESETS[opts.preset], opts.map);
+ } else {
+ tree.warn("ext-glyph: missing `preset` option.");
+ }
+ this._superApply(arguments);
+ tree.$container.addClass("fancytree-ext-glyph");
+ },
+ nodeRenderStatus: function (ctx) {
+ var checkbox,
+ icon,
+ res,
+ span,
+ node = ctx.node,
+ $span = $(node.span),
+ opts = ctx.options.glyph;
+
+ res = this._super(ctx);
+
+ if (node.isRootNode()) {
+ return res;
+ }
+ span = $span.children(".fancytree-expander").get(0);
+ if (span) {
+ // if( node.isLoading() ){
+ // icon = "loading";
+ if (node.expanded && node.hasChildren()) {
+ icon = "expanderOpen";
+ } else if (node.isUndefined()) {
+ icon = "expanderLazy";
+ } else if (node.hasChildren()) {
+ icon = "expanderClosed";
+ } else {
+ icon = "noExpander";
+ }
+ // span.className = "fancytree-expander " + map[icon];
+ setIcon(node, span, "fancytree-expander", opts, icon);
+ }
+
+ if (node.tr) {
+ span = $("td", node.tr).find(".fancytree-checkbox").get(0);
+ } else {
+ span = $span.children(".fancytree-checkbox").get(0);
+ }
+ if (span) {
+ checkbox = FT.evalOption("checkbox", node, node, opts, false);
+ if (
+ (node.parent && node.parent.radiogroup) ||
+ checkbox === "radio"
+ ) {
+ icon = node.selected ? "radioSelected" : "radio";
+ setIcon(
+ node,
+ span,
+ "fancytree-checkbox fancytree-radio",
+ opts,
+ icon
+ );
+ } else {
+ // eslint-disable-next-line no-nested-ternary
+ icon = node.selected
+ ? "checkboxSelected"
+ : node.partsel
+ ? "checkboxUnknown"
+ : "checkbox";
+ // span.className = "fancytree-checkbox " + map[icon];
+ setIcon(node, span, "fancytree-checkbox", opts, icon);
+ }
+ }
+
+ // Standard icon (note that this does not match .fancytree-custom-icon,
+ // that might be set by opts.icon callbacks)
+ span = $span.children(".fancytree-icon").get(0);
+ if (span) {
+ if (node.statusNodeType) {
+ icon = node.statusNodeType; // loading, error
+ } else if (node.folder) {
+ icon =
+ node.expanded && node.hasChildren()
+ ? "folderOpen"
+ : "folder";
+ } else {
+ icon = node.expanded ? "docOpen" : "doc";
+ }
+ setIcon(node, span, "fancytree-icon", opts, icon);
+ }
+ return res;
+ },
+ nodeSetStatus: function (ctx, status, message, details) {
+ var res,
+ span,
+ opts = ctx.options.glyph,
+ node = ctx.node;
+
+ res = this._superApply(arguments);
+
+ if (
+ status === "error" ||
+ status === "loading" ||
+ status === "nodata"
+ ) {
+ if (node.parent) {
+ span = $(".fancytree-expander", node.span).get(0);
+ if (span) {
+ setIcon(node, span, "fancytree-expander", opts, status);
+ }
+ } else {
+ //
+ span = $(
+ ".fancytree-statusnode-" + status,
+ node[this.nodeContainerAttrName]
+ )
+ .find(".fancytree-icon")
+ .get(0);
+ if (span) {
+ setIcon(node, span, "fancytree-icon", opts, status);
+ }
+ }
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.grid.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.grid.js
new file mode 100644
index 0000000..73e53cd
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.grid.js
@@ -0,0 +1,1014 @@
+/*!
+ * jquery.fancytree.grid.js
+ *
+ * Render tree as table (aka 'tree grid', 'table tree').
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var FT = $.ui.fancytree,
+ _assert = FT.assert,
+ SCROLL_MODE = "wheel"; // 'wheel' | 'scroll'
+ // EPS = 1.0;
+
+ /*
+ * [ext-grid] ...
+ *
+ * @alias Fancytree#_addScrollbar
+ * @requires jquery.fancytree.grid.js
+ */
+ function _addScrollbar(table) {
+ var sbWidth = 10,
+ $table = $(table),
+ position = $table.position(),
+ // top = $table.find("tbody").position().top,
+
+ $sb = $("<div>", {
+ class: "fancytree-scrollbar",
+ css: {
+ border: "1px solid gray",
+ position: "absolute",
+ top: position.top,
+ left: position.left + $table.width(),
+ width: sbWidth,
+ height: $table.find("tbody").height(),
+ },
+ });
+
+ $table
+ .css({
+ "margin-right": sbWidth,
+ })
+ .after($sb);
+
+ return $sb;
+ }
+
+ /*
+ * [ext-grid] Invalidate renumber status, i.e. trigger renumber next time.
+ *
+ * @alias Fancytree#_renumberReset
+ * @requires jquery.fancytree.grid.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype._renumberReset = function () {
+ // this.debug("_renumberReset()");
+ this.visibleNodeList = null;
+ };
+
+ /*
+ * [ext-grid] Adjust the start value if the content would be outside otherwise.
+ *
+ * @alias Fancytree#_fixStart
+ * @requires jquery.fancytree.grid.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype._fixStart = function (
+ start,
+ apply
+ ) {
+ var vp = this.viewport,
+ nodeList = this.visibleNodeList;
+
+ start = start == null ? vp.start : start;
+ // this.debug("_fixStart(" + start + ", " + !!apply + ")");
+ var orgStart = start;
+ // Don't scroll down below bottom node
+ if (nodeList) {
+ start = Math.min(start, this.visibleNodeList.length - vp.count);
+ start = Math.max(start, 0, start);
+ if (start !== orgStart) {
+ this.debug("Adjust start " + orgStart + " => " + start);
+ if (apply) {
+ vp.start = start;
+ }
+ }
+ }
+ return start;
+ };
+
+ /*
+ * [ext-grid] ...
+ *
+ * @alias Fancytree#_shiftViewport
+ * @requires jquery.fancytree.grid.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype._shiftViewport = function (
+ mode,
+ ofs
+ ) {
+ this.debug("_shiftViewport", mode, ofs);
+ switch (mode) {
+ case "vscroll":
+ if (ofs) {
+ this.setViewport({
+ start: this.viewport.start + (ofs > 0 ? 1 : -1),
+ });
+ }
+ break;
+
+ default:
+ throw Error("Invalid mode: " + mode);
+ }
+ };
+
+ /**
+ * [ext-grid] Return true if viewport cannot be scrolled down any further.
+ *
+ * @alias Fancytree#isViewportBottom
+ * @requires jquery.fancytree.grid.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.isViewportBottom = function () {
+ return (
+ this.viewport.start + this.viewport.count >=
+ this.visibleNodeList.length
+ );
+ };
+
+ /**
+ * [ext-grid] Define a subset of rows/columns to display and redraw.
+ *
+ * @param {object | boolean} options viewport boundaries and status.
+ *
+ * @alias Fancytree#setViewport
+ * @requires jquery.fancytree.grid.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.setViewport = function (opts) {
+ if (typeof opts === "boolean") {
+ this.debug("setViewport( " + opts + ")");
+ return this.setViewport({ enabled: opts });
+ }
+ opts = opts || {};
+ var i,
+ count,
+ start,
+ newRow,
+ redrawReason = "",
+ vp = this.viewport,
+ diffVp = { start: 0, count: 0, enabled: null, force: null },
+ newVp = $.extend({}, vp),
+ trList = this.tbody.children,
+ trCount = trList.length;
+
+ // Sanitize viewport settings and check if we need to redraw
+ this.debug("setViewport(" + opts.start + ", +" + opts.count + ")");
+ if (opts.force) {
+ redrawReason += "force";
+ diffVp.force = true;
+ }
+
+ opts.enabled = opts.enabled !== false; // default to true
+ if (vp.enabled !== opts.enabled) {
+ redrawReason += "enable";
+ newVp.enabled = diffVp.enabled = opts.enabled;
+ }
+
+ start = opts.start == null ? vp.start : Math.max(0, +opts.start);
+ // Adjust start value to assure the current content is inside vp
+ start = this._fixStart(start, false);
+
+ if (vp.start !== +start) {
+ redrawReason += "start";
+ newVp.start = start;
+ diffVp.start = start - vp.start;
+ }
+
+ count = opts.count == null ? vp.count : Math.max(1, +opts.count);
+ if (vp.count !== +count) {
+ redrawReason += "count";
+ newVp.count = count;
+ diffVp.count = count - vp.count;
+ }
+ // if (vp.left !== +opts.left) {
+ // diffVp.left = left - vp.left;
+ // newVp.left = opts.left;
+ // redrawReason += "left";
+ // }
+ // if (vp.right !== +opts.right) {
+ // diffVp.right = right - vp.right;
+ // newVp.right = opts.right;
+ // redrawReason += "right";
+ // }
+
+ if (!redrawReason) {
+ return false;
+ }
+ // Let user cancel or modify the update
+ var info = {
+ next: newVp,
+ diff: diffVp,
+ reason: redrawReason,
+ scrollOnly: redrawReason === "start",
+ };
+ if (
+ !opts.noEvents &&
+ this._triggerTreeEvent("beforeUpdateViewport", null, info) === false
+ ) {
+ return false;
+ }
+ info.prev = $.extend({}, vp);
+ delete info.next;
+ // vp.enabled = newVp.enabled;
+ vp.start = newVp.start;
+ vp.count = newVp.count;
+
+ // Make sure we have the correct count of TRs
+ var prevPhase = this.isVpUpdating;
+
+ if (trCount > count) {
+ for (i = 0; i < trCount - count; i++) {
+ delete this.tbody.lastChild.ftnode;
+ this.tbody.removeChild(this.tbody.lastChild);
+ }
+ } else if (trCount < count) {
+ for (i = 0; i < count - trCount; i++) {
+ newRow = this.rowFragment.firstChild.cloneNode(true);
+ this.tbody.appendChild(newRow);
+ }
+ }
+ trCount = trList.length;
+
+ // Update visible node cache if needed
+ var force = opts.force;
+ this.redrawViewport(force);
+
+ if (!opts.noEvents) {
+ this._triggerTreeEvent("updateViewport", null, info);
+ }
+
+ this.isVpUpdating = prevPhase;
+ return true;
+ };
+
+ /**
+ * [ext-grid] Calculate the viewport count from current scroll wrapper height.
+ *
+ * @alias Fancytree#adjustViewportSize
+ * @requires jquery.fancytree.grid.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.adjustViewportSize = function () {
+ _assert(
+ this.scrollWrapper,
+ "No parent div.fancytree-grid-container found."
+ );
+ if (this.isVpUpdating) {
+ this.debug("Ignoring adjustViewportSize() during VP update.");
+ return;
+ }
+ // Calculate how many rows fit into current container height
+ var $table = this.$container,
+ wrapper = this.scrollWrapper,
+ trHeight = $table.find(">tbody>tr").first().height() || 0,
+ tableHeight = $table.height(),
+ headHeight = tableHeight - this.viewport.count * trHeight,
+ wrapperHeight = wrapper.offsetHeight,
+ free = wrapperHeight - headHeight,
+ newCount = trHeight ? Math.floor(free / trHeight) : 0;
+
+ // console.info(
+ // "set container height",
+ // $(this)
+ // .parent(".fancytree-grid-container")
+ // .height()
+ // );
+
+ this.setViewport({ count: newCount });
+ // if (SCROLL_MODE === "scroll") {
+ // // Add bottom margin to the table, to make sure the wrapper becomes
+ // // scrollable
+ // var mb = wrapperHeight - $table.height() - 2.0 * EPS;
+ // this.debug("margin-bottom=" + mb);
+ // $table.css("margin-bottom", mb);
+ // }
+ };
+
+ /*
+ * [ext-grid] Calculate the scroll container dimension from the current tree table.
+ *
+ * @alias Fancytree#initViewportWrapper
+ * @requires jquery.fancytree.grid.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype._initViewportWrapper =
+ function () {
+ var // wrapper = this.scrollWrapper,
+ // $wrapper = $(wrapper),
+ tree = this;
+
+ // if (SCROLL_MODE === "scroll") {
+ // $wrapper.on("scroll", function(e) {
+ // var viewport = tree.viewport,
+ // curTop = wrapper.scrollTop,
+ // homeTop = viewport.start === 0 ? 0 : EPS,
+ // dy = viewport.start === 0 ? 1 : curTop - EPS; //homeTop;
+
+ // tree.debug(
+ // "Got 'scroll' event: scrollTop=" +
+ // curTop +
+ // ", homeTop=" +
+ // homeTop +
+ // ", start=" +
+ // viewport.start +
+ // ", dy=" +
+ // dy
+ // );
+ // if (tree.isVpUpdating) {
+ // tree.debug("Ignoring scroll during VP update.");
+ // return;
+ // } else if (curTop === homeTop) {
+ // tree.debug("Ignoring scroll to neutral " + homeTop + ".");
+ // return;
+ // }
+ // tree._shiftViewport("vscroll", dy);
+ // homeTop = viewport.start === 0 ? 0 : EPS;
+ // setTimeout(function() {
+ // tree.debug(
+ // "scrollTop(" +
+ // wrapper.scrollTop +
+ // " -> " +
+ // homeTop +
+ // ")..."
+ // );
+ // wrapper.scrollTop = homeTop;
+ // }, 0);
+ // });
+ // }
+ if (SCROLL_MODE === "wheel") {
+ this.$container.on("wheel", function (e) {
+ var orgEvent = e.originalEvent,
+ viewport = tree.viewport,
+ dy = orgEvent.deltaY; // * orgEvent.wheelDeltaY;
+
+ if (
+ !dy ||
+ e.altKey ||
+ e.ctrlKey ||
+ e.metaKey ||
+ e.shiftKey
+ ) {
+ return true;
+ }
+ if (dy < 0 && viewport.start === 0) {
+ return true;
+ }
+ if (dy > 0 && tree.isViewportBottom()) {
+ return true;
+ }
+ tree.debug(
+ "Got 'wheel' event: dy=" +
+ dy +
+ ", mode=" +
+ orgEvent.deltaMode
+ );
+ tree._shiftViewport("vscroll", dy);
+ return false;
+ });
+ }
+ };
+
+ /*
+ * [ext-grid] Renumber and collect all visible rows.
+ *
+ * @param {bool} [force=false]
+ * @param {FancytreeNode | int} [startIdx=0]
+ * @alias Fancytree#_renumberVisibleNodes
+ * @requires jquery.fancytree.grid.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype._renumberVisibleNodes = function (
+ force,
+ startIdx
+ ) {
+ if (
+ (!this.options.viewport.enabled || this.visibleNodeList != null) &&
+ force !== true
+ ) {
+ // this.debug("_renumberVisibleNodes() ignored.");
+ return false;
+ }
+ this.debugTime("_renumberVisibleNodes()");
+ var i = 0,
+ prevLength = this.visibleNodeList ? this.visibleNodeList.length : 0,
+ visibleNodeList = (this.visibleNodeList = []);
+
+ // Reset previous data
+ this.visit(function (node) {
+ node._rowIdx = null;
+ // node.span = null;
+ // if (node.tr) {
+ // delete node.tr.ftnode;
+ // node.tr = null;
+ // }
+ });
+ // Iterate over all *visible* nodes
+ this.visitRows(function (node) {
+ node._rowIdx = i++;
+ visibleNodeList.push(node);
+ });
+ this.debugTimeEnd("_renumberVisibleNodes()");
+ if (i !== prevLength) {
+ this._triggerTreeEvent("updateViewport", null, {
+ reason: "renumber",
+ diff: { start: 0, count: 0, enabled: null, force: null },
+ next: $.extend({}, this.viewport),
+ // visibleCount: prevLength,
+ // cur: i,
+ });
+ }
+ };
+
+ /**
+ * [ext-grid] Render all visible nodes into the viweport.
+ *
+ * @param {bool} [force=false]
+ * @alias Fancytree#redrawViewport
+ * @requires jquery.fancytree.grid.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.redrawViewport = function (force) {
+ if (this._enableUpdate === false) {
+ // tree.debug("no render", tree._enableUpdate);
+ return;
+ }
+ this.debugTime("redrawViewport()");
+ this._renumberVisibleNodes(force);
+ // Adjust vp.start value to assure the current content is inside:
+ this._fixStart(null, true);
+
+ var i = 0,
+ vp = this.viewport,
+ visibleNodeList = this.visibleNodeList,
+ start = vp.start,
+ bottom = start + vp.count,
+ tr,
+ _renderCount = 0,
+ trIdx = 0,
+ trList = this.tbody.children,
+ prevPhase = this.isVpUpdating;
+
+ // Reset previous data
+ this.visit(function (node) {
+ // node.debug("redrawViewport(): _rowIdx=" + node._rowIdx);
+ node.span = null;
+ if (node.tr) {
+ delete node.tr.ftnode;
+ node.tr = null;
+ }
+ });
+
+ // Redraw the whole tree, erasing all node markup before and after
+ // the viewport
+
+ for (i = start; i < bottom; i++) {
+ var node = visibleNodeList[i];
+
+ tr = trList[trIdx];
+
+ if (!node) {
+ // TODO: make trailing empty rows configurable (custom template or remove TRs)
+ var newRow = this.rowFragment.firstChild.cloneNode(true);
+ this.tbody.replaceChild(newRow, tr);
+ trIdx++;
+ continue;
+ }
+ if (tr !== node.tr) {
+ node.tr = tr;
+ node.render();
+ _renderCount++;
+
+ // TODO:
+ // Implement scrolling by re-using existing markup
+ // e.g. shifting TRs or TR child elements instead of
+ // re-creating all the time
+ }
+ trIdx++;
+ }
+ this.isVpUpdating = prevPhase;
+ this.debugTimeEnd("redrawViewport()");
+ };
+
+ $.ui.fancytree.registerExtension({
+ name: "grid",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx)
+ indentation: 16, // indent every node level by 16px
+ mergeStatusColumns: true, // display 'nodata', 'loading', 'error' centered in a single, merged TR
+ nodeColumnIdx: 0, // render node expander, icon, and title to this column (default: #0)
+ },
+ // Overide virtual methods for this extension.
+ // `this` : is this extension object
+ // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
+ treeInit: function (ctx) {
+ var i,
+ columnCount,
+ n,
+ $row,
+ $tbody,
+ tree = ctx.tree,
+ opts = ctx.options,
+ tableOpts = opts.table,
+ $table = tree.widget.element,
+ $scrollWrapper = $table.parent(".fancytree-grid-container");
+
+ if ($.inArray("table", opts.extensions) >= 0) {
+ $.error("ext-grid and ext-table are mutually exclusive.");
+ }
+ if (opts.renderStatusColumns === true) {
+ opts.renderStatusColumns = opts.renderColumns;
+ }
+ // Note: we also re-use CSS rules from ext-table
+ $table.addClass(
+ "fancytree-container fancytree-ext-grid fancytree-ext-table"
+ );
+ $tbody = $table.find(">tbody");
+ if (!$tbody.length) {
+ // TODO: not sure if we can rely on browsers to insert missing <tbody> before <tr>s:
+ if ($table.find(">tr").length) {
+ $.error(
+ "Expected table > tbody > tr. If you see this, please open an issue."
+ );
+ }
+ $tbody = $("<tbody>").appendTo($table);
+ }
+
+ tree.tbody = $tbody[0];
+
+ // Prepare row templates:
+ // Determine column count from table header if any
+ columnCount = $("thead >tr", $table).last().find(">th").length;
+ // Read TR templates from tbody if any
+ $row = $tbody.children("tr").first();
+ if ($row.length) {
+ n = $row.children("td").length;
+ if (columnCount && n !== columnCount) {
+ tree.warn(
+ "Column count mismatch between thead (" +
+ columnCount +
+ ") and tbody (" +
+ n +
+ "): using tbody."
+ );
+ columnCount = n;
+ }
+ $row = $row.clone();
+ } else {
+ // Only thead is defined: create default row markup
+ _assert(
+ columnCount >= 1,
+ "Need either <thead> or <tbody> with <td> elements to determine column count."
+ );
+ $row = $("<tr />");
+ for (i = 0; i < columnCount; i++) {
+ $row.append("<td />");
+ }
+ }
+ $row.find(">td")
+ .eq(tableOpts.nodeColumnIdx)
+ .html("<span class='fancytree-node' />");
+ if (opts.aria) {
+ $row.attr("role", "row");
+ $row.find("td").attr("role", "gridcell");
+ }
+ tree.rowFragment = document.createDocumentFragment();
+ tree.rowFragment.appendChild($row.get(0));
+
+ $tbody.empty();
+
+ // Make sure that status classes are set on the node's <tr> elements
+ tree.statusClassPropName = "tr";
+ tree.ariaPropName = "tr";
+ this.nodeContainerAttrName = "tr";
+
+ // #489: make sure $container is set to <table>, even if ext-dnd is listed before ext-grid
+ tree.$container = $table;
+ if ($scrollWrapper.length) {
+ tree.scrollWrapper = $scrollWrapper[0];
+ this._initViewportWrapper();
+ } else {
+ tree.scrollWrapper = null;
+ }
+
+ // Scrolling is implemented completely differently here
+ $.ui.fancytree.overrideMethod(
+ $.ui.fancytree._FancytreeNodeClass.prototype,
+ "scrollIntoView",
+ function (effects, options) {
+ var node = this,
+ tree = node.tree,
+ topNode = options && options.topNode,
+ vp = tree.viewport,
+ start = vp ? vp.start : null;
+
+ if (!tree.viewport) {
+ return node._super.apply(this, arguments);
+ }
+ if (node._rowIdx < vp.start) {
+ start = node._rowIdx;
+ } else if (node._rowIdx >= vp.start + vp.count) {
+ start = node._rowIdx - vp.count + 1;
+ }
+ if (topNode && topNode._rowIdx < start) {
+ start = topNode._rowIdx;
+ }
+ tree.setViewport({ start: start });
+ // Return a resolved promise
+ return $.Deferred(function () {
+ this.resolveWith(node);
+ }).promise();
+ }
+ );
+
+ tree.visibleNodeList = null; // Set by _renumberVisibleNodes()
+ tree.viewport = {
+ enabled: true,
+ start: 0,
+ count: 10,
+ left: 0,
+ right: 0,
+ };
+ this.setViewport(
+ $.extend(
+ {
+ // enabled: true,
+ autoSize: true,
+ start: 0,
+ count: 10,
+ left: 0,
+ right: 0,
+ keepEmptyRows: true,
+ noEvents: true,
+ },
+ opts.viewport
+ )
+ );
+ // tree.$scrollbar = _addScrollbar($table);
+
+ this._superApply(arguments);
+
+ // standard Fancytree created a root UL
+ $(tree.rootNode.ul).remove();
+ tree.rootNode.ul = null;
+
+ // Add container to the TAB chain
+ // #577: Allow to set tabindex to "0", "-1" and ""
+ this.$container.attr("tabindex", opts.tabindex);
+ // this.$container.attr("tabindex", opts.tabbable ? "0" : "-1");
+ if (opts.aria) {
+ tree.$container
+ .attr("role", "treegrid")
+ .attr("aria-readonly", true);
+ }
+ },
+ nodeKeydown: function (ctx) {
+ var nextNode = null,
+ nextIdx = null,
+ tree = ctx.tree,
+ node = ctx.node,
+ nodeList = tree.visibleNodeList,
+ // treeOpts = ctx.options,
+ viewport = tree.viewport,
+ event = ctx.originalEvent,
+ eventString = FT.eventToString(event);
+
+ tree.debug("nodeKeydown(" + eventString + ")");
+
+ switch (eventString) {
+ case "home":
+ case "meta+up":
+ nextIdx = 0;
+ break;
+ case "end":
+ case "meta+down":
+ nextIdx = nodeList.length - 1;
+ break;
+ case "pageup":
+ nextIdx = node._rowIdx - viewport.count;
+ break;
+ case "pagedown":
+ nextIdx = node._rowIdx + viewport.count;
+ break;
+ }
+ if (nextIdx != null) {
+ nextIdx = Math.min(Math.max(0, nextIdx), nodeList.length - 1);
+ nextNode = nodeList[nextIdx];
+ nextNode.makeVisible();
+ nextNode.setActive();
+ return false;
+ }
+ return this._superApply(arguments);
+ },
+ nodeRemoveChildMarkup: function (ctx) {
+ var node = ctx.node;
+
+ node.visit(function (n) {
+ if (n.tr) {
+ delete n.tr.ftnode;
+ n.tr = null;
+ n.span = null;
+ }
+ });
+ },
+ nodeRemoveMarkup: function (ctx) {
+ var node = ctx.node;
+
+ if (node.tr) {
+ delete node.tr.ftnode;
+ node.tr = null;
+ node.span = null;
+ }
+ this.nodeRemoveChildMarkup(ctx);
+ },
+ /* Override standard render. */
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ var children,
+ i,
+ l,
+ outsideViewport,
+ subCtx,
+ tree = ctx.tree,
+ node = ctx.node;
+
+ if (tree._enableUpdate === false) {
+ node.debug("nodeRender(): _enableUpdate: false");
+ return;
+ }
+ var opts = ctx.options,
+ viewport = tree.viewport.enabled ? tree.viewport : null,
+ start = viewport && viewport.start > 0 ? +viewport.start : 0,
+ bottom = viewport ? start + viewport.count - 1 : 0,
+ isRootNode = !node.parent;
+
+ _assert(viewport);
+
+ // node.debug("nodeRender(): " + node + ", isRoot=" + isRootNode, "tr=" + node.tr, "hcp=" + ctx.hasCollapsedParents, "parent.tr=" + (node.parent && node.parent.tr));
+ if (!_recursive) {
+ // node.debug("nodeRender(): start top node");
+ if (isRootNode && viewport) {
+ node.debug("nodeRender(): redrawViewport() instead");
+ return ctx.tree.redrawViewport();
+ }
+ ctx.hasCollapsedParents = node.parent && !node.parent.expanded;
+ // Make sure visible row indices are up-to-date
+ if (viewport) {
+ tree._renumberVisibleNodes();
+ }
+ }
+
+ if (!isRootNode) {
+ outsideViewport =
+ viewport &&
+ (node._rowIdx < start ||
+ node._rowIdx >= start + viewport.count);
+
+ // node.debug(
+ // "nodeRender(): idx=" +
+ // node._rowIdx +
+ // ", outside=" +
+ // outsideViewport +
+ // ", TR count=" +
+ // tree.tbody.rows.length
+ // );
+ if (outsideViewport) {
+ // node.debug("nodeRender(): outsideViewport: ignored");
+ return;
+ }
+ if (!node.tr) {
+ if (node._rowIdx == null) {
+ // node.warn("nodeRender(): ignoring hidden");
+ return;
+ }
+ node.debug("nodeRender(): creating new TR.");
+ node.tr = tree.tbody.rows[node._rowIdx - start];
+ }
+ // _assert(
+ // node.tr,
+ // "nodeRender() called for node.tr == null: " + node
+ // );
+ node.tr.ftnode = node;
+
+ if (node.key && opts.generateIds) {
+ node.tr.id = opts.idPrefix + node.key;
+ }
+ node.span = $("span.fancytree-node", node.tr).get(0);
+
+ // Set icon, link, and title (normally this is only required on initial render)
+ // var ctx = this._makeHookContext(node);
+ this.nodeRenderTitle(ctx); // triggers renderColumns()
+
+ // Allow tweaking, binding, after node was created for the first time
+ if (opts.createNode) {
+ opts.createNode.call(this, { type: "createNode" }, ctx);
+ }
+ }
+ // Allow tweaking after node state was rendered
+ if (opts.renderNode) {
+ opts.renderNode.call(tree, { type: "renderNode" }, ctx);
+ }
+ // Visit child nodes
+ // Add child markup
+ children = node.children;
+ _assert(!deep, "deep is not supported");
+
+ if (children && (isRootNode || deep || node.expanded)) {
+ for (i = 0, l = children.length; i < l; i++) {
+ var child = children[i];
+
+ if (viewport && child._rowIdx > bottom) {
+ children[i].debug("BREAK render children loop");
+ return false;
+ }
+ subCtx = $.extend({}, ctx, { node: child });
+ subCtx.hasCollapsedParents =
+ subCtx.hasCollapsedParents || !node.expanded;
+ this.nodeRender(subCtx, force, deep, collapsed, true);
+ }
+ }
+ },
+ nodeRenderTitle: function (ctx, title) {
+ var $cb,
+ res,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = ctx.options,
+ isStatusNode = node.isStatusNode();
+
+ res = this._super(ctx, title);
+
+ if (node.isRootNode()) {
+ return res;
+ }
+ // Move checkbox to custom column
+ if (
+ opts.checkbox &&
+ !isStatusNode &&
+ opts.table.checkboxColumnIdx != null
+ ) {
+ $cb = $("span.fancytree-checkbox", node.span); //.detach();
+ $(node.tr)
+ .find("td")
+ .eq(+opts.table.checkboxColumnIdx)
+ .html($cb);
+ }
+ // Update element classes according to node state
+ this.nodeRenderStatus(ctx);
+
+ if (isStatusNode) {
+ if (opts.renderStatusColumns) {
+ // Let user code write column content
+ opts.renderStatusColumns.call(
+ tree,
+ { type: "renderStatusColumns" },
+ ctx
+ );
+ } else if (opts.grid.mergeStatusColumns && node.isTopLevel()) {
+ node.warn("mergeStatusColumns is not yet implemented.");
+ // This approach would not work, since the roe may be re-used:
+ // $(node.tr)
+ // .find(">td")
+ // .eq(0)
+ // .prop("colspan", tree.columnCount)
+ // .text(node.title)
+ // .addClass("fancytree-status-merged")
+ // .nextAll()
+ // .remove();
+ } // else: default rendering for status node: leave other cells empty
+ } else if (opts.renderColumns) {
+ opts.renderColumns.call(tree, { type: "renderColumns" }, ctx);
+ }
+ return res;
+ },
+ nodeRenderStatus: function (ctx) {
+ var indent,
+ node = ctx.node,
+ opts = ctx.options;
+
+ this._super(ctx);
+
+ $(node.tr).removeClass("fancytree-node");
+ // indent
+ indent = (node.getLevel() - 1) * opts.table.indentation;
+ if (opts.rtl) {
+ $(node.span).css({ paddingRight: indent + "px" });
+ } else {
+ $(node.span).css({ paddingLeft: indent + "px" });
+ }
+ },
+ /* Expand node, return Deferred.promise. */
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var node = ctx.node,
+ tree = ctx.tree;
+
+ // flag defaults to true
+ flag = flag !== false;
+
+ if ((node.expanded && flag) || (!node.expanded && !flag)) {
+ // Expanded state isn't changed - just call base implementation
+ return this._superApply(arguments);
+ }
+
+ var dfd = new $.Deferred(),
+ subOpts = $.extend({}, callOpts, {
+ noEvents: true,
+ noAnimation: true,
+ });
+
+ callOpts = callOpts || {};
+
+ function _afterExpand(ok) {
+ tree.redrawViewport(true);
+
+ if (ok) {
+ if (
+ flag &&
+ ctx.options.autoScroll &&
+ !callOpts.noAnimation &&
+ node.hasChildren()
+ ) {
+ // Scroll down to last child, but keep current node visible
+ node.getLastChild()
+ .scrollIntoView(true, { topNode: node })
+ .always(function () {
+ if (!callOpts.noEvents) {
+ tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.resolveWith(node);
+ });
+ } else {
+ if (!callOpts.noEvents) {
+ tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.resolveWith(node);
+ }
+ } else {
+ if (!callOpts.noEvents) {
+ tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.rejectWith(node);
+ }
+ }
+ // Call base-expand with disabled events and animation
+ this._super(ctx, flag, subOpts)
+ .done(function () {
+ _afterExpand(true);
+ })
+ .fail(function () {
+ _afterExpand(false);
+ });
+ return dfd.promise();
+ },
+ treeClear: function (ctx) {
+ // this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode));
+ // this._renumberReset(); // Invalidate visible row cache
+ return this._superApply(arguments);
+ },
+ treeDestroy: function (ctx) {
+ this.$container.find("tbody").empty();
+ this.$container.off("wheel");
+ if (this.$source) {
+ this.$source.removeClass("fancytree-helper-hidden");
+ }
+ this._renumberReset(); // Invalidate visible row cache
+ return this._superApply(arguments);
+ },
+ treeStructureChanged: function (ctx, type) {
+ // debugger;
+ if (type !== "addNode" || ctx.tree.visibleNodeList) {
+ // this.debug("treeStructureChanged(" + type + ")");
+ this._renumberReset(); // Invalidate visible row cache
+ }
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.gridnav.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.gridnav.js
new file mode 100644
index 0000000..7ffbb67
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.gridnav.js
@@ -0,0 +1,218 @@
+/*!
+ * jquery.fancytree.gridnav.js
+ *
+ * Support keyboard navigation for trees with embedded input controls.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([
+ "jquery",
+ "./jquery.fancytree",
+ "./jquery.fancytree.table",
+ ], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree.table"); // core + table
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ // Allow these navigation keys even when input controls are focused
+
+ var KC = $.ui.keyCode,
+ // which keys are *not* handled by embedded control, but passed to tree
+ // navigation handler:
+ NAV_KEYS = {
+ text: [KC.UP, KC.DOWN],
+ checkbox: [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+ link: [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+ radiobutton: [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT],
+ "select-one": [KC.LEFT, KC.RIGHT],
+ "select-multiple": [KC.LEFT, KC.RIGHT],
+ };
+
+ /* Calculate TD column index (considering colspans).*/
+ function getColIdx($tr, $td) {
+ var colspan,
+ td = $td.get(0),
+ idx = 0;
+
+ $tr.children().each(function () {
+ if (this === td) {
+ return false;
+ }
+ colspan = $(this).prop("colspan");
+ idx += colspan ? colspan : 1;
+ });
+ return idx;
+ }
+
+ /* Find TD at given column index (considering colspans).*/
+ function findTdAtColIdx($tr, colIdx) {
+ var colspan,
+ res = null,
+ idx = 0;
+
+ $tr.children().each(function () {
+ if (idx >= colIdx) {
+ res = $(this);
+ return false;
+ }
+ colspan = $(this).prop("colspan");
+ idx += colspan ? colspan : 1;
+ });
+ return res;
+ }
+
+ /* Find adjacent cell for a given direction. Skip empty cells and consider merged cells */
+ function findNeighbourTd($target, keyCode) {
+ var $tr,
+ colIdx,
+ $td = $target.closest("td"),
+ $tdNext = null;
+
+ switch (keyCode) {
+ case KC.LEFT:
+ $tdNext = $td.prev();
+ break;
+ case KC.RIGHT:
+ $tdNext = $td.next();
+ break;
+ case KC.UP:
+ case KC.DOWN:
+ $tr = $td.parent();
+ colIdx = getColIdx($tr, $td);
+ while (true) {
+ $tr = keyCode === KC.UP ? $tr.prev() : $tr.next();
+ if (!$tr.length) {
+ break;
+ }
+ // Skip hidden rows
+ if ($tr.is(":hidden")) {
+ continue;
+ }
+ // Find adjacent cell in the same column
+ $tdNext = findTdAtColIdx($tr, colIdx);
+ // Skip cells that don't conatain a focusable element
+ if ($tdNext && $tdNext.find(":input,a").length) {
+ break;
+ }
+ }
+ break;
+ }
+ return $tdNext;
+ }
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "gridnav",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ autofocusInput: false, // Focus first embedded input if node gets activated
+ handleCursorKeys: true, // Allow UP/DOWN in inputs to move to prev/next node
+ },
+
+ treeInit: function (ctx) {
+ // gridnav requires the table extension to be loaded before itself
+ this._requireExtension("table", true, true);
+ this._superApply(arguments);
+
+ this.$container.addClass("fancytree-ext-gridnav");
+
+ // Activate node if embedded input gets focus (due to a click)
+ this.$container.on("focusin", function (event) {
+ var ctx2,
+ node = $.ui.fancytree.getNode(event.target);
+
+ if (node && !node.isActive()) {
+ // Call node.setActive(), but also pass the event
+ ctx2 = ctx.tree._makeHookContext(node, event);
+ ctx.tree._callHook("nodeSetActive", ctx2, true);
+ }
+ });
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var $outer,
+ opts = ctx.options.gridnav,
+ node = ctx.node,
+ event = ctx.originalEvent || {},
+ triggeredByInput = $(event.target).is(":input");
+
+ flag = flag !== false;
+
+ this._superApply(arguments);
+
+ if (flag) {
+ if (ctx.options.titlesTabbable) {
+ if (!triggeredByInput) {
+ $(node.span).find("span.fancytree-title").focus();
+ node.setFocus();
+ }
+ // If one node is tabbable, the container no longer needs to be
+ ctx.tree.$container.attr("tabindex", "-1");
+ // ctx.tree.$container.removeAttr("tabindex");
+ } else if (opts.autofocusInput && !triggeredByInput) {
+ // Set focus to input sub input (if node was clicked, but not
+ // when TAB was pressed )
+ $outer = $(node.tr || node.span);
+ $outer.find(":input:enabled").first().focus();
+ }
+ }
+ },
+ nodeKeydown: function (ctx) {
+ var inputType,
+ handleKeys,
+ $td,
+ opts = ctx.options.gridnav,
+ event = ctx.originalEvent,
+ $target = $(event.target);
+
+ if ($target.is(":input:enabled")) {
+ inputType = $target.prop("type");
+ } else if ($target.is("a")) {
+ inputType = "link";
+ }
+ // ctx.tree.debug("ext-gridnav nodeKeydown", event, inputType);
+
+ if (inputType && opts.handleCursorKeys) {
+ handleKeys = NAV_KEYS[inputType];
+ if (handleKeys && $.inArray(event.which, handleKeys) >= 0) {
+ $td = findNeighbourTd($target, event.which);
+ if ($td && $td.length) {
+ // ctx.node.debug("ignore keydown in input", event.which, handleKeys);
+ $td.find(":input:enabled,a").focus();
+ // Prevent Fancytree default navigation
+ return false;
+ }
+ }
+ return true;
+ }
+ // ctx.tree.debug("ext-gridnav NOT HANDLED", event, inputType);
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.js
new file mode 100644
index 0000000..ada9aeb
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.js
@@ -0,0 +1,7374 @@
+/*!
+ * jquery.fancytree.js
+ * Tree view control with support for lazy loading and much more.
+ * https://github.com/mar10/fancytree/
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+/** Core Fancytree module.
+ */
+
+// UMD wrapper for the Fancytree core module
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree.ui-deps"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree.ui-deps");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ // prevent duplicate loading
+ if ($.ui && $.ui.fancytree) {
+ $.ui.fancytree.warn("Fancytree: ignored duplicate include");
+ return;
+ }
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+
+ var i,
+ attr,
+ FT = null, // initialized below
+ TEST_IMG = new RegExp(/\.|\//), // strings are considered image urls if they contain '.' or '/'
+ REX_HTML = /[&<>"'/]/g, // Escape those characters
+ REX_TOOLTIP = /[<>"'/]/g, // Don't escape `&` in tooltips
+ RECURSIVE_REQUEST_ERROR = "$recursive_request",
+ INVALID_REQUEST_TARGET_ERROR = "$request_target_invalid",
+ ENTITY_MAP = {
+ "&": "&amp;",
+ "<": "&lt;",
+ ">": "&gt;",
+ '"': "&quot;",
+ "'": "&#39;",
+ "/": "&#x2F;",
+ },
+ IGNORE_KEYCODES = { 16: true, 17: true, 18: true },
+ SPECIAL_KEYCODES = {
+ 8: "backspace",
+ 9: "tab",
+ 10: "return",
+ 13: "return",
+ // 16: null, 17: null, 18: null, // ignore shift, ctrl, alt
+ 19: "pause",
+ 20: "capslock",
+ 27: "esc",
+ 32: "space",
+ 33: "pageup",
+ 34: "pagedown",
+ 35: "end",
+ 36: "home",
+ 37: "left",
+ 38: "up",
+ 39: "right",
+ 40: "down",
+ 45: "insert",
+ 46: "del",
+ 59: ";",
+ 61: "=",
+ // 91: null, 93: null, // ignore left and right meta
+ 96: "0",
+ 97: "1",
+ 98: "2",
+ 99: "3",
+ 100: "4",
+ 101: "5",
+ 102: "6",
+ 103: "7",
+ 104: "8",
+ 105: "9",
+ 106: "*",
+ 107: "+",
+ 109: "-",
+ 110: ".",
+ 111: "/",
+ 112: "f1",
+ 113: "f2",
+ 114: "f3",
+ 115: "f4",
+ 116: "f5",
+ 117: "f6",
+ 118: "f7",
+ 119: "f8",
+ 120: "f9",
+ 121: "f10",
+ 122: "f11",
+ 123: "f12",
+ 144: "numlock",
+ 145: "scroll",
+ 173: "-",
+ 186: ";",
+ 187: "=",
+ 188: ",",
+ 189: "-",
+ 190: ".",
+ 191: "/",
+ 192: "`",
+ 219: "[",
+ 220: "\\",
+ 221: "]",
+ 222: "'",
+ },
+ MODIFIERS = {
+ 16: "shift",
+ 17: "ctrl",
+ 18: "alt",
+ 91: "meta",
+ 93: "meta",
+ },
+ MOUSE_BUTTONS = { 0: "", 1: "left", 2: "middle", 3: "right" },
+ // Boolean attributes that can be set with equivalent class names in the LI tags
+ // Note: v2.23: checkbox and hideCheckbox are *not* in this list
+ CLASS_ATTRS =
+ "active expanded focus folder lazy radiogroup selected unselectable unselectableIgnore".split(
+ " "
+ ),
+ CLASS_ATTR_MAP = {},
+ // Top-level Fancytree attributes, that can be set by dict
+ TREE_ATTRS = "columns types".split(" "),
+ // TREE_ATTR_MAP = {},
+ // Top-level FancytreeNode attributes, that can be set by dict
+ NODE_ATTRS =
+ "checkbox expanded extraClasses folder icon iconTooltip key lazy partsel radiogroup refKey selected statusNodeType title tooltip type unselectable unselectableIgnore unselectableStatus".split(
+ " "
+ ),
+ NODE_ATTR_MAP = {},
+ // Mapping of lowercase -> real name (because HTML5 data-... attribute only supports lowercase)
+ NODE_ATTR_LOWERCASE_MAP = {},
+ // Attribute names that should NOT be added to node.data
+ NONE_NODE_DATA_MAP = {
+ active: true,
+ children: true,
+ data: true,
+ focus: true,
+ };
+
+ for (i = 0; i < CLASS_ATTRS.length; i++) {
+ CLASS_ATTR_MAP[CLASS_ATTRS[i]] = true;
+ }
+ for (i = 0; i < NODE_ATTRS.length; i++) {
+ attr = NODE_ATTRS[i];
+ NODE_ATTR_MAP[attr] = true;
+ if (attr !== attr.toLowerCase()) {
+ NODE_ATTR_LOWERCASE_MAP[attr.toLowerCase()] = attr;
+ }
+ }
+ // for(i=0; i<TREE_ATTRS.length; i++) {
+ // TREE_ATTR_MAP[TREE_ATTRS[i]] = true;
+ // }
+
+ function _assert(cond, msg) {
+ // TODO: see qunit.js extractStacktrace()
+ if (!cond) {
+ msg = msg ? ": " + msg : "";
+ msg = "Fancytree assertion failed" + msg;
+
+ // consoleApply("assert", [!!cond, msg]);
+
+ // #1041: Raised exceptions may not be visible in the browser
+ // console if inside promise chains, so we also print directly:
+ $.ui.fancytree.error(msg);
+
+ // Throw exception:
+ $.error(msg);
+ }
+ }
+
+ function _hasProp(object, property) {
+ return Object.prototype.hasOwnProperty.call(object, property);
+ }
+
+ /* Replacement for the deprecated `jQuery.isFunction()`. */
+ function _isFunction(obj) {
+ return typeof obj === "function";
+ }
+
+ /* Replacement for the deprecated `jQuery.trim()`. */
+ function _trim(text) {
+ return text == null ? "" : text.trim();
+ }
+
+ /* Replacement for the deprecated `jQuery.isArray()`. */
+ var _isArray = Array.isArray;
+
+ _assert($.ui, "Fancytree requires jQuery UI (http://jqueryui.com)");
+
+ function consoleApply(method, args) {
+ var i,
+ s,
+ fn = window.console ? window.console[method] : null;
+
+ if (fn) {
+ try {
+ fn.apply(window.console, args);
+ } catch (e) {
+ // IE 8?
+ s = "";
+ for (i = 0; i < args.length; i++) {
+ s += args[i];
+ }
+ fn(s);
+ }
+ }
+ }
+
+ /* support: IE8 Polyfil for Date.now() */
+ if (!Date.now) {
+ Date.now = function now() {
+ return new Date().getTime();
+ };
+ }
+
+ /*Return true if x is a FancytreeNode.*/
+ function _isNode(x) {
+ return !!(x.tree && x.statusNodeType !== undefined);
+ }
+
+ /** Return true if dotted version string is equal or higher than requested version.
+ *
+ * See http://jsfiddle.net/mar10/FjSAN/
+ */
+ function isVersionAtLeast(dottedVersion, major, minor, patch) {
+ var i,
+ v,
+ t,
+ verParts = $.map(_trim(dottedVersion).split("."), function (e) {
+ return parseInt(e, 10);
+ }),
+ testParts = $.map(
+ Array.prototype.slice.call(arguments, 1),
+ function (e) {
+ return parseInt(e, 10);
+ }
+ );
+
+ for (i = 0; i < testParts.length; i++) {
+ v = verParts[i] || 0;
+ t = testParts[i] || 0;
+ if (v !== t) {
+ return v > t;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Deep-merge a list of objects (but replace array-type options).
+ *
+ * jQuery's $.extend(true, ...) method does a deep merge, that also merges Arrays.
+ * This variant is used to merge extension defaults with user options, and should
+ * merge objects, but override arrays (for example the `triggerStart: [...]` option
+ * of ext-edit). Also `null` values are copied over and not skipped.
+ *
+ * See issue #876
+ *
+ * Example:
+ * _simpleDeepMerge({}, o1, o2);
+ */
+ function _simpleDeepMerge() {
+ var options,
+ name,
+ src,
+ copy,
+ clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length;
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if (typeof target !== "object" && !_isFunction(target)) {
+ target = {};
+ }
+ if (i === length) {
+ throw Error("need at least two args");
+ }
+ for (; i < length; i++) {
+ // Only deal with non-null/undefined values
+ if ((options = arguments[i]) != null) {
+ // Extend the base object
+ for (name in options) {
+ if (_hasProp(options, name)) {
+ src = target[name];
+ copy = options[name];
+ // Prevent never-ending loop
+ if (target === copy) {
+ continue;
+ }
+ // Recurse if we're merging plain objects
+ // (NOTE: unlike $.extend, we don't merge arrays, but replace them)
+ if (copy && $.isPlainObject(copy)) {
+ clone = src && $.isPlainObject(src) ? src : {};
+ // Never move original objects, clone them
+ target[name] = _simpleDeepMerge(clone, copy);
+ // Don't bring in undefined values
+ } else if (copy !== undefined) {
+ target[name] = copy;
+ }
+ }
+ }
+ }
+ }
+ // Return the modified object
+ return target;
+ }
+
+ /** Return a wrapper that calls sub.methodName() and exposes
+ * this : tree
+ * this._local : tree.ext.EXTNAME
+ * this._super : base.methodName.call()
+ * this._superApply : base.methodName.apply()
+ */
+ function _makeVirtualFunction(methodName, tree, base, extension, extName) {
+ // $.ui.fancytree.debug("_makeVirtualFunction", methodName, tree, base, extension, extName);
+ // if(rexTestSuper && !rexTestSuper.test(func)){
+ // // extension.methodName() doesn't call _super(), so no wrapper required
+ // return func;
+ // }
+ // Use an immediate function as closure
+ var proxy = (function () {
+ var prevFunc = tree[methodName], // org. tree method or prev. proxy
+ baseFunc = extension[methodName], //
+ _local = tree.ext[extName],
+ _super = function () {
+ return prevFunc.apply(tree, arguments);
+ },
+ _superApply = function (args) {
+ return prevFunc.apply(tree, args);
+ };
+
+ // Return the wrapper function
+ return function () {
+ var prevLocal = tree._local,
+ prevSuper = tree._super,
+ prevSuperApply = tree._superApply;
+
+ try {
+ tree._local = _local;
+ tree._super = _super;
+ tree._superApply = _superApply;
+ return baseFunc.apply(tree, arguments);
+ } finally {
+ tree._local = prevLocal;
+ tree._super = prevSuper;
+ tree._superApply = prevSuperApply;
+ }
+ };
+ })(); // end of Immediate Function
+ return proxy;
+ }
+
+ /**
+ * Subclass `base` by creating proxy functions
+ */
+ function _subclassObject(tree, base, extension, extName) {
+ // $.ui.fancytree.debug("_subclassObject", tree, base, extension, extName);
+ for (var attrName in extension) {
+ if (typeof extension[attrName] === "function") {
+ if (typeof tree[attrName] === "function") {
+ // override existing method
+ tree[attrName] = _makeVirtualFunction(
+ attrName,
+ tree,
+ base,
+ extension,
+ extName
+ );
+ } else if (attrName.charAt(0) === "_") {
+ // Create private methods in tree.ext.EXTENSION namespace
+ tree.ext[extName][attrName] = _makeVirtualFunction(
+ attrName,
+ tree,
+ base,
+ extension,
+ extName
+ );
+ } else {
+ $.error(
+ "Could not override tree." +
+ attrName +
+ ". Use prefix '_' to create tree." +
+ extName +
+ "._" +
+ attrName
+ );
+ }
+ } else {
+ // Create member variables in tree.ext.EXTENSION namespace
+ if (attrName !== "options") {
+ tree.ext[extName][attrName] = extension[attrName];
+ }
+ }
+ }
+ }
+
+ function _getResolvedPromise(context, argArray) {
+ if (context === undefined) {
+ return $.Deferred(function () {
+ this.resolve();
+ }).promise();
+ }
+ return $.Deferred(function () {
+ this.resolveWith(context, argArray);
+ }).promise();
+ }
+
+ function _getRejectedPromise(context, argArray) {
+ if (context === undefined) {
+ return $.Deferred(function () {
+ this.reject();
+ }).promise();
+ }
+ return $.Deferred(function () {
+ this.rejectWith(context, argArray);
+ }).promise();
+ }
+
+ function _makeResolveFunc(deferred, context) {
+ return function () {
+ deferred.resolveWith(context);
+ };
+ }
+
+ function _getElementDataAsDict($el) {
+ // Evaluate 'data-NAME' attributes with special treatment for 'data-json'.
+ var d = $.extend({}, $el.data()),
+ json = d.json;
+
+ delete d.fancytree; // added to container by widget factory (old jQuery UI)
+ delete d.uiFancytree; // added to container by widget factory
+
+ if (json) {
+ delete d.json;
+ // <li data-json='...'> is already returned as object (http://api.jquery.com/data/#data-html5)
+ d = $.extend(d, json);
+ }
+ return d;
+ }
+
+ function _escapeTooltip(s) {
+ return ("" + s).replace(REX_TOOLTIP, function (s) {
+ return ENTITY_MAP[s];
+ });
+ }
+
+ // TODO: use currying
+ function _makeNodeTitleMatcher(s) {
+ s = s.toLowerCase();
+ return function (node) {
+ return node.title.toLowerCase().indexOf(s) >= 0;
+ };
+ }
+
+ function _makeNodeTitleStartMatcher(s) {
+ var reMatch = new RegExp("^" + s, "i");
+ return function (node) {
+ return reMatch.test(node.title);
+ };
+ }
+
+ /******************************************************************************
+ * FancytreeNode
+ */
+
+ /**
+ * Creates a new FancytreeNode
+ *
+ * @class FancytreeNode
+ * @classdesc A FancytreeNode represents the hierarchical data model and operations.
+ *
+ * @param {FancytreeNode} parent
+ * @param {NodeData} obj
+ *
+ * @property {Fancytree} tree The tree instance
+ * @property {FancytreeNode} parent The parent node
+ * @property {string} key Node id (must be unique inside the tree)
+ * @property {string} title Display name (may contain HTML)
+ * @property {object} data Contains all extra data that was passed on node creation
+ * @property {FancytreeNode[] | null | undefined} children Array of child nodes.<br>
+ * For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array
+ * to define a node that has no children.
+ * @property {boolean} expanded Use isExpanded(), setExpanded() to access this property.
+ * @property {string} extraClasses Additional CSS classes, added to the node's `<span>`.<br>
+ * Note: use `node.add/remove/toggleClass()` to modify.
+ * @property {boolean} folder Folder nodes have different default icons and click behavior.<br>
+ * Note: Also non-folders may have children.
+ * @property {string} statusNodeType null for standard nodes. Otherwise type of special system node: 'error', 'loading', 'nodata', or 'paging'.
+ * @property {boolean} lazy True if this node is loaded on demand, i.e. on first expansion.
+ * @property {boolean} selected Use isSelected(), setSelected() to access this property.
+ * @property {string} tooltip Alternative description used as hover popup
+ * @property {string} iconTooltip Description used as hover popup for icon. @since 2.27
+ * @property {string} type Node type, used with tree.types map. @since 2.27
+ */
+ function FancytreeNode(parent, obj) {
+ var i, l, name, cl;
+
+ this.parent = parent;
+ this.tree = parent.tree;
+ this.ul = null;
+ this.li = null; // <li id='key' ftnode=this> tag
+ this.statusNodeType = null; // if this is a temp. node to display the status of its parent
+ this._isLoading = false; // if this node itself is loading
+ this._error = null; // {message: '...'} if a load error occurred
+ this.data = {};
+
+ // TODO: merge this code with node.toDict()
+ // copy attributes from obj object
+ for (i = 0, l = NODE_ATTRS.length; i < l; i++) {
+ name = NODE_ATTRS[i];
+ this[name] = obj[name];
+ }
+ // unselectableIgnore and unselectableStatus imply unselectable
+ if (
+ this.unselectableIgnore != null ||
+ this.unselectableStatus != null
+ ) {
+ this.unselectable = true;
+ }
+ if (obj.hideCheckbox) {
+ $.error(
+ "'hideCheckbox' node option was removed in v2.23.0: use 'checkbox: false'"
+ );
+ }
+ // node.data += obj.data
+ if (obj.data) {
+ $.extend(this.data, obj.data);
+ }
+ // Copy all other attributes to this.data.NAME
+ for (name in obj) {
+ if (
+ !NODE_ATTR_MAP[name] &&
+ (this.tree.options.copyFunctionsToData ||
+ !_isFunction(obj[name])) &&
+ !NONE_NODE_DATA_MAP[name]
+ ) {
+ // node.data.NAME = obj.NAME
+ this.data[name] = obj[name];
+ }
+ }
+
+ // Fix missing key
+ if (this.key == null) {
+ // test for null OR undefined
+ if (this.tree.options.defaultKey) {
+ this.key = "" + this.tree.options.defaultKey(this);
+ _assert(this.key, "defaultKey() must return a unique key");
+ } else {
+ this.key = "_" + FT._nextNodeKey++;
+ }
+ } else {
+ this.key = "" + this.key; // Convert to string (#217)
+ }
+
+ // Fix tree.activeNode
+ // TODO: not elegant: we use obj.active as marker to set tree.activeNode
+ // when loading from a dictionary.
+ if (obj.active) {
+ _assert(
+ this.tree.activeNode === null,
+ "only one active node allowed"
+ );
+ this.tree.activeNode = this;
+ }
+ if (obj.selected) {
+ // #186
+ this.tree.lastSelectedNode = this;
+ }
+ // TODO: handle obj.focus = true
+
+ // Create child nodes
+ cl = obj.children;
+ if (cl) {
+ if (cl.length) {
+ this._setChildren(cl);
+ } else {
+ // if an empty array was passed for a lazy node, keep it, in order to mark it 'loaded'
+ this.children = this.lazy ? [] : null;
+ }
+ } else {
+ this.children = null;
+ }
+ // Add to key/ref map (except for root node)
+ // if( parent ) {
+ this.tree._callHook("treeRegisterNode", this.tree, true, this);
+ // }
+ }
+
+ FancytreeNode.prototype = /** @lends FancytreeNode# */ {
+ /* Return the direct child FancytreeNode with a given key, index. */
+ _findDirectChild: function (ptr) {
+ var i,
+ l,
+ cl = this.children;
+
+ if (cl) {
+ if (typeof ptr === "string") {
+ for (i = 0, l = cl.length; i < l; i++) {
+ if (cl[i].key === ptr) {
+ return cl[i];
+ }
+ }
+ } else if (typeof ptr === "number") {
+ return this.children[ptr];
+ } else if (ptr.parent === this) {
+ return ptr;
+ }
+ }
+ return null;
+ },
+ // TODO: activate()
+ // TODO: activateSilently()
+ /* Internal helper called in recursive addChildren sequence.*/
+ _setChildren: function (children) {
+ _assert(
+ children && (!this.children || this.children.length === 0),
+ "only init supported"
+ );
+ this.children = [];
+ for (var i = 0, l = children.length; i < l; i++) {
+ this.children.push(new FancytreeNode(this, children[i]));
+ }
+ this.tree._callHook(
+ "treeStructureChanged",
+ this.tree,
+ "setChildren"
+ );
+ },
+ /**
+ * Append (or insert) a list of child nodes.
+ *
+ * @param {NodeData[]} children array of child node definitions (also single child accepted)
+ * @param {FancytreeNode | string | Integer} [insertBefore] child node (or key or index of such).
+ * If omitted, the new children are appended.
+ * @returns {FancytreeNode} first child added
+ *
+ * @see FancytreeNode#applyPatch
+ */
+ addChildren: function (children, insertBefore) {
+ var i,
+ l,
+ pos,
+ origFirstChild = this.getFirstChild(),
+ origLastChild = this.getLastChild(),
+ firstNode = null,
+ nodeList = [];
+
+ if ($.isPlainObject(children)) {
+ children = [children];
+ }
+ if (!this.children) {
+ this.children = [];
+ }
+ for (i = 0, l = children.length; i < l; i++) {
+ nodeList.push(new FancytreeNode(this, children[i]));
+ }
+ firstNode = nodeList[0];
+ if (insertBefore == null) {
+ this.children = this.children.concat(nodeList);
+ } else {
+ // Returns null if insertBefore is not a direct child:
+ insertBefore = this._findDirectChild(insertBefore);
+ pos = $.inArray(insertBefore, this.children);
+ _assert(pos >= 0, "insertBefore must be an existing child");
+ // insert nodeList after children[pos]
+ this.children.splice.apply(
+ this.children,
+ [pos, 0].concat(nodeList)
+ );
+ }
+ if (origFirstChild && !insertBefore) {
+ // #708: Fast path -- don't render every child of root, just the new ones!
+ // #723, #729: but only if it's appended to an existing child list
+ for (i = 0, l = nodeList.length; i < l; i++) {
+ nodeList[i].render(); // New nodes were never rendered before
+ }
+ // Adjust classes where status may have changed
+ // Has a first child
+ if (origFirstChild !== this.getFirstChild()) {
+ // Different first child -- recompute classes
+ origFirstChild.renderStatus();
+ }
+ if (origLastChild !== this.getLastChild()) {
+ // Different last child -- recompute classes
+ origLastChild.renderStatus();
+ }
+ } else if (!this.parent || this.parent.ul || this.tr) {
+ // render if the parent was rendered (or this is a root node)
+ this.render();
+ }
+ if (this.tree.options.selectMode === 3) {
+ this.fixSelection3FromEndNodes();
+ }
+ this.triggerModifyChild(
+ "add",
+ nodeList.length === 1 ? nodeList[0] : null
+ );
+ return firstNode;
+ },
+ /**
+ * Add class to node's span tag and to .extraClasses.
+ *
+ * @param {string} className class name
+ *
+ * @since 2.17
+ */
+ addClass: function (className) {
+ return this.toggleClass(className, true);
+ },
+ /**
+ * Append or prepend a node, or append a child node.
+ *
+ * This a convenience function that calls addChildren()
+ *
+ * @param {NodeData} node node definition
+ * @param {string} [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')
+ * @returns {FancytreeNode} new node
+ */
+ addNode: function (node, mode) {
+ if (mode === undefined || mode === "over") {
+ mode = "child";
+ }
+ switch (mode) {
+ case "after":
+ return this.getParent().addChildren(
+ node,
+ this.getNextSibling()
+ );
+ case "before":
+ return this.getParent().addChildren(node, this);
+ case "firstChild":
+ // Insert before the first child if any
+ var insertBefore = this.children ? this.children[0] : null;
+ return this.addChildren(node, insertBefore);
+ case "child":
+ case "over":
+ return this.addChildren(node);
+ }
+ _assert(false, "Invalid mode: " + mode);
+ },
+ /**Add child status nodes that indicate 'More...', etc.
+ *
+ * This also maintains the node's `partload` property.
+ * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.
+ * @param {string} [mode='child'] 'child'|firstChild'
+ * @since 2.15
+ */
+ addPagingNode: function (node, mode) {
+ var i, n;
+
+ mode = mode || "child";
+ if (node === false) {
+ for (i = this.children.length - 1; i >= 0; i--) {
+ n = this.children[i];
+ if (n.statusNodeType === "paging") {
+ this.removeChild(n);
+ }
+ }
+ this.partload = false;
+ return;
+ }
+ node = $.extend(
+ {
+ title: this.tree.options.strings.moreData,
+ statusNodeType: "paging",
+ icon: false,
+ },
+ node
+ );
+ this.partload = true;
+ return this.addNode(node, mode);
+ },
+ /**
+ * Append new node after this.
+ *
+ * This a convenience function that calls addNode(node, 'after')
+ *
+ * @param {NodeData} node node definition
+ * @returns {FancytreeNode} new node
+ */
+ appendSibling: function (node) {
+ return this.addNode(node, "after");
+ },
+ /**
+ * (experimental) Apply a modification (or navigation) operation.
+ *
+ * @param {string} cmd
+ * @param {object} [opts]
+ * @see Fancytree#applyCommand
+ * @since 2.32
+ */
+ applyCommand: function (cmd, opts) {
+ return this.tree.applyCommand(cmd, this, opts);
+ },
+ /**
+ * Modify existing child nodes.
+ *
+ * @param {NodePatch} patch
+ * @returns {$.Promise}
+ * @see FancytreeNode#addChildren
+ */
+ applyPatch: function (patch) {
+ // patch [key, null] means 'remove'
+ if (patch === null) {
+ this.remove();
+ return _getResolvedPromise(this);
+ }
+ // TODO: make sure that root node is not collapsed or modified
+ // copy (most) attributes to node.ATTR or node.data.ATTR
+ var name,
+ promise,
+ v,
+ IGNORE_MAP = { children: true, expanded: true, parent: true }; // TODO: should be global
+
+ for (name in patch) {
+ if (_hasProp(patch, name)) {
+ v = patch[name];
+ if (!IGNORE_MAP[name] && !_isFunction(v)) {
+ if (NODE_ATTR_MAP[name]) {
+ this[name] = v;
+ } else {
+ this.data[name] = v;
+ }
+ }
+ }
+ }
+ // Remove and/or create children
+ if (_hasProp(patch, "children")) {
+ this.removeChildren();
+ if (patch.children) {
+ // only if not null and not empty list
+ // TODO: addChildren instead?
+ this._setChildren(patch.children);
+ }
+ // TODO: how can we APPEND or INSERT child nodes?
+ }
+ if (this.isVisible()) {
+ this.renderTitle();
+ this.renderStatus();
+ }
+ // Expand collapse (final step, since this may be async)
+ if (_hasProp(patch, "expanded")) {
+ promise = this.setExpanded(patch.expanded);
+ } else {
+ promise = _getResolvedPromise(this);
+ }
+ return promise;
+ },
+ /** Collapse all sibling nodes.
+ * @returns {$.Promise}
+ */
+ collapseSiblings: function () {
+ return this.tree._callHook("nodeCollapseSiblings", this);
+ },
+ /** Copy this node as sibling or child of `node`.
+ *
+ * @param {FancytreeNode} node source node
+ * @param {string} [mode=child] 'before' | 'after' | 'child'
+ * @param {Function} [map] callback function(NodeData, FancytreeNode) that could modify the new node
+ * @returns {FancytreeNode} new
+ */
+ copyTo: function (node, mode, map) {
+ return node.addNode(this.toDict(true, map), mode);
+ },
+ /** Count direct and indirect children.
+ *
+ * @param {boolean} [deep=true] pass 'false' to only count direct children
+ * @returns {int} number of child nodes
+ */
+ countChildren: function (deep) {
+ var cl = this.children,
+ i,
+ l,
+ n;
+ if (!cl) {
+ return 0;
+ }
+ n = cl.length;
+ if (deep !== false) {
+ for (i = 0, l = n; i < l; i++) {
+ n += cl[i].countChildren();
+ }
+ }
+ return n;
+ },
+ // TODO: deactivate()
+ /** Write to browser console if debugLevel >= 4 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ debug: function (msg) {
+ if (this.tree.options.debugLevel >= 4) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("log", arguments);
+ }
+ },
+ /** Deprecated.
+ * @deprecated since 2014-02-16. Use resetLazy() instead.
+ */
+ discard: function () {
+ this.warn(
+ "FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."
+ );
+ return this.resetLazy();
+ },
+ /** Remove DOM elements for all descendents. May be called on .collapse event
+ * to keep the DOM small.
+ * @param {boolean} [includeSelf=false]
+ */
+ discardMarkup: function (includeSelf) {
+ var fn = includeSelf ? "nodeRemoveMarkup" : "nodeRemoveChildMarkup";
+ this.tree._callHook(fn, this);
+ },
+ /** Write error to browser console if debugLevel >= 1 (prepending tree info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ error: function (msg) {
+ if (this.tree.options.debugLevel >= 1) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("error", arguments);
+ }
+ },
+ /**Find all nodes that match condition (excluding self).
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode[]} array of nodes (may be empty)
+ */
+ findAll: function (match) {
+ match = _isFunction(match) ? match : _makeNodeTitleMatcher(match);
+ var res = [];
+ this.visit(function (n) {
+ if (match(n)) {
+ res.push(n);
+ }
+ });
+ return res;
+ },
+ /**Find first node that matches condition (excluding self).
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode} matching node or null
+ * @see FancytreeNode#findAll
+ */
+ findFirst: function (match) {
+ match = _isFunction(match) ? match : _makeNodeTitleMatcher(match);
+ var res = null;
+ this.visit(function (n) {
+ if (match(n)) {
+ res = n;
+ return false;
+ }
+ });
+ return res;
+ },
+ /** Find a node relative to self.
+ *
+ * @param {number|string} where The keyCode that would normally trigger this move,
+ * or a keyword ('down', 'first', 'last', 'left', 'parent', 'right', 'up').
+ * @returns {FancytreeNode}
+ * @since v2.31
+ */
+ findRelatedNode: function (where, includeHidden) {
+ return this.tree.findRelatedNode(this, where, includeHidden);
+ },
+ /* Apply selection state (internal use only) */
+ _changeSelectStatusAttrs: function (state) {
+ var changed = false,
+ opts = this.tree.options,
+ unselectable = FT.evalOption(
+ "unselectable",
+ this,
+ this,
+ opts,
+ false
+ ),
+ unselectableStatus = FT.evalOption(
+ "unselectableStatus",
+ this,
+ this,
+ opts,
+ undefined
+ );
+
+ if (unselectable && unselectableStatus != null) {
+ state = unselectableStatus;
+ }
+ switch (state) {
+ case false:
+ changed = this.selected || this.partsel;
+ this.selected = false;
+ this.partsel = false;
+ break;
+ case true:
+ changed = !this.selected || !this.partsel;
+ this.selected = true;
+ this.partsel = true;
+ break;
+ case undefined:
+ changed = this.selected || !this.partsel;
+ this.selected = false;
+ this.partsel = true;
+ break;
+ default:
+ _assert(false, "invalid state: " + state);
+ }
+ // this.debug("fixSelection3AfterLoad() _changeSelectStatusAttrs()", state, changed);
+ if (changed) {
+ this.renderStatus();
+ }
+ return changed;
+ },
+ /**
+ * Fix selection status, after this node was (de)selected in multi-hier mode.
+ * This includes (de)selecting all children.
+ */
+ fixSelection3AfterClick: function (callOpts) {
+ var flag = this.isSelected();
+
+ // this.debug("fixSelection3AfterClick()");
+
+ this.visit(function (node) {
+ node._changeSelectStatusAttrs(flag);
+ if (node.radiogroup) {
+ // #931: don't (de)select this branch
+ return "skip";
+ }
+ });
+ this.fixSelection3FromEndNodes(callOpts);
+ },
+ /**
+ * Fix selection status for multi-hier mode.
+ * Only end-nodes are considered to update the descendants branch and parents.
+ * Should be called after this node has loaded new children or after
+ * children have been modified using the API.
+ */
+ fixSelection3FromEndNodes: function (callOpts) {
+ var opts = this.tree.options;
+
+ // this.debug("fixSelection3FromEndNodes()");
+ _assert(opts.selectMode === 3, "expected selectMode 3");
+
+ // Visit all end nodes and adjust their parent's `selected` and `partsel`
+ // attributes. Return selection state true, false, or undefined.
+ function _walk(node) {
+ var i,
+ l,
+ child,
+ s,
+ state,
+ allSelected,
+ someSelected,
+ unselIgnore,
+ unselState,
+ children = node.children;
+
+ if (children && children.length) {
+ // check all children recursively
+ allSelected = true;
+ someSelected = false;
+
+ for (i = 0, l = children.length; i < l; i++) {
+ child = children[i];
+ // the selection state of a node is not relevant; we need the end-nodes
+ s = _walk(child);
+ // if( !child.unselectableIgnore ) {
+ unselIgnore = FT.evalOption(
+ "unselectableIgnore",
+ child,
+ child,
+ opts,
+ false
+ );
+ if (!unselIgnore) {
+ if (s !== false) {
+ someSelected = true;
+ }
+ if (s !== true) {
+ allSelected = false;
+ }
+ }
+ }
+ // eslint-disable-next-line no-nested-ternary
+ state = allSelected
+ ? true
+ : someSelected
+ ? undefined
+ : false;
+ } else {
+ // This is an end-node: simply report the status
+ unselState = FT.evalOption(
+ "unselectableStatus",
+ node,
+ node,
+ opts,
+ undefined
+ );
+ state = unselState == null ? !!node.selected : !!unselState;
+ }
+ // #939: Keep a `partsel` flag that was explicitly set on a lazy node
+ if (
+ node.partsel &&
+ !node.selected &&
+ node.lazy &&
+ node.children == null
+ ) {
+ state = undefined;
+ }
+ node._changeSelectStatusAttrs(state);
+ return state;
+ }
+ _walk(this);
+
+ // Update parent's state
+ this.visitParents(function (node) {
+ var i,
+ l,
+ child,
+ state,
+ unselIgnore,
+ unselState,
+ children = node.children,
+ allSelected = true,
+ someSelected = false;
+
+ for (i = 0, l = children.length; i < l; i++) {
+ child = children[i];
+ unselIgnore = FT.evalOption(
+ "unselectableIgnore",
+ child,
+ child,
+ opts,
+ false
+ );
+ if (!unselIgnore) {
+ unselState = FT.evalOption(
+ "unselectableStatus",
+ child,
+ child,
+ opts,
+ undefined
+ );
+ state =
+ unselState == null
+ ? !!child.selected
+ : !!unselState;
+ // When fixing the parents, we trust the sibling status (i.e.
+ // we don't recurse)
+ if (state || child.partsel) {
+ someSelected = true;
+ }
+ if (!state) {
+ allSelected = false;
+ }
+ }
+ }
+ // eslint-disable-next-line no-nested-ternary
+ state = allSelected ? true : someSelected ? undefined : false;
+ node._changeSelectStatusAttrs(state);
+ });
+ },
+ // TODO: focus()
+ /**
+ * Update node data. If dict contains 'children', then also replace
+ * the hole sub tree.
+ * @param {NodeData} dict
+ *
+ * @see FancytreeNode#addChildren
+ * @see FancytreeNode#applyPatch
+ */
+ fromDict: function (dict) {
+ // copy all other attributes to this.data.xxx
+ for (var name in dict) {
+ if (NODE_ATTR_MAP[name]) {
+ // node.NAME = dict.NAME
+ this[name] = dict[name];
+ } else if (name === "data") {
+ // node.data += dict.data
+ $.extend(this.data, dict.data);
+ } else if (
+ !_isFunction(dict[name]) &&
+ !NONE_NODE_DATA_MAP[name]
+ ) {
+ // node.data.NAME = dict.NAME
+ this.data[name] = dict[name];
+ }
+ }
+ if (dict.children) {
+ // recursively set children and render
+ this.removeChildren();
+ this.addChildren(dict.children);
+ }
+ this.renderTitle();
+ /*
+ var children = dict.children;
+ if(children === undefined){
+ this.data = $.extend(this.data, dict);
+ this.render();
+ return;
+ }
+ dict = $.extend({}, dict);
+ dict.children = undefined;
+ this.data = $.extend(this.data, dict);
+ this.removeChildren();
+ this.addChild(children);
+ */
+ },
+ /** Return the list of child nodes (undefined for unexpanded lazy nodes).
+ * @returns {FancytreeNode[] | undefined}
+ */
+ getChildren: function () {
+ if (this.hasChildren() === undefined) {
+ // TODO: only required for lazy nodes?
+ return undefined; // Lazy node: unloaded, currently loading, or load error
+ }
+ return this.children;
+ },
+ /** Return the first child node or null.
+ * @returns {FancytreeNode | null}
+ */
+ getFirstChild: function () {
+ return this.children ? this.children[0] : null;
+ },
+ /** Return the 0-based child index.
+ * @returns {int}
+ */
+ getIndex: function () {
+ // return this.parent.children.indexOf(this);
+ return $.inArray(this, this.parent.children); // indexOf doesn't work in IE7
+ },
+ /** Return the hierarchical child index (1-based, e.g. '3.2.4').
+ * @param {string} [separator="."]
+ * @param {int} [digits=1]
+ * @returns {string}
+ */
+ getIndexHier: function (separator, digits) {
+ separator = separator || ".";
+ var s,
+ res = [];
+ $.each(this.getParentList(false, true), function (i, o) {
+ s = "" + (o.getIndex() + 1);
+ if (digits) {
+ // prepend leading zeroes
+ s = ("0000000" + s).substr(-digits);
+ }
+ res.push(s);
+ });
+ return res.join(separator);
+ },
+ /** Return the parent keys separated by options.keyPathSeparator, e.g. "/id_1/id_17/id_32".
+ *
+ * (Unlike `node.getPath()`, this method prepends a "/" and inverts the first argument.)
+ *
+ * @see FancytreeNode#getPath
+ * @param {boolean} [excludeSelf=false]
+ * @returns {string}
+ */
+ getKeyPath: function (excludeSelf) {
+ var sep = this.tree.options.keyPathSeparator;
+
+ return sep + this.getPath(!excludeSelf, "key", sep);
+ },
+ /** Return the last child of this node or null.
+ * @returns {FancytreeNode | null}
+ */
+ getLastChild: function () {
+ return this.children
+ ? this.children[this.children.length - 1]
+ : null;
+ },
+ /** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... .
+ * @returns {int}
+ */
+ getLevel: function () {
+ var level = 0,
+ dtn = this.parent;
+ while (dtn) {
+ level++;
+ dtn = dtn.parent;
+ }
+ return level;
+ },
+ /** Return the successor node (under the same parent) or null.
+ * @returns {FancytreeNode | null}
+ */
+ getNextSibling: function () {
+ // TODO: use indexOf, if available: (not in IE6)
+ if (this.parent) {
+ var i,
+ l,
+ ac = this.parent.children;
+
+ for (i = 0, l = ac.length - 1; i < l; i++) {
+ // up to length-2, so next(last) = null
+ if (ac[i] === this) {
+ return ac[i + 1];
+ }
+ }
+ }
+ return null;
+ },
+ /** Return the parent node (null for the system root node).
+ * @returns {FancytreeNode | null}
+ */
+ getParent: function () {
+ // TODO: return null for top-level nodes?
+ return this.parent;
+ },
+ /** Return an array of all parent nodes (top-down).
+ * @param {boolean} [includeRoot=false] Include the invisible system root node.
+ * @param {boolean} [includeSelf=false] Include the node itself.
+ * @returns {FancytreeNode[]}
+ */
+ getParentList: function (includeRoot, includeSelf) {
+ var l = [],
+ dtn = includeSelf ? this : this.parent;
+ while (dtn) {
+ if (includeRoot || dtn.parent) {
+ l.unshift(dtn);
+ }
+ dtn = dtn.parent;
+ }
+ return l;
+ },
+ /** Return a string representing the hierachical node path, e.g. "a/b/c".
+ * @param {boolean} [includeSelf=true]
+ * @param {string | function} [part="title"] node property name or callback
+ * @param {string} [separator="/"]
+ * @returns {string}
+ * @since v2.31
+ */
+ getPath: function (includeSelf, part, separator) {
+ includeSelf = includeSelf !== false;
+ part = part || "title";
+ separator = separator || "/";
+
+ var val,
+ path = [],
+ isFunc = _isFunction(part);
+
+ this.visitParents(function (n) {
+ if (n.parent) {
+ val = isFunc ? part(n) : n[part];
+ path.unshift(val);
+ }
+ }, includeSelf);
+ return path.join(separator);
+ },
+ /** Return the predecessor node (under the same parent) or null.
+ * @returns {FancytreeNode | null}
+ */
+ getPrevSibling: function () {
+ if (this.parent) {
+ var i,
+ l,
+ ac = this.parent.children;
+
+ for (i = 1, l = ac.length; i < l; i++) {
+ // start with 1, so prev(first) = null
+ if (ac[i] === this) {
+ return ac[i - 1];
+ }
+ }
+ }
+ return null;
+ },
+ /**
+ * Return an array of selected descendant nodes.
+ * @param {boolean} [stopOnParents=false] only return the topmost selected
+ * node (useful with selectMode 3)
+ * @returns {FancytreeNode[]}
+ */
+ getSelectedNodes: function (stopOnParents) {
+ var nodeList = [];
+ this.visit(function (node) {
+ if (node.selected) {
+ nodeList.push(node);
+ if (stopOnParents === true) {
+ return "skip"; // stop processing this branch
+ }
+ }
+ });
+ return nodeList;
+ },
+ /** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded).
+ * @returns {boolean | undefined}
+ */
+ hasChildren: function () {
+ if (this.lazy) {
+ if (this.children == null) {
+ // null or undefined: Not yet loaded
+ return undefined;
+ } else if (this.children.length === 0) {
+ // Loaded, but response was empty
+ return false;
+ } else if (
+ this.children.length === 1 &&
+ this.children[0].isStatusNode()
+ ) {
+ // Currently loading or load error
+ return undefined;
+ }
+ return true;
+ }
+ return !!(this.children && this.children.length);
+ },
+ /**
+ * Return true if node has `className` defined in .extraClasses.
+ *
+ * @param {string} className class name (separate multiple classes by space)
+ * @returns {boolean}
+ *
+ * @since 2.32
+ */
+ hasClass: function (className) {
+ return (
+ (" " + (this.extraClasses || "") + " ").indexOf(
+ " " + className + " "
+ ) >= 0
+ );
+ },
+ /** Return true if node has keyboard focus.
+ * @returns {boolean}
+ */
+ hasFocus: function () {
+ return this.tree.hasFocus() && this.tree.focusNode === this;
+ },
+ /** Write to browser console if debugLevel >= 3 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ info: function (msg) {
+ if (this.tree.options.debugLevel >= 3) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("info", arguments);
+ }
+ },
+ /** Return true if node is active (see also FancytreeNode#isSelected).
+ * @returns {boolean}
+ */
+ isActive: function () {
+ return this.tree.activeNode === this;
+ },
+ /** Return true if node is vertically below `otherNode`, i.e. rendered in a subsequent row.
+ * @param {FancytreeNode} otherNode
+ * @returns {boolean}
+ * @since 2.28
+ */
+ isBelowOf: function (otherNode) {
+ return this.getIndexHier(".", 5) > otherNode.getIndexHier(".", 5);
+ },
+ /** Return true if node is a direct child of otherNode.
+ * @param {FancytreeNode} otherNode
+ * @returns {boolean}
+ */
+ isChildOf: function (otherNode) {
+ return this.parent && this.parent === otherNode;
+ },
+ /** Return true, if node is a direct or indirect sub node of otherNode.
+ * @param {FancytreeNode} otherNode
+ * @returns {boolean}
+ */
+ isDescendantOf: function (otherNode) {
+ if (!otherNode || otherNode.tree !== this.tree) {
+ return false;
+ }
+ var p = this.parent;
+ while (p) {
+ if (p === otherNode) {
+ return true;
+ }
+ if (p === p.parent) {
+ $.error("Recursive parent link: " + p);
+ }
+ p = p.parent;
+ }
+ return false;
+ },
+ /** Return true if node is expanded.
+ * @returns {boolean}
+ */
+ isExpanded: function () {
+ return !!this.expanded;
+ },
+ /** Return true if node is the first node of its parent's children.
+ * @returns {boolean}
+ */
+ isFirstSibling: function () {
+ var p = this.parent;
+ return !p || p.children[0] === this;
+ },
+ /** Return true if node is a folder, i.e. has the node.folder attribute set.
+ * @returns {boolean}
+ */
+ isFolder: function () {
+ return !!this.folder;
+ },
+ /** Return true if node is the last node of its parent's children.
+ * @returns {boolean}
+ */
+ isLastSibling: function () {
+ var p = this.parent;
+ return !p || p.children[p.children.length - 1] === this;
+ },
+ /** Return true if node is lazy (even if data was already loaded)
+ * @returns {boolean}
+ */
+ isLazy: function () {
+ return !!this.lazy;
+ },
+ /** Return true if node is lazy and loaded. For non-lazy nodes always return true.
+ * @returns {boolean}
+ */
+ isLoaded: function () {
+ return !this.lazy || this.hasChildren() !== undefined; // Also checks if the only child is a status node
+ },
+ /** Return true if children are currently beeing loaded, i.e. a Ajax request is pending.
+ * @returns {boolean}
+ */
+ isLoading: function () {
+ return !!this._isLoading;
+ },
+ /*
+ * @deprecated since v2.4.0: Use isRootNode() instead
+ */
+ isRoot: function () {
+ return this.isRootNode();
+ },
+ /** Return true if node is partially selected (tri-state).
+ * @returns {boolean}
+ * @since 2.23
+ */
+ isPartsel: function () {
+ return !this.selected && !!this.partsel;
+ },
+ /** (experimental) Return true if this is partially loaded.
+ * @returns {boolean}
+ * @since 2.15
+ */
+ isPartload: function () {
+ return !!this.partload;
+ },
+ /** Return true if this is the (invisible) system root node.
+ * @returns {boolean}
+ * @since 2.4
+ */
+ isRootNode: function () {
+ return this.tree.rootNode === this;
+ },
+ /** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive).
+ * @returns {boolean}
+ */
+ isSelected: function () {
+ return !!this.selected;
+ },
+ /** Return true if this node is a temporarily generated system node like
+ * 'loading', 'paging', or 'error' (node.statusNodeType contains the type).
+ * @returns {boolean}
+ */
+ isStatusNode: function () {
+ return !!this.statusNodeType;
+ },
+ /** Return true if this node is a status node of type 'paging'.
+ * @returns {boolean}
+ * @since 2.15
+ */
+ isPagingNode: function () {
+ return this.statusNodeType === "paging";
+ },
+ /** Return true if this a top level node, i.e. a direct child of the (invisible) system root node.
+ * @returns {boolean}
+ * @since 2.4
+ */
+ isTopLevel: function () {
+ return this.tree.rootNode === this.parent;
+ },
+ /** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false.
+ * @returns {boolean}
+ */
+ isUndefined: function () {
+ return this.hasChildren() === undefined; // also checks if the only child is a status node
+ },
+ /** Return true if all parent nodes are expanded. Note: this does not check
+ * whether the node is scrolled into the visible part of the screen.
+ * @returns {boolean}
+ */
+ isVisible: function () {
+ var i,
+ l,
+ n,
+ hasFilter = this.tree.enableFilter,
+ parents = this.getParentList(false, false);
+
+ // TODO: check $(n.span).is(":visible")
+ // i.e. return false for nodes (but not parents) that are hidden
+ // by a filter
+ if (hasFilter && !this.match && !this.subMatchCount) {
+ // this.debug( "isVisible: HIDDEN (" + hasFilter + ", " + this.match + ", " + this.match + ")" );
+ return false;
+ }
+
+ for (i = 0, l = parents.length; i < l; i++) {
+ n = parents[i];
+
+ if (!n.expanded) {
+ // this.debug("isVisible: HIDDEN (parent collapsed)");
+ return false;
+ }
+ // if (hasFilter && !n.match && !n.subMatchCount) {
+ // this.debug("isVisible: HIDDEN (" + hasFilter + ", " + this.match + ", " + this.match + ")");
+ // return false;
+ // }
+ }
+ // this.debug("isVisible: VISIBLE");
+ return true;
+ },
+ /** Deprecated.
+ * @deprecated since 2014-02-16: use load() instead.
+ */
+ lazyLoad: function (discard) {
+ $.error(
+ "FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead."
+ );
+ },
+ /**
+ * Load all children of a lazy node if neccessary. The <i>expanded</i> state is maintained.
+ * @param {boolean} [forceReload=false] Pass true to discard any existing nodes before. Otherwise this method does nothing if the node was already loaded.
+ * @returns {$.Promise}
+ */
+ load: function (forceReload) {
+ var res,
+ source,
+ self = this,
+ wasExpanded = this.isExpanded();
+
+ _assert(this.isLazy(), "load() requires a lazy node");
+ // _assert( forceReload || this.isUndefined(), "Pass forceReload=true to re-load a lazy node" );
+ if (!forceReload && !this.isUndefined()) {
+ return _getResolvedPromise(this);
+ }
+ if (this.isLoaded()) {
+ this.resetLazy(); // also collapses
+ }
+ // This method is also called by setExpanded() and loadKeyPath(), so we
+ // have to avoid recursion.
+ source = this.tree._triggerNodeEvent("lazyLoad", this);
+ if (source === false) {
+ // #69
+ return _getResolvedPromise(this);
+ }
+ _assert(
+ typeof source !== "boolean",
+ "lazyLoad event must return source in data.result"
+ );
+ res = this.tree._callHook("nodeLoadChildren", this, source);
+ if (wasExpanded) {
+ this.expanded = true;
+ res.always(function () {
+ self.render();
+ });
+ } else {
+ res.always(function () {
+ self.renderStatus(); // fix expander icon to 'loaded'
+ });
+ }
+ return res;
+ },
+ /** Expand all parents and optionally scroll into visible area as neccessary.
+ * Promise is resolved, when lazy loading and animations are done.
+ * @param {object} [opts] passed to `setExpanded()`.
+ * Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
+ * @returns {$.Promise}
+ */
+ makeVisible: function (opts) {
+ var i,
+ self = this,
+ deferreds = [],
+ dfd = new $.Deferred(),
+ parents = this.getParentList(false, false),
+ len = parents.length,
+ effects = !(opts && opts.noAnimation === true),
+ scroll = !(opts && opts.scrollIntoView === false);
+
+ // Expand bottom-up, so only the top node is animated
+ for (i = len - 1; i >= 0; i--) {
+ // self.debug("pushexpand" + parents[i]);
+ deferreds.push(parents[i].setExpanded(true, opts));
+ }
+ $.when.apply($, deferreds).done(function () {
+ // All expands have finished
+ // self.debug("expand DONE", scroll);
+ if (scroll) {
+ self.scrollIntoView(effects).done(function () {
+ // self.debug("scroll DONE");
+ dfd.resolve();
+ });
+ } else {
+ dfd.resolve();
+ }
+ });
+ return dfd.promise();
+ },
+ /** Move this node to targetNode.
+ * @param {FancytreeNode} targetNode
+ * @param {string} mode <pre>
+ * 'child': append this node as last child of targetNode.
+ * This is the default. To be compatble with the D'n'd
+ * hitMode, we also accept 'over'.
+ * 'firstChild': add this node as first child of targetNode.
+ * 'before': add this node as sibling before targetNode.
+ * 'after': add this node as sibling after targetNode.</pre>
+ * @param {function} [map] optional callback(FancytreeNode) to allow modifcations
+ */
+ moveTo: function (targetNode, mode, map) {
+ if (mode === undefined || mode === "over") {
+ mode = "child";
+ } else if (mode === "firstChild") {
+ if (targetNode.children && targetNode.children.length) {
+ mode = "before";
+ targetNode = targetNode.children[0];
+ } else {
+ mode = "child";
+ }
+ }
+ var pos,
+ tree = this.tree,
+ prevParent = this.parent,
+ targetParent =
+ mode === "child" ? targetNode : targetNode.parent;
+
+ if (this === targetNode) {
+ return;
+ } else if (!this.parent) {
+ $.error("Cannot move system root");
+ } else if (targetParent.isDescendantOf(this)) {
+ $.error("Cannot move a node to its own descendant");
+ }
+ if (targetParent !== prevParent) {
+ prevParent.triggerModifyChild("remove", this);
+ }
+ // Unlink this node from current parent
+ if (this.parent.children.length === 1) {
+ if (this.parent === targetParent) {
+ return; // #258
+ }
+ this.parent.children = this.parent.lazy ? [] : null;
+ this.parent.expanded = false;
+ } else {
+ pos = $.inArray(this, this.parent.children);
+ _assert(pos >= 0, "invalid source parent");
+ this.parent.children.splice(pos, 1);
+ }
+ // Remove from source DOM parent
+ // if(this.parent.ul){
+ // this.parent.ul.removeChild(this.li);
+ // }
+
+ // Insert this node to target parent's child list
+ this.parent = targetParent;
+ if (targetParent.hasChildren()) {
+ switch (mode) {
+ case "child":
+ // Append to existing target children
+ targetParent.children.push(this);
+ break;
+ case "before":
+ // Insert this node before target node
+ pos = $.inArray(targetNode, targetParent.children);
+ _assert(pos >= 0, "invalid target parent");
+ targetParent.children.splice(pos, 0, this);
+ break;
+ case "after":
+ // Insert this node after target node
+ pos = $.inArray(targetNode, targetParent.children);
+ _assert(pos >= 0, "invalid target parent");
+ targetParent.children.splice(pos + 1, 0, this);
+ break;
+ default:
+ $.error("Invalid mode " + mode);
+ }
+ } else {
+ targetParent.children = [this];
+ }
+ // Parent has no <ul> tag yet:
+ // if( !targetParent.ul ) {
+ // // This is the parent's first child: create UL tag
+ // // (Hidden, because it will be
+ // targetParent.ul = document.createElement("ul");
+ // targetParent.ul.style.display = "none";
+ // targetParent.li.appendChild(targetParent.ul);
+ // }
+ // // Issue 319: Add to target DOM parent (only if node was already rendered(expanded))
+ // if(this.li){
+ // targetParent.ul.appendChild(this.li);
+ // }
+
+ // Let caller modify the nodes
+ if (map) {
+ targetNode.visit(map, true);
+ }
+ if (targetParent === prevParent) {
+ targetParent.triggerModifyChild("move", this);
+ } else {
+ // prevParent.triggerModifyChild("remove", this);
+ targetParent.triggerModifyChild("add", this);
+ }
+ // Handle cross-tree moves
+ if (tree !== targetNode.tree) {
+ // Fix node.tree for all source nodes
+ // _assert(false, "Cross-tree move is not yet implemented.");
+ this.warn("Cross-tree moveTo is experimental!");
+ this.visit(function (n) {
+ // TODO: fix selection state and activation, ...
+ n.tree = targetNode.tree;
+ }, true);
+ }
+
+ // A collaposed node won't re-render children, so we have to remove it manually
+ // if( !targetParent.expanded ){
+ // prevParent.ul.removeChild(this.li);
+ // }
+ tree._callHook("treeStructureChanged", tree, "moveTo");
+
+ // Update HTML markup
+ if (!prevParent.isDescendantOf(targetParent)) {
+ prevParent.render();
+ }
+ if (
+ !targetParent.isDescendantOf(prevParent) &&
+ targetParent !== prevParent
+ ) {
+ targetParent.render();
+ }
+ // TODO: fix selection state
+ // TODO: fix active state
+
+ /*
+ var tree = this.tree;
+ var opts = tree.options;
+ var pers = tree.persistence;
+
+ // Always expand, if it's below minExpandLevel
+ // tree.logDebug ("%s._addChildNode(%o), l=%o", this, ftnode, ftnode.getLevel());
+ if ( opts.minExpandLevel >= ftnode.getLevel() ) {
+ // tree.logDebug ("Force expand for %o", ftnode);
+ this.bExpanded = true;
+ }
+
+ // In multi-hier mode, update the parents selection state
+ // DT issue #82: only if not initializing, because the children may not exist yet
+ // if( !ftnode.data.isStatusNode() && opts.selectMode==3 && !isInitializing )
+ // ftnode._fixSelectionState();
+
+ // In multi-hier mode, update the parents selection state
+ if( ftnode.bSelected && opts.selectMode==3 ) {
+ var p = this;
+ while( p ) {
+ if( !p.hasSubSel )
+ p._setSubSel(true);
+ p = p.parent;
+ }
+ }
+ // render this node and the new child
+ if ( tree.bEnableUpdate )
+ this.render();
+ return ftnode;
+ */
+ },
+ /** Set focus relative to this node and optionally activate.
+ *
+ * 'left' collapses the node if it is expanded, or move to the parent
+ * otherwise.
+ * 'right' expands the node if it is collapsed, or move to the first
+ * child otherwise.
+ *
+ * @param {string|number} where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.
+ * (Alternatively the keyCode that would normally trigger this move,
+ * e.g. `$.ui.keyCode.LEFT` = 'left'.
+ * @param {boolean} [activate=true]
+ * @returns {$.Promise}
+ */
+ navigate: function (where, activate) {
+ var node,
+ KC = $.ui.keyCode;
+
+ // Handle optional expand/collapse action for LEFT/RIGHT
+ switch (where) {
+ case "left":
+ case KC.LEFT:
+ if (this.expanded) {
+ return this.setExpanded(false);
+ }
+ break;
+ case "right":
+ case KC.RIGHT:
+ if (!this.expanded && (this.children || this.lazy)) {
+ return this.setExpanded();
+ }
+ break;
+ }
+ // Otherwise activate or focus the related node
+ node = this.findRelatedNode(where);
+ if (node) {
+ // setFocus/setActive will scroll later (if autoScroll is specified)
+ try {
+ node.makeVisible({ scrollIntoView: false });
+ } catch (e) {} // #272
+ if (activate === false) {
+ node.setFocus();
+ return _getResolvedPromise();
+ }
+ return node.setActive();
+ }
+ this.warn("Could not find related node '" + where + "'.");
+ return _getResolvedPromise();
+ },
+ /**
+ * Remove this node (not allowed for system root).
+ */
+ remove: function () {
+ return this.parent.removeChild(this);
+ },
+ /**
+ * Remove childNode from list of direct children.
+ * @param {FancytreeNode} childNode
+ */
+ removeChild: function (childNode) {
+ return this.tree._callHook("nodeRemoveChild", this, childNode);
+ },
+ /**
+ * Remove all child nodes and descendents. This converts the node into a leaf.<br>
+ * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy()
+ * in order to trigger lazyLoad on next expand.
+ */
+ removeChildren: function () {
+ return this.tree._callHook("nodeRemoveChildren", this);
+ },
+ /**
+ * Remove class from node's span tag and .extraClasses.
+ *
+ * @param {string} className class name
+ *
+ * @since 2.17
+ */
+ removeClass: function (className) {
+ return this.toggleClass(className, false);
+ },
+ /**
+ * This method renders and updates all HTML markup that is required
+ * to display this node in its current state.<br>
+ * Note:
+ * <ul>
+ * <li>It should only be neccessary to call this method after the node object
+ * was modified by direct access to its properties, because the common
+ * API methods (node.setTitle(), moveTo(), addChildren(), remove(), ...)
+ * already handle this.
+ * <li> {@link FancytreeNode#renderTitle} and {@link FancytreeNode#renderStatus}
+ * are implied. If changes are more local, calling only renderTitle() or
+ * renderStatus() may be sufficient and faster.
+ * </ul>
+ *
+ * @param {boolean} [force=false] re-render, even if html markup was already created
+ * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+ */
+ render: function (force, deep) {
+ return this.tree._callHook("nodeRender", this, force, deep);
+ },
+ /** Create HTML markup for the node's outer `<span>` (expander, checkbox, icon, and title).
+ * Implies {@link FancytreeNode#renderStatus}.
+ * @see Fancytree_Hooks#nodeRenderTitle
+ */
+ renderTitle: function () {
+ return this.tree._callHook("nodeRenderTitle", this);
+ },
+ /** Update element's CSS classes according to node state.
+ * @see Fancytree_Hooks#nodeRenderStatus
+ */
+ renderStatus: function () {
+ return this.tree._callHook("nodeRenderStatus", this);
+ },
+ /**
+ * (experimental) Replace this node with `source`.
+ * (Currently only available for paging nodes.)
+ * @param {NodeData[]} source List of child node definitions
+ * @since 2.15
+ */
+ replaceWith: function (source) {
+ var res,
+ parent = this.parent,
+ pos = $.inArray(this, parent.children),
+ self = this;
+
+ _assert(
+ this.isPagingNode(),
+ "replaceWith() currently requires a paging status node"
+ );
+
+ res = this.tree._callHook("nodeLoadChildren", this, source);
+ res.done(function (data) {
+ // New nodes are currently children of `this`.
+ var children = self.children;
+ // Prepend newly loaded child nodes to `this`
+ // Move new children after self
+ for (i = 0; i < children.length; i++) {
+ children[i].parent = parent;
+ }
+ parent.children.splice.apply(
+ parent.children,
+ [pos + 1, 0].concat(children)
+ );
+
+ // Remove self
+ self.children = null;
+ self.remove();
+ // Redraw new nodes
+ parent.render();
+ // TODO: set node.partload = false if this was tha last paging node?
+ // parent.addPagingNode(false);
+ }).fail(function () {
+ self.setExpanded();
+ });
+ return res;
+ // $.error("Not implemented: replaceWith()");
+ },
+ /**
+ * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad
+ * event is triggered on next expand.
+ */
+ resetLazy: function () {
+ this.removeChildren();
+ this.expanded = false;
+ this.lazy = true;
+ this.children = undefined;
+ this.renderStatus();
+ },
+ /** Schedule activity for delayed execution (cancel any pending request).
+ * scheduleAction('cancel') will only cancel a pending request (if any).
+ * @param {string} mode
+ * @param {number} ms
+ */
+ scheduleAction: function (mode, ms) {
+ if (this.tree.timer) {
+ clearTimeout(this.tree.timer);
+ this.tree.debug("clearTimeout(%o)", this.tree.timer);
+ }
+ this.tree.timer = null;
+ var self = this; // required for closures
+ switch (mode) {
+ case "cancel":
+ // Simply made sure that timer was cleared
+ break;
+ case "expand":
+ this.tree.timer = setTimeout(function () {
+ self.tree.debug("setTimeout: trigger expand");
+ self.setExpanded(true);
+ }, ms);
+ break;
+ case "activate":
+ this.tree.timer = setTimeout(function () {
+ self.tree.debug("setTimeout: trigger activate");
+ self.setActive(true);
+ }, ms);
+ break;
+ default:
+ $.error("Invalid mode " + mode);
+ }
+ // this.tree.debug("setTimeout(%s, %s): %s", mode, ms, this.tree.timer);
+ },
+ /**
+ *
+ * @param {boolean | PlainObject} [effects=false] animation options.
+ * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in
+ * any case, even if `this` is outside the scroll pane.
+ * @returns {$.Promise}
+ */
+ scrollIntoView: function (effects, options) {
+ if (options !== undefined && _isNode(options)) {
+ throw Error(
+ "scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead."
+ );
+ }
+ // The scroll parent is typically the plain tree's <UL> container.
+ // For ext-table, we choose the nearest parent that has `position: relative`
+ // and `overflow` set.
+ // (This default can be overridden by the local or global `scrollParent` option.)
+ var opts = $.extend(
+ {
+ effects:
+ effects === true
+ ? { duration: 200, queue: false }
+ : effects,
+ scrollOfs: this.tree.options.scrollOfs,
+ scrollParent: this.tree.options.scrollParent,
+ topNode: null,
+ },
+ options
+ ),
+ $scrollParent = opts.scrollParent,
+ $container = this.tree.$container,
+ overflowY = $container.css("overflow-y");
+
+ if (!$scrollParent) {
+ if (this.tree.tbody) {
+ $scrollParent = $container.scrollParent();
+ } else if (overflowY === "scroll" || overflowY === "auto") {
+ $scrollParent = $container;
+ } else {
+ // #922 plain tree in a non-fixed-sized UL scrolls inside its parent
+ $scrollParent = $container.scrollParent();
+ }
+ } else if (!$scrollParent.jquery) {
+ // Make sure we have a jQuery object
+ $scrollParent = $($scrollParent);
+ }
+ if (
+ $scrollParent[0] === document ||
+ $scrollParent[0] === document.body
+ ) {
+ // `document` may be returned by $().scrollParent(), if nothing is found,
+ // but would not work: (see #894)
+ this.debug(
+ "scrollIntoView(): normalizing scrollParent to 'window':",
+ $scrollParent[0]
+ );
+ $scrollParent = $(window);
+ }
+ // eslint-disable-next-line one-var
+ var topNodeY,
+ nodeY,
+ horzScrollbarHeight,
+ containerOffsetTop,
+ dfd = new $.Deferred(),
+ self = this,
+ nodeHeight = $(this.span).height(),
+ topOfs = opts.scrollOfs.top || 0,
+ bottomOfs = opts.scrollOfs.bottom || 0,
+ containerHeight = $scrollParent.height(),
+ scrollTop = $scrollParent.scrollTop(),
+ $animateTarget = $scrollParent,
+ isParentWindow = $scrollParent[0] === window,
+ topNode = opts.topNode || null,
+ newScrollTop = null;
+
+ // this.debug("scrollIntoView(), scrollTop=" + scrollTop, opts.scrollOfs);
+ // _assert($(this.span).is(":visible"), "scrollIntoView node is invisible"); // otherwise we cannot calc offsets
+ if (this.isRootNode() || !this.isVisible()) {
+ // We cannot calc offsets for hidden elements
+ this.info("scrollIntoView(): node is invisible.");
+ return _getResolvedPromise();
+ }
+ if (isParentWindow) {
+ nodeY = $(this.span).offset().top;
+ topNodeY =
+ topNode && topNode.span ? $(topNode.span).offset().top : 0;
+ $animateTarget = $("html,body");
+ } else {
+ _assert(
+ $scrollParent[0] !== document &&
+ $scrollParent[0] !== document.body,
+ "scrollParent should be a simple element or `window`, not document or body."
+ );
+
+ containerOffsetTop = $scrollParent.offset().top;
+ nodeY =
+ $(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent
+ topNodeY = topNode
+ ? $(topNode.span).offset().top -
+ containerOffsetTop +
+ scrollTop
+ : 0;
+ horzScrollbarHeight = Math.max(
+ 0,
+ $scrollParent.innerHeight() - $scrollParent[0].clientHeight
+ );
+ containerHeight -= horzScrollbarHeight;
+ }
+
+ // this.debug(" scrollIntoView(), nodeY=" + nodeY + ", containerHeight=" + containerHeight);
+ if (nodeY < scrollTop + topOfs) {
+ // Node is above visible container area
+ newScrollTop = nodeY - topOfs;
+ // this.debug(" scrollIntoView(), UPPER newScrollTop=" + newScrollTop);
+ } else if (
+ nodeY + nodeHeight >
+ scrollTop + containerHeight - bottomOfs
+ ) {
+ newScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs;
+ // this.debug(" scrollIntoView(), LOWER newScrollTop=" + newScrollTop);
+ // If a topNode was passed, make sure that it is never scrolled
+ // outside the upper border
+ if (topNode) {
+ _assert(
+ topNode.isRootNode() || topNode.isVisible(),
+ "topNode must be visible"
+ );
+ if (topNodeY < newScrollTop) {
+ newScrollTop = topNodeY - topOfs;
+ // this.debug(" scrollIntoView(), TOP newScrollTop=" + newScrollTop);
+ }
+ }
+ }
+
+ if (newScrollTop === null) {
+ dfd.resolveWith(this);
+ } else {
+ // this.debug(" scrollIntoView(), SET newScrollTop=" + newScrollTop);
+ if (opts.effects) {
+ opts.effects.complete = function () {
+ dfd.resolveWith(self);
+ };
+ $animateTarget.stop(true).animate(
+ {
+ scrollTop: newScrollTop,
+ },
+ opts.effects
+ );
+ } else {
+ $animateTarget[0].scrollTop = newScrollTop;
+ dfd.resolveWith(this);
+ }
+ }
+ return dfd.promise();
+ },
+
+ /**Activate this node.
+ *
+ * The `cell` option requires the ext-table and ext-ariagrid extensions.
+ *
+ * @param {boolean} [flag=true] pass false to deactivate
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false, cell: null}
+ * @returns {$.Promise}
+ */
+ setActive: function (flag, opts) {
+ return this.tree._callHook("nodeSetActive", this, flag, opts);
+ },
+ /**Expand or collapse this node. Promise is resolved, when lazy loading and animations are done.
+ * @param {boolean} [flag=true] pass false to collapse
+ * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}
+ * @returns {$.Promise}
+ */
+ setExpanded: function (flag, opts) {
+ return this.tree._callHook("nodeSetExpanded", this, flag, opts);
+ },
+ /**Set keyboard focus to this node.
+ * @param {boolean} [flag=true] pass false to blur
+ * @see Fancytree#setFocus
+ */
+ setFocus: function (flag) {
+ return this.tree._callHook("nodeSetFocus", this, flag);
+ },
+ /**Select this node, i.e. check the checkbox.
+ * @param {boolean} [flag=true] pass false to deselect
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, p
+ * propagateDown: null, propagateUp: null, callback: null }
+ */
+ setSelected: function (flag, opts) {
+ return this.tree._callHook("nodeSetSelected", this, flag, opts);
+ },
+ /**Mark a lazy node as 'error', 'loading', 'nodata', or 'ok'.
+ * @param {string} status 'error'|'loading'|'nodata'|'ok'
+ * @param {string} [message]
+ * @param {string} [details]
+ */
+ setStatus: function (status, message, details) {
+ return this.tree._callHook(
+ "nodeSetStatus",
+ this,
+ status,
+ message,
+ details
+ );
+ },
+ /**Rename this node.
+ * @param {string} title
+ */
+ setTitle: function (title) {
+ this.title = title;
+ this.renderTitle();
+ this.triggerModify("rename");
+ },
+ /**Sort child list by title.
+ * @param {function} [cmp] custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title).
+ * @param {boolean} [deep=false] pass true to sort all descendant nodes
+ */
+ sortChildren: function (cmp, deep) {
+ var i,
+ l,
+ cl = this.children;
+
+ if (!cl) {
+ return;
+ }
+ cmp =
+ cmp ||
+ function (a, b) {
+ var x = a.title.toLowerCase(),
+ y = b.title.toLowerCase();
+
+ // eslint-disable-next-line no-nested-ternary
+ return x === y ? 0 : x > y ? 1 : -1;
+ };
+ cl.sort(cmp);
+ if (deep) {
+ for (i = 0, l = cl.length; i < l; i++) {
+ if (cl[i].children) {
+ cl[i].sortChildren(cmp, "$norender$");
+ }
+ }
+ }
+ if (deep !== "$norender$") {
+ this.render();
+ }
+ this.triggerModifyChild("sort");
+ },
+ /** Convert node (or whole branch) into a plain object.
+ *
+ * The result is compatible with node.addChildren().
+ *
+ * @param {boolean} [recursive=false] include child nodes
+ * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications.
+ * Return `false` to ignore this node or `"skip"` to include this node without its children.
+ * @returns {NodeData}
+ */
+ toDict: function (recursive, callback) {
+ var i,
+ l,
+ node,
+ res,
+ dict = {},
+ self = this;
+
+ $.each(NODE_ATTRS, function (i, a) {
+ if (self[a] || self[a] === false) {
+ dict[a] = self[a];
+ }
+ });
+ if (!$.isEmptyObject(this.data)) {
+ dict.data = $.extend({}, this.data);
+ if ($.isEmptyObject(dict.data)) {
+ delete dict.data;
+ }
+ }
+ if (callback) {
+ res = callback(dict, self);
+ if (res === false) {
+ return false; // Don't include this node nor its children
+ }
+ if (res === "skip") {
+ recursive = false; // Include this node, but not the children
+ }
+ }
+ if (recursive) {
+ if (_isArray(this.children)) {
+ dict.children = [];
+ for (i = 0, l = this.children.length; i < l; i++) {
+ node = this.children[i];
+ if (!node.isStatusNode()) {
+ res = node.toDict(true, callback);
+ if (res !== false) {
+ dict.children.push(res);
+ }
+ }
+ }
+ }
+ }
+ return dict;
+ },
+ /**
+ * Set, clear, or toggle class of node's span tag and .extraClasses.
+ *
+ * @param {string} className class name (separate multiple classes by space)
+ * @param {boolean} [flag] true/false to add/remove class. If omitted, class is toggled.
+ * @returns {boolean} true if a class was added
+ *
+ * @since 2.17
+ */
+ toggleClass: function (value, flag) {
+ var className,
+ hasClass,
+ rnotwhite = /\S+/g,
+ classNames = value.match(rnotwhite) || [],
+ i = 0,
+ wasAdded = false,
+ statusElem = this[this.tree.statusClassPropName],
+ curClasses = " " + (this.extraClasses || "") + " ";
+
+ // this.info("toggleClass('" + value + "', " + flag + ")", curClasses);
+ // Modify DOM element directly if it already exists
+ if (statusElem) {
+ $(statusElem).toggleClass(value, flag);
+ }
+ // Modify node.extraClasses to make this change persistent
+ // Toggle if flag was not passed
+ while ((className = classNames[i++])) {
+ hasClass = curClasses.indexOf(" " + className + " ") >= 0;
+ flag = flag === undefined ? !hasClass : !!flag;
+ if (flag) {
+ if (!hasClass) {
+ curClasses += className + " ";
+ wasAdded = true;
+ }
+ } else {
+ while (curClasses.indexOf(" " + className + " ") > -1) {
+ curClasses = curClasses.replace(
+ " " + className + " ",
+ " "
+ );
+ }
+ }
+ }
+ this.extraClasses = _trim(curClasses);
+ // this.info("-> toggleClass('" + value + "', " + flag + "): '" + this.extraClasses + "'");
+ return wasAdded;
+ },
+ /** Flip expanded status. */
+ toggleExpanded: function () {
+ return this.tree._callHook("nodeToggleExpanded", this);
+ },
+ /** Flip selection status. */
+ toggleSelected: function () {
+ return this.tree._callHook("nodeToggleSelected", this);
+ },
+ toString: function () {
+ return "FancytreeNode@" + this.key + "[title='" + this.title + "']";
+ // return "<FancytreeNode(#" + this.key + ", '" + this.title + "')>";
+ },
+ /**
+ * Trigger `modifyChild` event on a parent to signal that a child was modified.
+ * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
+ * @param {FancytreeNode} [childNode]
+ * @param {object} [extra]
+ */
+ triggerModifyChild: function (operation, childNode, extra) {
+ var data,
+ modifyChild = this.tree.options.modifyChild;
+
+ if (modifyChild) {
+ if (childNode && childNode.parent !== this) {
+ $.error(
+ "childNode " + childNode + " is not a child of " + this
+ );
+ }
+ data = {
+ node: this,
+ tree: this.tree,
+ operation: operation,
+ childNode: childNode || null,
+ };
+ if (extra) {
+ $.extend(data, extra);
+ }
+ modifyChild({ type: "modifyChild" }, data);
+ }
+ },
+ /**
+ * Trigger `modifyChild` event on node.parent(!).
+ * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...
+ * @param {object} [extra]
+ */
+ triggerModify: function (operation, extra) {
+ this.parent.triggerModifyChild(operation, this, extra);
+ },
+ /** Call fn(node) for all child nodes in hierarchical order (depth-first).<br>
+ * Stop iteration, if fn() returns false. Skip current branch, if fn() returns "skip".<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and
+ * its children only.
+ * @param {boolean} [includeSelf=false]
+ * @returns {boolean}
+ */
+ visit: function (fn, includeSelf) {
+ var i,
+ l,
+ res = true,
+ children = this.children;
+
+ if (includeSelf === true) {
+ res = fn(this);
+ if (res === false || res === "skip") {
+ return res;
+ }
+ }
+ if (children) {
+ for (i = 0, l = children.length; i < l; i++) {
+ res = children[i].visit(fn, true);
+ if (res === false) {
+ break;
+ }
+ }
+ }
+ return res;
+ },
+ /** Call fn(node) for all child nodes and recursively load lazy children.<br>
+ * <b>Note:</b> If you need this method, you probably should consider to review
+ * your architecture! Recursivley loading nodes is a perfect way for lazy
+ * programmers to flood the server with requests ;-)
+ *
+ * @param {function} [fn] optional callback function.
+ * Return false to stop iteration, return "skip" to skip this node and
+ * its children only.
+ * @param {boolean} [includeSelf=false]
+ * @returns {$.Promise}
+ * @since 2.4
+ */
+ visitAndLoad: function (fn, includeSelf, _recursion) {
+ var dfd,
+ res,
+ loaders,
+ node = this;
+
+ // node.debug("visitAndLoad");
+ if (fn && includeSelf === true) {
+ res = fn(node);
+ if (res === false || res === "skip") {
+ return _recursion ? res : _getResolvedPromise();
+ }
+ }
+ if (!node.children && !node.lazy) {
+ return _getResolvedPromise();
+ }
+ dfd = new $.Deferred();
+ loaders = [];
+ // node.debug("load()...");
+ node.load().done(function () {
+ // node.debug("load()... done.");
+ for (var i = 0, l = node.children.length; i < l; i++) {
+ res = node.children[i].visitAndLoad(fn, true, true);
+ if (res === false) {
+ dfd.reject();
+ break;
+ } else if (res !== "skip") {
+ loaders.push(res); // Add promise to the list
+ }
+ }
+ $.when.apply(this, loaders).then(function () {
+ dfd.resolve();
+ });
+ });
+ return dfd.promise();
+ },
+ /** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>
+ * Stop iteration, if fn() returns false.<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and children only.
+ * @param {boolean} [includeSelf=false]
+ * @returns {boolean}
+ */
+ visitParents: function (fn, includeSelf) {
+ // Visit parent nodes (bottom up)
+ if (includeSelf && fn(this) === false) {
+ return false;
+ }
+ var p = this.parent;
+ while (p) {
+ if (fn(p) === false) {
+ return false;
+ }
+ p = p.parent;
+ }
+ return true;
+ },
+ /** Call fn(node) for all sibling nodes.<br>
+ * Stop iteration, if fn() returns false.<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration.
+ * @param {boolean} [includeSelf=false]
+ * @returns {boolean}
+ */
+ visitSiblings: function (fn, includeSelf) {
+ var i,
+ l,
+ n,
+ ac = this.parent.children;
+
+ for (i = 0, l = ac.length; i < l; i++) {
+ n = ac[i];
+ if (includeSelf || n !== this) {
+ if (fn(n) === false) {
+ return false;
+ }
+ }
+ }
+ return true;
+ },
+ /** Write warning to browser console if debugLevel >= 2 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ warn: function (msg) {
+ if (this.tree.options.debugLevel >= 2) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("warn", arguments);
+ }
+ },
+ };
+
+ /******************************************************************************
+ * Fancytree
+ */
+ /**
+ * Construct a new tree object.
+ *
+ * @class Fancytree
+ * @classdesc The controller behind a fancytree.
+ * This class also contains 'hook methods': see {@link Fancytree_Hooks}.
+ *
+ * @param {Widget} widget
+ *
+ * @property {string} _id Automatically generated unique tree instance ID, e.g. "1".
+ * @property {string} _ns Automatically generated unique tree namespace, e.g. ".fancytree-1".
+ * @property {FancytreeNode} activeNode Currently active node or null.
+ * @property {string} ariaPropName Property name of FancytreeNode that contains the element which will receive the aria attributes.
+ * Typically "li", but "tr" for table extension.
+ * @property {jQueryObject} $container Outer `<ul>` element (or `<table>` element for ext-table).
+ * @property {jQueryObject} $div A jQuery object containing the element used to instantiate the tree widget (`widget.element`)
+ * @property {object|array} columns Recommended place to store shared column meta data. @since 2.27
+ * @property {object} data Metadata, i.e. properties that may be passed to `source` in addition to a children array.
+ * @property {object} ext Hash of all active plugin instances.
+ * @property {FancytreeNode} focusNode Currently focused node or null.
+ * @property {FancytreeNode} lastSelectedNode Used to implement selectMode 1 (single select)
+ * @property {string} nodeContainerAttrName Property name of FancytreeNode that contains the outer element of single nodes.
+ * Typically "li", but "tr" for table extension.
+ * @property {FancytreeOptions} options Current options, i.e. default options + options passed to constructor.
+ * @property {FancytreeNode} rootNode Invisible system root node.
+ * @property {string} statusClassPropName Property name of FancytreeNode that contains the element which will receive the status classes.
+ * Typically "span", but "tr" for table extension.
+ * @property {object} types Map for shared type specific meta data, used with node.type attribute. @since 2.27
+ * @property {object} viewport See ext-vieport. @since v2.31
+ * @property {object} widget Base widget instance.
+ */
+ function Fancytree(widget) {
+ this.widget = widget;
+ this.$div = widget.element;
+ this.options = widget.options;
+ if (this.options) {
+ if (this.options.lazyload !== undefined) {
+ $.error(
+ "The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."
+ );
+ }
+ if (this.options.loaderror !== undefined) {
+ $.error(
+ "The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."
+ );
+ }
+ if (this.options.fx !== undefined) {
+ $.error(
+ "The 'fx' option was replaced by 'toggleEffect' since 2014-11-30."
+ );
+ }
+ if (this.options.removeNode !== undefined) {
+ $.error(
+ "The 'removeNode' event was replaced by 'modifyChild' since 2.20 (2016-09-10)."
+ );
+ }
+ }
+ this.ext = {}; // Active extension instances
+ this.types = {};
+ this.columns = {};
+ // allow to init tree.data.foo from <div data-foo=''>
+ this.data = _getElementDataAsDict(this.$div);
+ // TODO: use widget.uuid instead?
+ this._id = "" + (this.options.treeId || $.ui.fancytree._nextId++);
+ // TODO: use widget.eventNamespace instead?
+ this._ns = ".fancytree-" + this._id; // append for namespaced events
+ this.activeNode = null;
+ this.focusNode = null;
+ this._hasFocus = null;
+ this._tempCache = {};
+ this._lastMousedownNode = null;
+ this._enableUpdate = true;
+ this.lastSelectedNode = null;
+ this.systemFocusElement = null;
+ this.lastQuicksearchTerm = "";
+ this.lastQuicksearchTime = 0;
+ this.viewport = null; // ext-grid
+
+ this.statusClassPropName = "span";
+ this.ariaPropName = "li";
+ this.nodeContainerAttrName = "li";
+
+ // Remove previous markup if any
+ this.$div.find(">ul.fancytree-container").remove();
+
+ // Create a node without parent.
+ var fakeParent = { tree: this },
+ $ul;
+ this.rootNode = new FancytreeNode(fakeParent, {
+ title: "root",
+ key: "root_" + this._id,
+ children: null,
+ expanded: true,
+ });
+ this.rootNode.parent = null;
+
+ // Create root markup
+ $ul = $("<ul>", {
+ id: "ft-id-" + this._id,
+ class: "ui-fancytree fancytree-container fancytree-plain",
+ }).appendTo(this.$div);
+ this.$container = $ul;
+ this.rootNode.ul = $ul[0];
+
+ if (this.options.debugLevel == null) {
+ this.options.debugLevel = FT.debugLevel;
+ }
+ // // Add container to the TAB chain
+ // // See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant
+ // // #577: Allow to set tabindex to "0", "-1" and ""
+ // this.$container.attr("tabindex", this.options.tabindex);
+
+ // if( this.options.rtl ) {
+ // this.$container.attr("DIR", "RTL").addClass("fancytree-rtl");
+ // // }else{
+ // // this.$container.attr("DIR", null).removeClass("fancytree-rtl");
+ // }
+ // if(this.options.aria){
+ // this.$container.attr("role", "tree");
+ // if( this.options.selectMode !== 1 ) {
+ // this.$container.attr("aria-multiselectable", true);
+ // }
+ // }
+ }
+
+ Fancytree.prototype = /** @lends Fancytree# */ {
+ /* Return a context object that can be re-used for _callHook().
+ * @param {Fancytree | FancytreeNode | EventData} obj
+ * @param {Event} originalEvent
+ * @param {Object} extra
+ * @returns {EventData}
+ */
+ _makeHookContext: function (obj, originalEvent, extra) {
+ var ctx, tree;
+ if (obj.node !== undefined) {
+ // obj is already a context object
+ if (originalEvent && obj.originalEvent !== originalEvent) {
+ $.error("invalid args");
+ }
+ ctx = obj;
+ } else if (obj.tree) {
+ // obj is a FancytreeNode
+ tree = obj.tree;
+ ctx = {
+ node: obj,
+ tree: tree,
+ widget: tree.widget,
+ options: tree.widget.options,
+ originalEvent: originalEvent,
+ typeInfo: tree.types[obj.type] || {},
+ };
+ } else if (obj.widget) {
+ // obj is a Fancytree
+ ctx = {
+ node: null,
+ tree: obj,
+ widget: obj.widget,
+ options: obj.widget.options,
+ originalEvent: originalEvent,
+ };
+ } else {
+ $.error("invalid args");
+ }
+ if (extra) {
+ $.extend(ctx, extra);
+ }
+ return ctx;
+ },
+ /* Trigger a hook function: funcName(ctx, [...]).
+ *
+ * @param {string} funcName
+ * @param {Fancytree|FancytreeNode|EventData} contextObject
+ * @param {any} [_extraArgs] optional additional arguments
+ * @returns {any}
+ */
+ _callHook: function (funcName, contextObject, _extraArgs) {
+ var ctx = this._makeHookContext(contextObject),
+ fn = this[funcName],
+ args = Array.prototype.slice.call(arguments, 2);
+ if (!_isFunction(fn)) {
+ $.error("_callHook('" + funcName + "') is not a function");
+ }
+ args.unshift(ctx);
+ // this.debug("_hook", funcName, ctx.node && ctx.node.toString() || ctx.tree.toString(), args);
+ return fn.apply(this, args);
+ },
+ _setExpiringValue: function (key, value, ms) {
+ this._tempCache[key] = {
+ value: value,
+ expire: Date.now() + (+ms || 50),
+ };
+ },
+ _getExpiringValue: function (key) {
+ var entry = this._tempCache[key];
+ if (entry && entry.expire > Date.now()) {
+ return entry.value;
+ }
+ delete this._tempCache[key];
+ return null;
+ },
+ /* Check if this tree has extension `name` enabled.
+ *
+ * @param {string} name name of the required extension
+ */
+ _usesExtension: function (name) {
+ return $.inArray(name, this.options.extensions) >= 0;
+ },
+ /* Check if current extensions dependencies are met and throw an error if not.
+ *
+ * This method may be called inside the `treeInit` hook for custom extensions.
+ *
+ * @param {string} name name of the required extension
+ * @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present
+ * @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter)
+ * @param {string} [message] optional error message (defaults to a descriptve error message)
+ */
+ _requireExtension: function (name, required, before, message) {
+ if (before != null) {
+ before = !!before;
+ }
+ var thisName = this._local.name,
+ extList = this.options.extensions,
+ isBefore =
+ $.inArray(name, extList) < $.inArray(thisName, extList),
+ isMissing = required && this.ext[name] == null,
+ badOrder = !isMissing && before != null && before !== isBefore;
+
+ _assert(
+ thisName && thisName !== name,
+ "invalid or same name '" + thisName + "' (require yourself?)"
+ );
+
+ if (isMissing || badOrder) {
+ if (!message) {
+ if (isMissing || required) {
+ message =
+ "'" +
+ thisName +
+ "' extension requires '" +
+ name +
+ "'";
+ if (badOrder) {
+ message +=
+ " to be registered " +
+ (before ? "before" : "after") +
+ " itself";
+ }
+ } else {
+ message =
+ "If used together, `" +
+ name +
+ "` must be registered " +
+ (before ? "before" : "after") +
+ " `" +
+ thisName +
+ "`";
+ }
+ }
+ $.error(message);
+ return false;
+ }
+ return true;
+ },
+ /** Activate node with a given key and fire focus and activate events.
+ *
+ * A previously activated node will be deactivated.
+ * If activeVisible option is set, all parents will be expanded as necessary.
+ * Pass key = false, to deactivate the current node only.
+ * @param {string} key
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}
+ * @returns {FancytreeNode} activated node (null, if not found)
+ */
+ activateKey: function (key, opts) {
+ var node = this.getNodeByKey(key);
+ if (node) {
+ node.setActive(true, opts);
+ } else if (this.activeNode) {
+ this.activeNode.setActive(false, opts);
+ }
+ return node;
+ },
+ /** (experimental) Add child status nodes that indicate 'More...', ....
+ * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.
+ * @param {string} [mode='append'] 'child'|firstChild'
+ * @since 2.15
+ */
+ addPagingNode: function (node, mode) {
+ return this.rootNode.addPagingNode(node, mode);
+ },
+ /**
+ * (experimental) Apply a modification (or navigation) operation.
+ *
+ * Valid commands:
+ * - 'moveUp', 'moveDown'
+ * - 'indent', 'outdent'
+ * - 'remove'
+ * - 'edit', 'addChild', 'addSibling': (reqires ext-edit extension)
+ * - 'cut', 'copy', 'paste': (use an internal singleton 'clipboard')
+ * - 'down', 'first', 'last', 'left', 'parent', 'right', 'up': navigate
+ *
+ * @param {string} cmd
+ * @param {FancytreeNode} [node=active_node]
+ * @param {object} [opts] Currently unused
+ *
+ * @since 2.32
+ */
+ applyCommand: function (cmd, node, opts_) {
+ var // clipboard,
+ refNode;
+ // opts = $.extend(
+ // { setActive: true, clipboard: CLIPBOARD },
+ // opts_
+ // );
+
+ node = node || this.getActiveNode();
+ // clipboard = opts.clipboard;
+
+ switch (cmd) {
+ // Sorting and indentation:
+ case "moveUp":
+ refNode = node.getPrevSibling();
+ if (refNode) {
+ node.moveTo(refNode, "before");
+ node.setActive();
+ }
+ break;
+ case "moveDown":
+ refNode = node.getNextSibling();
+ if (refNode) {
+ node.moveTo(refNode, "after");
+ node.setActive();
+ }
+ break;
+ case "indent":
+ refNode = node.getPrevSibling();
+ if (refNode) {
+ node.moveTo(refNode, "child");
+ refNode.setExpanded();
+ node.setActive();
+ }
+ break;
+ case "outdent":
+ if (!node.isTopLevel()) {
+ node.moveTo(node.getParent(), "after");
+ node.setActive();
+ }
+ break;
+ // Remove:
+ case "remove":
+ refNode = node.getPrevSibling() || node.getParent();
+ node.remove();
+ if (refNode) {
+ refNode.setActive();
+ }
+ break;
+ // Add, edit (requires ext-edit):
+ case "addChild":
+ node.editCreateNode("child", "");
+ break;
+ case "addSibling":
+ node.editCreateNode("after", "");
+ break;
+ case "rename":
+ node.editStart();
+ break;
+ // Simple clipboard simulation:
+ // case "cut":
+ // clipboard = { mode: cmd, data: node };
+ // break;
+ // case "copy":
+ // clipboard = {
+ // mode: cmd,
+ // data: node.toDict(function(d, n) {
+ // delete d.key;
+ // }),
+ // };
+ // break;
+ // case "clear":
+ // clipboard = null;
+ // break;
+ // case "paste":
+ // if (clipboard.mode === "cut") {
+ // // refNode = node.getPrevSibling();
+ // clipboard.data.moveTo(node, "child");
+ // clipboard.data.setActive();
+ // } else if (clipboard.mode === "copy") {
+ // node.addChildren(clipboard.data).setActive();
+ // }
+ // break;
+ // Navigation commands:
+ case "down":
+ case "first":
+ case "last":
+ case "left":
+ case "parent":
+ case "right":
+ case "up":
+ return node.navigate(cmd);
+ default:
+ $.error("Unhandled command: '" + cmd + "'");
+ }
+ },
+ /** (experimental) Modify existing data model.
+ *
+ * @param {Array} patchList array of [key, NodePatch] arrays
+ * @returns {$.Promise} resolved, when all patches have been applied
+ * @see TreePatch
+ */
+ applyPatch: function (patchList) {
+ var dfd,
+ i,
+ p2,
+ key,
+ patch,
+ node,
+ patchCount = patchList.length,
+ deferredList = [];
+
+ for (i = 0; i < patchCount; i++) {
+ p2 = patchList[i];
+ _assert(
+ p2.length === 2,
+ "patchList must be an array of length-2-arrays"
+ );
+ key = p2[0];
+ patch = p2[1];
+ node = key === null ? this.rootNode : this.getNodeByKey(key);
+ if (node) {
+ dfd = new $.Deferred();
+ deferredList.push(dfd);
+ node.applyPatch(patch).always(_makeResolveFunc(dfd, node));
+ } else {
+ this.warn("could not find node with key '" + key + "'");
+ }
+ }
+ // Return a promise that is resolved, when ALL patches were applied
+ return $.when.apply($, deferredList).promise();
+ },
+ /* TODO: implement in dnd extension
+ cancelDrag: function() {
+ var dd = $.ui.ddmanager.current;
+ if(dd){
+ dd.cancel();
+ }
+ },
+ */
+ /** Remove all nodes.
+ * @since 2.14
+ */
+ clear: function (source) {
+ this._callHook("treeClear", this);
+ },
+ /** Return the number of nodes.
+ * @returns {integer}
+ */
+ count: function () {
+ return this.rootNode.countChildren();
+ },
+ /** Write to browser console if debugLevel >= 4 (prepending tree name)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ debug: function (msg) {
+ if (this.options.debugLevel >= 4) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("log", arguments);
+ }
+ },
+ /** Destroy this widget, restore previous markup and cleanup resources.
+ *
+ * @since 2.34
+ */
+ destroy: function () {
+ this.widget.destroy();
+ },
+ /** Enable (or disable) the tree control.
+ *
+ * @param {boolean} [flag=true] pass false to disable
+ * @since 2.30
+ */
+ enable: function (flag) {
+ if (flag === false) {
+ this.widget.disable();
+ } else {
+ this.widget.enable();
+ }
+ },
+ /** Temporarily suppress rendering to improve performance on bulk-updates.
+ *
+ * @param {boolean} flag
+ * @returns {boolean} previous status
+ * @since 2.19
+ */
+ enableUpdate: function (flag) {
+ flag = flag !== false;
+ if (!!this._enableUpdate === !!flag) {
+ return flag;
+ }
+ this._enableUpdate = flag;
+ if (flag) {
+ this.debug("enableUpdate(true): redraw "); //, this._dirtyRoots);
+ this._callHook("treeStructureChanged", this, "enableUpdate");
+ this.render();
+ } else {
+ // this._dirtyRoots = null;
+ this.debug("enableUpdate(false)...");
+ }
+ return !flag; // return previous value
+ },
+ /** Write error to browser console if debugLevel >= 1 (prepending tree info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ error: function (msg) {
+ if (this.options.debugLevel >= 1) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("error", arguments);
+ }
+ },
+ /** Expand (or collapse) all parent nodes.
+ *
+ * This convenience method uses `tree.visit()` and `tree.setExpanded()`
+ * internally.
+ *
+ * @param {boolean} [flag=true] pass false to collapse
+ * @param {object} [opts] passed to setExpanded()
+ * @since 2.30
+ */
+ expandAll: function (flag, opts) {
+ var prev = this.enableUpdate(false);
+
+ flag = flag !== false;
+ this.visit(function (node) {
+ if (
+ node.hasChildren() !== false &&
+ node.isExpanded() !== flag
+ ) {
+ node.setExpanded(flag, opts);
+ }
+ });
+ this.enableUpdate(prev);
+ },
+ /**Find all nodes that matches condition.
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode[]} array of nodes (may be empty)
+ * @see FancytreeNode#findAll
+ * @since 2.12
+ */
+ findAll: function (match) {
+ return this.rootNode.findAll(match);
+ },
+ /**Find first node that matches condition.
+ *
+ * @param {string | function(node)} match title string to search for, or a
+ * callback function that returns `true` if a node is matched.
+ * @returns {FancytreeNode} matching node or null
+ * @see FancytreeNode#findFirst
+ * @since 2.12
+ */
+ findFirst: function (match) {
+ return this.rootNode.findFirst(match);
+ },
+ /** Find the next visible node that starts with `match`, starting at `startNode`
+ * and wrap-around at the end.
+ *
+ * @param {string|function} match
+ * @param {FancytreeNode} [startNode] defaults to first node
+ * @returns {FancytreeNode} matching node or null
+ */
+ findNextNode: function (match, startNode) {
+ //, visibleOnly) {
+ var res = null,
+ firstNode = this.getFirstChild();
+
+ match =
+ typeof match === "string"
+ ? _makeNodeTitleStartMatcher(match)
+ : match;
+ startNode = startNode || firstNode;
+
+ function _checkNode(n) {
+ // console.log("_check " + n)
+ if (match(n)) {
+ res = n;
+ }
+ if (res || n === startNode) {
+ return false;
+ }
+ }
+ this.visitRows(_checkNode, {
+ start: startNode,
+ includeSelf: false,
+ });
+ // Wrap around search
+ if (!res && startNode !== firstNode) {
+ this.visitRows(_checkNode, {
+ start: firstNode,
+ includeSelf: true,
+ });
+ }
+ return res;
+ },
+ /** Find a node relative to another node.
+ *
+ * @param {FancytreeNode} node
+ * @param {string|number} where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.
+ * (Alternatively the keyCode that would normally trigger this move,
+ * e.g. `$.ui.keyCode.LEFT` = 'left'.
+ * @param {boolean} [includeHidden=false] Not yet implemented
+ * @returns {FancytreeNode|null}
+ * @since v2.31
+ */
+ findRelatedNode: function (node, where, includeHidden) {
+ var res = null,
+ KC = $.ui.keyCode;
+
+ switch (where) {
+ case "parent":
+ case KC.BACKSPACE:
+ if (node.parent && node.parent.parent) {
+ res = node.parent;
+ }
+ break;
+ case "first":
+ case KC.HOME:
+ // First visible node
+ this.visit(function (n) {
+ if (n.isVisible()) {
+ res = n;
+ return false;
+ }
+ });
+ break;
+ case "last":
+ case KC.END:
+ this.visit(function (n) {
+ // last visible node
+ if (n.isVisible()) {
+ res = n;
+ }
+ });
+ break;
+ case "left":
+ case KC.LEFT:
+ if (node.expanded) {
+ node.setExpanded(false);
+ } else if (node.parent && node.parent.parent) {
+ res = node.parent;
+ }
+ break;
+ case "right":
+ case KC.RIGHT:
+ if (!node.expanded && (node.children || node.lazy)) {
+ node.setExpanded();
+ res = node;
+ } else if (node.children && node.children.length) {
+ res = node.children[0];
+ }
+ break;
+ case "up":
+ case KC.UP:
+ this.visitRows(
+ function (n) {
+ res = n;
+ return false;
+ },
+ { start: node, reverse: true, includeSelf: false }
+ );
+ break;
+ case "down":
+ case KC.DOWN:
+ this.visitRows(
+ function (n) {
+ res = n;
+ return false;
+ },
+ { start: node, includeSelf: false }
+ );
+ break;
+ default:
+ this.tree.warn("Unknown relation '" + where + "'.");
+ }
+ return res;
+ },
+ // TODO: fromDict
+ /**
+ * Generate INPUT elements that can be submitted with html forms.
+ *
+ * In selectMode 3 only the topmost selected nodes are considered, unless
+ * `opts.stopOnParents: false` is passed.
+ *
+ * @example
+ * // Generate input elements for active and selected nodes
+ * tree.generateFormElements();
+ * // Generate input elements selected nodes, using a custom `name` attribute
+ * tree.generateFormElements("cust_sel", false);
+ * // Generate input elements using a custom filter
+ * tree.generateFormElements(true, true, { filter: function(node) {
+ * return node.isSelected() && node.data.yes;
+ * }});
+ *
+ * @param {boolean | string} [selected=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID[]')
+ * @param {boolean | string} [active=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID_active')
+ * @param {object} [opts] default { filter: null, stopOnParents: true }
+ */
+ generateFormElements: function (selected, active, opts) {
+ opts = opts || {};
+
+ var nodeList,
+ selectedName =
+ typeof selected === "string"
+ ? selected
+ : "ft_" + this._id + "[]",
+ activeName =
+ typeof active === "string"
+ ? active
+ : "ft_" + this._id + "_active",
+ id = "fancytree_result_" + this._id,
+ $result = $("#" + id),
+ stopOnParents =
+ this.options.selectMode === 3 &&
+ opts.stopOnParents !== false;
+
+ if ($result.length) {
+ $result.empty();
+ } else {
+ $result = $("<div>", {
+ id: id,
+ })
+ .hide()
+ .insertAfter(this.$container);
+ }
+ if (active !== false && this.activeNode) {
+ $result.append(
+ $("<input>", {
+ type: "radio",
+ name: activeName,
+ value: this.activeNode.key,
+ checked: true,
+ })
+ );
+ }
+ function _appender(node) {
+ $result.append(
+ $("<input>", {
+ type: "checkbox",
+ name: selectedName,
+ value: node.key,
+ checked: true,
+ })
+ );
+ }
+ if (opts.filter) {
+ this.visit(function (node) {
+ var res = opts.filter(node);
+ if (res === "skip") {
+ return res;
+ }
+ if (res !== false) {
+ _appender(node);
+ }
+ });
+ } else if (selected !== false) {
+ nodeList = this.getSelectedNodes(stopOnParents);
+ $.each(nodeList, function (idx, node) {
+ _appender(node);
+ });
+ }
+ },
+ /**
+ * Return the currently active node or null.
+ * @returns {FancytreeNode}
+ */
+ getActiveNode: function () {
+ return this.activeNode;
+ },
+ /** Return the first top level node if any (not the invisible root node).
+ * @returns {FancytreeNode | null}
+ */
+ getFirstChild: function () {
+ return this.rootNode.getFirstChild();
+ },
+ /**
+ * Return node that has keyboard focus or null.
+ * @returns {FancytreeNode}
+ */
+ getFocusNode: function () {
+ return this.focusNode;
+ },
+ /**
+ * Return current option value.
+ * (Note: this is the preferred variant of `$().fancytree("option", "KEY")`)
+ *
+ * @param {string} name option name (may contain '.')
+ * @returns {any}
+ */
+ getOption: function (optionName) {
+ return this.widget.option(optionName);
+ },
+ /**
+ * Return node with a given key or null if not found.
+ *
+ * @param {string} key
+ * @param {FancytreeNode} [searchRoot] only search below this node
+ * @returns {FancytreeNode | null}
+ */
+ getNodeByKey: function (key, searchRoot) {
+ // Search the DOM by element ID (assuming this is faster than traversing all nodes).
+ var el, match;
+ // TODO: use tree.keyMap if available
+ // TODO: check opts.generateIds === true
+ if (!searchRoot) {
+ el = document.getElementById(this.options.idPrefix + key);
+ if (el) {
+ return el.ftnode ? el.ftnode : null;
+ }
+ }
+ // Not found in the DOM, but still may be in an unrendered part of tree
+ searchRoot = searchRoot || this.rootNode;
+ match = null;
+ key = "" + key; // Convert to string (#1005)
+ searchRoot.visit(function (node) {
+ if (node.key === key) {
+ match = node;
+ return false; // Stop iteration
+ }
+ }, true);
+ return match;
+ },
+ /** Return the invisible system root node.
+ * @returns {FancytreeNode}
+ */
+ getRootNode: function () {
+ return this.rootNode;
+ },
+ /**
+ * Return an array of selected nodes.
+ *
+ * Note: you cannot send this result via Ajax directly. Instead the
+ * node object need to be converted to plain objects, for example
+ * by using `$.map()` and `node.toDict()`.
+ * @param {boolean} [stopOnParents=false] only return the topmost selected
+ * node (useful with selectMode 3)
+ * @returns {FancytreeNode[]}
+ */
+ getSelectedNodes: function (stopOnParents) {
+ return this.rootNode.getSelectedNodes(stopOnParents);
+ },
+ /** Return true if the tree control has keyboard focus
+ * @returns {boolean}
+ */
+ hasFocus: function () {
+ // var ae = document.activeElement,
+ // hasFocus = !!(
+ // ae && $(ae).closest(".fancytree-container").length
+ // );
+
+ // if (hasFocus !== !!this._hasFocus) {
+ // this.warn(
+ // "hasFocus(): fix inconsistent container state, now: " +
+ // hasFocus
+ // );
+ // this._hasFocus = hasFocus;
+ // this.$container.toggleClass("fancytree-treefocus", hasFocus);
+ // }
+ // return hasFocus;
+ return !!this._hasFocus;
+ },
+ /** Write to browser console if debugLevel >= 3 (prepending tree name)
+ * @param {*} msg string or object or array of such
+ */
+ info: function (msg) {
+ if (this.options.debugLevel >= 3) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("info", arguments);
+ }
+ },
+ /** Return true if any node is currently beeing loaded, i.e. a Ajax request is pending.
+ * @returns {boolean}
+ * @since 2.32
+ */
+ isLoading: function () {
+ var res = false;
+
+ this.rootNode.visit(function (n) {
+ // also visit rootNode
+ if (n._isLoading || n._requestId) {
+ res = true;
+ return false;
+ }
+ }, true);
+ return res;
+ },
+ /*
+ TODO: isInitializing: function() {
+ return ( this.phase=="init" || this.phase=="postInit" );
+ },
+ TODO: isReloading: function() {
+ return ( this.phase=="init" || this.phase=="postInit" ) && this.options.persist && this.persistence.cookiesFound;
+ },
+ TODO: isUserEvent: function() {
+ return ( this.phase=="userEvent" );
+ },
+ */
+
+ /**
+ * Make sure that a node with a given ID is loaded, by traversing - and
+ * loading - its parents. This method is meant for lazy hierarchies.
+ * A callback is executed for every node as we go.
+ * @example
+ * // Resolve using node.key:
+ * tree.loadKeyPath("/_3/_23/_26/_27", function(node, status){
+ * if(status === "loaded") {
+ * console.log("loaded intermediate node " + node);
+ * }else if(status === "ok") {
+ * node.activate();
+ * }
+ * });
+ * // Use deferred promise:
+ * tree.loadKeyPath("/_3/_23/_26/_27").progress(function(data){
+ * if(data.status === "loaded") {
+ * console.log("loaded intermediate node " + data.node);
+ * }else if(data.status === "ok") {
+ * node.activate();
+ * }
+ * }).done(function(){
+ * ...
+ * });
+ * // Custom path segment resolver:
+ * tree.loadKeyPath("/321/431/21/2", {
+ * matchKey: function(node, key){
+ * return node.data.refKey === key;
+ * },
+ * callback: function(node, status){
+ * if(status === "loaded") {
+ * console.log("loaded intermediate node " + node);
+ * }else if(status === "ok") {
+ * node.activate();
+ * }
+ * }
+ * });
+ * @param {string | string[]} keyPathList one or more key paths (e.g. '/3/2_1/7')
+ * @param {function | object} optsOrCallback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error').
+ * Pass an object to define custom key matchers for the path segments: {callback: function, matchKey: function}.
+ * @returns {$.Promise}
+ */
+ loadKeyPath: function (keyPathList, optsOrCallback) {
+ var callback,
+ i,
+ path,
+ self = this,
+ dfd = new $.Deferred(),
+ parent = this.getRootNode(),
+ sep = this.options.keyPathSeparator,
+ pathSegList = [],
+ opts = $.extend({}, optsOrCallback);
+
+ // Prepare options
+ if (typeof optsOrCallback === "function") {
+ callback = optsOrCallback;
+ } else if (optsOrCallback && optsOrCallback.callback) {
+ callback = optsOrCallback.callback;
+ }
+ opts.callback = function (ctx, node, status) {
+ if (callback) {
+ callback.call(ctx, node, status);
+ }
+ dfd.notifyWith(ctx, [{ node: node, status: status }]);
+ };
+ if (opts.matchKey == null) {
+ opts.matchKey = function (node, key) {
+ return node.key === key;
+ };
+ }
+ // Convert array of path strings to array of segment arrays
+ if (!_isArray(keyPathList)) {
+ keyPathList = [keyPathList];
+ }
+ for (i = 0; i < keyPathList.length; i++) {
+ path = keyPathList[i];
+ // strip leading slash
+ if (path.charAt(0) === sep) {
+ path = path.substr(1);
+ }
+ // segListMap[path] = { parent: parent, segList: path.split(sep) };
+ pathSegList.push(path.split(sep));
+ // targetList.push({ parent: parent, segList: path.split(sep)/* , path: path*/});
+ }
+ // The timeout forces async behavior always (even if nodes are all loaded)
+ // This way a potential progress() event will fire.
+ setTimeout(function () {
+ self._loadKeyPathImpl(dfd, opts, parent, pathSegList).done(
+ function () {
+ dfd.resolve();
+ }
+ );
+ }, 0);
+ return dfd.promise();
+ },
+ /*
+ * Resolve a list of paths, relative to one parent node.
+ */
+ _loadKeyPathImpl: function (dfd, opts, parent, pathSegList) {
+ var deferredList,
+ i,
+ key,
+ node,
+ nodeKey,
+ remain,
+ remainMap,
+ tmpParent,
+ segList,
+ subDfd,
+ self = this;
+
+ function __findChild(parent, key) {
+ // console.log("__findChild", key, parent);
+ var i,
+ l,
+ cl = parent.children;
+
+ if (cl) {
+ for (i = 0, l = cl.length; i < l; i++) {
+ if (opts.matchKey(cl[i], key)) {
+ return cl[i];
+ }
+ }
+ }
+ return null;
+ }
+
+ // console.log("_loadKeyPathImpl, parent=", parent, ", pathSegList=", pathSegList);
+
+ // Pass 1:
+ // Handle all path segments for nodes that are already loaded.
+ // Collect distinct top-most lazy nodes in a map.
+ // Note that we can use node.key to de-dupe entries, even if a custom matcher would
+ // look for other node attributes.
+ // map[node.key] => {node: node, pathList: [list of remaining rest-paths]}
+ remainMap = {};
+
+ for (i = 0; i < pathSegList.length; i++) {
+ segList = pathSegList[i];
+ // target = targetList[i];
+
+ // Traverse and pop path segments (i.e. keys), until we hit a lazy, unloaded node
+ tmpParent = parent;
+ while (segList.length) {
+ key = segList.shift();
+ node = __findChild(tmpParent, key);
+ if (!node) {
+ this.warn(
+ "loadKeyPath: key not found: " +
+ key +
+ " (parent: " +
+ tmpParent +
+ ")"
+ );
+ opts.callback(this, key, "error");
+ break;
+ } else if (segList.length === 0) {
+ opts.callback(this, node, "ok");
+ break;
+ } else if (!node.lazy || node.hasChildren() !== undefined) {
+ opts.callback(this, node, "loaded");
+ tmpParent = node;
+ } else {
+ opts.callback(this, node, "loaded");
+ key = node.key; //target.segList.join(sep);
+ if (remainMap[key]) {
+ remainMap[key].pathSegList.push(segList);
+ } else {
+ remainMap[key] = {
+ parent: node,
+ pathSegList: [segList],
+ };
+ }
+ break;
+ }
+ }
+ }
+ // console.log("_loadKeyPathImpl AFTER pass 1, remainMap=", remainMap);
+
+ // Now load all lazy nodes and continue iteration for remaining paths
+ deferredList = [];
+
+ // Avoid jshint warning 'Don't make functions within a loop.':
+ function __lazyload(dfd, parent, pathSegList) {
+ // console.log("__lazyload", parent, "pathSegList=", pathSegList);
+ opts.callback(self, parent, "loading");
+ parent
+ .load()
+ .done(function () {
+ self._loadKeyPathImpl
+ .call(self, dfd, opts, parent, pathSegList)
+ .always(_makeResolveFunc(dfd, self));
+ })
+ .fail(function (errMsg) {
+ self.warn("loadKeyPath: error loading lazy " + parent);
+ opts.callback(self, node, "error");
+ dfd.rejectWith(self);
+ });
+ }
+ // remainMap contains parent nodes, each with a list of relative sub-paths.
+ // We start loading all of them now, and pass the the list to each loader.
+ for (nodeKey in remainMap) {
+ if (_hasProp(remainMap, nodeKey)) {
+ remain = remainMap[nodeKey];
+ // console.log("for(): remain=", remain, "remainMap=", remainMap);
+ // key = remain.segList.shift();
+ // node = __findChild(remain.parent, key);
+ // if (node == null) { // #576
+ // // Issue #576, refactored for v2.27:
+ // // The root cause was, that sometimes the wrong parent was used here
+ // // to find the next segment.
+ // // Falling back to getNodeByKey() was a hack that no longer works if a custom
+ // // matcher is used, because we cannot assume that a single segment-key is unique
+ // // throughout the tree.
+ // self.error("loadKeyPath: error loading child by key '" + key + "' (parent: " + target.parent + ")", target);
+ // // node = self.getNodeByKey(key);
+ // continue;
+ // }
+ subDfd = new $.Deferred();
+ deferredList.push(subDfd);
+ __lazyload(subDfd, remain.parent, remain.pathSegList);
+ }
+ }
+ // Return a promise that is resolved, when ALL paths were loaded
+ return $.when.apply($, deferredList).promise();
+ },
+ /** Re-fire beforeActivate, activate, and (optional) focus events.
+ * Calling this method in the `init` event, will activate the node that
+ * was marked 'active' in the source data, and optionally set the keyboard
+ * focus.
+ * @param [setFocus=false]
+ */
+ reactivate: function (setFocus) {
+ var res,
+ node = this.activeNode;
+
+ if (!node) {
+ return _getResolvedPromise();
+ }
+ this.activeNode = null; // Force re-activating
+ res = node.setActive(true, { noFocus: true });
+ if (setFocus) {
+ node.setFocus();
+ }
+ return res;
+ },
+ /** Reload tree from source and return a promise.
+ * @param [source] optional new source (defaults to initial source data)
+ * @returns {$.Promise}
+ */
+ reload: function (source) {
+ this._callHook("treeClear", this);
+ return this._callHook("treeLoad", this, source);
+ },
+ /**Render tree (i.e. create DOM elements for all top-level nodes).
+ * @param {boolean} [force=false] create DOM elemnts, even if parent is collapsed
+ * @param {boolean} [deep=false]
+ */
+ render: function (force, deep) {
+ return this.rootNode.render(force, deep);
+ },
+ /**(De)select all nodes.
+ * @param {boolean} [flag=true]
+ * @since 2.28
+ */
+ selectAll: function (flag) {
+ this.visit(function (node) {
+ node.setSelected(flag);
+ });
+ },
+ // TODO: selectKey: function(key, select)
+ // TODO: serializeArray: function(stopOnParents)
+ /**
+ * @param {boolean} [flag=true]
+ */
+ setFocus: function (flag) {
+ return this._callHook("treeSetFocus", this, flag);
+ },
+ /**
+ * Set current option value.
+ * (Note: this is the preferred variant of `$().fancytree("option", "KEY", VALUE)`)
+ * @param {string} name option name (may contain '.')
+ * @param {any} new value
+ */
+ setOption: function (optionName, value) {
+ return this.widget.option(optionName, value);
+ },
+ /**
+ * Call console.time() when in debug mode (verbose >= 4).
+ *
+ * @param {string} label
+ */
+ debugTime: function (label) {
+ if (this.options.debugLevel >= 4) {
+ window.console.time(this + " - " + label);
+ }
+ },
+ /**
+ * Call console.timeEnd() when in debug mode (verbose >= 4).
+ *
+ * @param {string} label
+ */
+ debugTimeEnd: function (label) {
+ if (this.options.debugLevel >= 4) {
+ window.console.timeEnd(this + " - " + label);
+ }
+ },
+ /**
+ * Return all nodes as nested list of {@link NodeData}.
+ *
+ * @param {boolean} [includeRoot=false] Returns the hidden system root node (and its children)
+ * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications.
+ * Return `false` to ignore this node or "skip" to include this node without its children.
+ * @returns {Array | object}
+ * @see FancytreeNode#toDict
+ */
+ toDict: function (includeRoot, callback) {
+ var res = this.rootNode.toDict(true, callback);
+ return includeRoot ? res : res.children;
+ },
+ /* Implicitly called for string conversions.
+ * @returns {string}
+ */
+ toString: function () {
+ return "Fancytree@" + this._id;
+ // return "<Fancytree(#" + this._id + ")>";
+ },
+ /* _trigger a widget event with additional node ctx.
+ * @see EventData
+ */
+ _triggerNodeEvent: function (type, node, originalEvent, extra) {
+ // this.debug("_trigger(" + type + "): '" + ctx.node.title + "'", ctx);
+ var ctx = this._makeHookContext(node, originalEvent, extra),
+ res = this.widget._trigger(type, originalEvent, ctx);
+ if (res !== false && ctx.result !== undefined) {
+ return ctx.result;
+ }
+ return res;
+ },
+ /* _trigger a widget event with additional tree data. */
+ _triggerTreeEvent: function (type, originalEvent, extra) {
+ // this.debug("_trigger(" + type + ")", ctx);
+ var ctx = this._makeHookContext(this, originalEvent, extra),
+ res = this.widget._trigger(type, originalEvent, ctx);
+
+ if (res !== false && ctx.result !== undefined) {
+ return ctx.result;
+ }
+ return res;
+ },
+ /** Call fn(node) for all nodes in hierarchical order (depth-first).
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and children only.
+ * @returns {boolean} false, if the iterator was stopped.
+ */
+ visit: function (fn) {
+ return this.rootNode.visit(fn, false);
+ },
+ /** Call fn(node) for all nodes in vertical order, top down (or bottom up).<br>
+ * Stop iteration, if fn() returns false.<br>
+ * Return false if iteration was stopped.
+ *
+ * @param {function} fn the callback function.
+ * Return false to stop iteration, return "skip" to skip this node and children only.
+ * @param {object} [options]
+ * Defaults:
+ * {start: First top node, reverse: false, includeSelf: true, includeHidden: false}
+ * @returns {boolean} false if iteration was cancelled
+ * @since 2.28
+ */
+ visitRows: function (fn, opts) {
+ if (!this.rootNode.hasChildren()) {
+ return false;
+ }
+ if (opts && opts.reverse) {
+ delete opts.reverse;
+ return this._visitRowsUp(fn, opts);
+ }
+ opts = opts || {};
+
+ var i,
+ nextIdx,
+ parent,
+ res,
+ siblings,
+ siblingOfs = 0,
+ skipFirstNode = opts.includeSelf === false,
+ includeHidden = !!opts.includeHidden,
+ checkFilter = !includeHidden && this.enableFilter,
+ node = opts.start || this.rootNode.children[0];
+
+ parent = node.parent;
+ while (parent) {
+ // visit siblings
+ siblings = parent.children;
+ nextIdx = siblings.indexOf(node) + siblingOfs;
+ _assert(
+ nextIdx >= 0,
+ "Could not find " +
+ node +
+ " in parent's children: " +
+ parent
+ );
+
+ for (i = nextIdx; i < siblings.length; i++) {
+ node = siblings[i];
+ if (checkFilter && !node.match && !node.subMatchCount) {
+ continue;
+ }
+ if (!skipFirstNode && fn(node) === false) {
+ return false;
+ }
+ skipFirstNode = false;
+ // Dive into node's child nodes
+ if (
+ node.children &&
+ node.children.length &&
+ (includeHidden || node.expanded)
+ ) {
+ // Disable warning: Functions declared within loops referencing an outer
+ // scoped variable may lead to confusing semantics:
+ /*jshint -W083 */
+ res = node.visit(function (n) {
+ if (checkFilter && !n.match && !n.subMatchCount) {
+ return "skip";
+ }
+ if (fn(n) === false) {
+ return false;
+ }
+ if (!includeHidden && n.children && !n.expanded) {
+ return "skip";
+ }
+ }, false);
+ /*jshint +W083 */
+ if (res === false) {
+ return false;
+ }
+ }
+ }
+ // Visit parent nodes (bottom up)
+ node = parent;
+ parent = parent.parent;
+ siblingOfs = 1; //
+ }
+ return true;
+ },
+ /* Call fn(node) for all nodes in vertical order, bottom up.
+ */
+ _visitRowsUp: function (fn, opts) {
+ var children,
+ idx,
+ parent,
+ includeHidden = !!opts.includeHidden,
+ node = opts.start || this.rootNode.children[0];
+
+ while (true) {
+ parent = node.parent;
+ children = parent.children;
+
+ if (children[0] === node) {
+ // If this is already the first sibling, goto parent
+ node = parent;
+ if (!node.parent) {
+ break; // first node of the tree
+ }
+ children = parent.children;
+ } else {
+ // Otherwise, goto prev. sibling
+ idx = children.indexOf(node);
+ node = children[idx - 1];
+ // If the prev. sibling has children, follow down to last descendant
+ while (
+ // See: https://github.com/eslint/eslint/issues/11302
+ // eslint-disable-next-line no-unmodified-loop-condition
+ (includeHidden || node.expanded) &&
+ node.children &&
+ node.children.length
+ ) {
+ children = node.children;
+ parent = node;
+ node = children[children.length - 1];
+ }
+ }
+ // Skip invisible
+ if (!includeHidden && !node.isVisible()) {
+ continue;
+ }
+ if (fn(node) === false) {
+ return false;
+ }
+ }
+ },
+ /** Write warning to browser console if debugLevel >= 2 (prepending tree info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ warn: function (msg) {
+ if (this.options.debugLevel >= 2) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("warn", arguments);
+ }
+ },
+ };
+
+ /**
+ * These additional methods of the {@link Fancytree} class are 'hook functions'
+ * that can be used and overloaded by extensions.
+ *
+ * @see [writing extensions](https://github.com/mar10/fancytree/wiki/TutorialExtensions)
+ * @mixin Fancytree_Hooks
+ */
+ $.extend(
+ Fancytree.prototype,
+ /** @lends Fancytree_Hooks# */
+ {
+ /** Default handling for mouse click events.
+ *
+ * @param {EventData} ctx
+ */
+ nodeClick: function (ctx) {
+ var activate,
+ expand,
+ // event = ctx.originalEvent,
+ targetType = ctx.targetType,
+ node = ctx.node;
+
+ // this.debug("ftnode.onClick(" + event.type + "): ftnode:" + this + ", button:" + event.button + ", which: " + event.which, ctx);
+ // TODO: use switch
+ // TODO: make sure clicks on embedded <input> doesn't steal focus (see table sample)
+ if (targetType === "expander") {
+ if (node.isLoading()) {
+ // #495: we probably got a click event while a lazy load is pending.
+ // The 'expanded' state is not yet set, so 'toggle' would expand
+ // and trigger lazyLoad again.
+ // It would be better to allow to collapse/expand the status node
+ // while loading (instead of ignoring), but that would require some
+ // more work.
+ node.debug("Got 2nd click while loading: ignored");
+ return;
+ }
+ // Clicking the expander icon always expands/collapses
+ this._callHook("nodeToggleExpanded", ctx);
+ } else if (targetType === "checkbox") {
+ // Clicking the checkbox always (de)selects
+ this._callHook("nodeToggleSelected", ctx);
+ if (ctx.options.focusOnSelect) {
+ // #358
+ this._callHook("nodeSetFocus", ctx, true);
+ }
+ } else {
+ // Honor `clickFolderMode` for
+ expand = false;
+ activate = true;
+ if (node.folder) {
+ switch (ctx.options.clickFolderMode) {
+ case 2: // expand only
+ expand = true;
+ activate = false;
+ break;
+ case 3: // expand and activate
+ activate = true;
+ expand = true; //!node.isExpanded();
+ break;
+ // else 1 or 4: just activate
+ }
+ }
+ if (activate) {
+ this.nodeSetFocus(ctx);
+ this._callHook("nodeSetActive", ctx, true);
+ }
+ if (expand) {
+ if (!activate) {
+ // this._callHook("nodeSetFocus", ctx);
+ }
+ // this._callHook("nodeSetExpanded", ctx, true);
+ this._callHook("nodeToggleExpanded", ctx);
+ }
+ }
+ // Make sure that clicks stop, otherwise <a href='#'> jumps to the top
+ // if(event.target.localName === "a" && event.target.className === "fancytree-title"){
+ // event.preventDefault();
+ // }
+ // TODO: return promise?
+ },
+ /** Collapse all other children of same parent.
+ *
+ * @param {EventData} ctx
+ * @param {object} callOpts
+ */
+ nodeCollapseSiblings: function (ctx, callOpts) {
+ // TODO: return promise?
+ var ac,
+ i,
+ l,
+ node = ctx.node;
+
+ if (node.parent) {
+ ac = node.parent.children;
+ for (i = 0, l = ac.length; i < l; i++) {
+ if (ac[i] !== node && ac[i].expanded) {
+ this._callHook(
+ "nodeSetExpanded",
+ ac[i],
+ false,
+ callOpts
+ );
+ }
+ }
+ }
+ },
+ /** Default handling for mouse douleclick events.
+ * @param {EventData} ctx
+ */
+ nodeDblclick: function (ctx) {
+ // TODO: return promise?
+ if (
+ ctx.targetType === "title" &&
+ ctx.options.clickFolderMode === 4
+ ) {
+ // this.nodeSetFocus(ctx);
+ // this._callHook("nodeSetActive", ctx, true);
+ this._callHook("nodeToggleExpanded", ctx);
+ }
+ // TODO: prevent text selection on dblclicks
+ if (ctx.targetType === "title") {
+ ctx.originalEvent.preventDefault();
+ }
+ },
+ /** Default handling for mouse keydown events.
+ *
+ * NOTE: this may be called with node == null if tree (but no node) has focus.
+ * @param {EventData} ctx
+ */
+ nodeKeydown: function (ctx) {
+ // TODO: return promise?
+ var matchNode,
+ stamp,
+ _res,
+ focusNode,
+ event = ctx.originalEvent,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ which = event.which,
+ // #909: Use event.key, to get unicode characters.
+ // We can't use `/\w/.test(key)`, because that would
+ // only detect plain ascii alpha-numerics. But we still need
+ // to ignore modifier-only, whitespace, cursor-keys, etc.
+ key = event.key || String.fromCharCode(which),
+ specialModifiers = !!(
+ event.altKey ||
+ event.ctrlKey ||
+ event.metaKey
+ ),
+ isAlnum =
+ !MODIFIERS[which] &&
+ !SPECIAL_KEYCODES[which] &&
+ !specialModifiers,
+ $target = $(event.target),
+ handled = true,
+ activate = !(event.ctrlKey || !opts.autoActivate);
+
+ // (node || FT).debug("ftnode.nodeKeydown(" + event.type + "): ftnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which);
+ // FT.debug( "eventToString(): " + FT.eventToString(event) + ", key='" + key + "', isAlnum: " + isAlnum );
+
+ // Set focus to active (or first node) if no other node has the focus yet
+ if (!node) {
+ focusNode = this.getActiveNode() || this.getFirstChild();
+ if (focusNode) {
+ focusNode.setFocus();
+ node = ctx.node = this.focusNode;
+ node.debug("Keydown force focus on active node");
+ }
+ }
+
+ if (
+ opts.quicksearch &&
+ isAlnum &&
+ !$target.is(":input:enabled")
+ ) {
+ // Allow to search for longer streaks if typed in quickly
+ stamp = Date.now();
+ if (stamp - tree.lastQuicksearchTime > 500) {
+ tree.lastQuicksearchTerm = "";
+ }
+ tree.lastQuicksearchTime = stamp;
+ tree.lastQuicksearchTerm += key;
+ // tree.debug("quicksearch find", tree.lastQuicksearchTerm);
+ matchNode = tree.findNextNode(
+ tree.lastQuicksearchTerm,
+ tree.getActiveNode()
+ );
+ if (matchNode) {
+ matchNode.setActive();
+ }
+ event.preventDefault();
+ return;
+ }
+ switch (FT.eventToString(event)) {
+ case "+":
+ case "=": // 187: '+' @ Chrome, Safari
+ tree.nodeSetExpanded(ctx, true);
+ break;
+ case "-":
+ tree.nodeSetExpanded(ctx, false);
+ break;
+ case "space":
+ if (node.isPagingNode()) {
+ tree._triggerNodeEvent("clickPaging", ctx, event);
+ } else if (
+ FT.evalOption("checkbox", node, node, opts, false)
+ ) {
+ // #768
+ tree.nodeToggleSelected(ctx);
+ } else {
+ tree.nodeSetActive(ctx, true);
+ }
+ break;
+ case "return":
+ tree.nodeSetActive(ctx, true);
+ break;
+ case "home":
+ case "end":
+ case "backspace":
+ case "left":
+ case "right":
+ case "up":
+ case "down":
+ _res = node.navigate(event.which, activate);
+ break;
+ default:
+ handled = false;
+ }
+ if (handled) {
+ event.preventDefault();
+ }
+ },
+
+ // /** Default handling for mouse keypress events. */
+ // nodeKeypress: function(ctx) {
+ // var event = ctx.originalEvent;
+ // },
+
+ // /** Trigger lazyLoad event (async). */
+ // nodeLazyLoad: function(ctx) {
+ // var node = ctx.node;
+ // if(this._triggerNodeEvent())
+ // },
+ /** Load child nodes (async).
+ *
+ * @param {EventData} ctx
+ * @param {object[]|object|string|$.Promise|function} source
+ * @returns {$.Promise} The deferred will be resolved as soon as the (ajax)
+ * data was rendered.
+ */
+ nodeLoadChildren: function (ctx, source) {
+ var ajax,
+ delay,
+ ajaxDfd = null,
+ resultDfd,
+ isAsync = true,
+ tree = ctx.tree,
+ node = ctx.node,
+ nodePrevParent = node.parent,
+ tag = "nodeLoadChildren",
+ requestId = Date.now();
+
+ // `source` is a callback: use the returned result instead:
+ if (_isFunction(source)) {
+ source = source.call(tree, { type: "source" }, ctx);
+ _assert(
+ !_isFunction(source),
+ "source callback must not return another function"
+ );
+ }
+ // `source` is already a promise:
+ if (_isFunction(source.then)) {
+ // _assert(_isFunction(source.always), "Expected jQuery?");
+ ajaxDfd = source;
+ } else if (source.url) {
+ // `source` is an Ajax options object
+ ajax = $.extend({}, ctx.options.ajax, source);
+ if (ajax.debugDelay) {
+ // Simulate a slow server
+ delay = ajax.debugDelay;
+ delete ajax.debugDelay; // remove debug option
+ if (_isArray(delay)) {
+ // random delay range [min..max]
+ delay =
+ delay[0] +
+ Math.random() * (delay[1] - delay[0]);
+ }
+ node.warn(
+ "nodeLoadChildren waiting debugDelay " +
+ Math.round(delay) +
+ " ms ..."
+ );
+ ajaxDfd = $.Deferred(function (ajaxDfd) {
+ setTimeout(function () {
+ $.ajax(ajax)
+ .done(function () {
+ ajaxDfd.resolveWith(this, arguments);
+ })
+ .fail(function () {
+ ajaxDfd.rejectWith(this, arguments);
+ });
+ }, delay);
+ });
+ } else {
+ ajaxDfd = $.ajax(ajax);
+ }
+ } else if ($.isPlainObject(source) || _isArray(source)) {
+ // `source` is already a constant dict or list, but we convert
+ // to a thenable for unified processing.
+ // 2020-01-03: refactored.
+ // `ajaxDfd = $.when(source)` would do the trick, but the returned
+ // promise will resolve async, which broke some tests and
+ // would probably also break current implementations out there.
+ // So we mock-up a thenable that resolves synchronously:
+ ajaxDfd = {
+ then: function (resolve, reject) {
+ resolve(source, null, null);
+ },
+ };
+ isAsync = false;
+ } else {
+ $.error("Invalid source type: " + source);
+ }
+
+ // Check for overlapping requests
+ if (node._requestId) {
+ node.warn(
+ "Recursive load request #" +
+ requestId +
+ " while #" +
+ node._requestId +
+ " is pending."
+ );
+ node._requestId = requestId;
+ // node.debug("Send load request #" + requestId);
+ }
+
+ if (isAsync) {
+ tree.debugTime(tag);
+ tree.nodeSetStatus(ctx, "loading");
+ }
+
+ // The async Ajax request has now started...
+ // Defer the deferred:
+ // we want to be able to reject invalid responses, even if
+ // the raw HTTP Ajax XHR resolved as Ok.
+ // We use the ajaxDfd.then() syntax here, which is compatible with
+ // jQuery and ECMA6.
+ // However resultDfd is a jQuery deferred, which is currently the
+ // expected result type of nodeLoadChildren()
+ resultDfd = new $.Deferred();
+ ajaxDfd.then(
+ function (data, textStatus, jqXHR) {
+ // ajaxDfd was resolved, but we reject or resolve resultDfd
+ // depending on the response data
+ var errorObj, res;
+
+ if (
+ (source.dataType === "json" ||
+ source.dataType === "jsonp") &&
+ typeof data === "string"
+ ) {
+ $.error(
+ "Ajax request returned a string (did you get the JSON dataType wrong?)."
+ );
+ }
+ if (node._requestId && node._requestId > requestId) {
+ // The expected request time stamp is later than `requestId`
+ // (which was kept as as closure variable to this handler function)
+ // node.warn("Ignored load response for obsolete request #" + requestId + " (expected #" + node._requestId + ")");
+ resultDfd.rejectWith(this, [
+ RECURSIVE_REQUEST_ERROR,
+ ]);
+ return;
+ // } else {
+ // node.debug("Response returned for load request #" + requestId);
+ }
+ if (node.parent === null && nodePrevParent !== null) {
+ resultDfd.rejectWith(this, [
+ INVALID_REQUEST_TARGET_ERROR,
+ ]);
+ return;
+ }
+ // Allow to adjust the received response data in the `postProcess` event.
+ if (ctx.options.postProcess) {
+ // The handler may either
+ // - modify `ctx.response` in-place (and leave `ctx.result` undefined)
+ // => res = undefined
+ // - return a replacement in `ctx.result`
+ // => res = <new data>
+ // If res contains an `error` property, an error status is displayed
+ try {
+ res = tree._triggerNodeEvent(
+ "postProcess",
+ ctx,
+ ctx.originalEvent,
+ {
+ response: data,
+ error: null,
+ dataType: source.dataType,
+ }
+ );
+ if (res.error) {
+ tree.warn(
+ "postProcess returned error:",
+ res
+ );
+ }
+ } catch (e) {
+ res = {
+ error: e,
+ message: "" + e,
+ details: "postProcess failed",
+ };
+ }
+ if (res.error) {
+ // Either postProcess failed with an exception, or the returned
+ // result object has an 'error' property attached:
+ errorObj = $.isPlainObject(res.error)
+ ? res.error
+ : { message: res.error };
+ errorObj = tree._makeHookContext(
+ node,
+ null,
+ errorObj
+ );
+ resultDfd.rejectWith(this, [errorObj]);
+ return;
+ }
+ if (
+ _isArray(res) ||
+ ($.isPlainObject(res) && _isArray(res.children))
+ ) {
+ // Use `ctx.result` if valid
+ // (otherwise use existing data, which may have been modified in-place)
+ data = res;
+ }
+ } else if (
+ data &&
+ _hasProp(data, "d") &&
+ ctx.options.enableAspx
+ ) {
+ // Process ASPX WebMethod JSON object inside "d" property
+ // (only if no postProcess event was defined)
+ if (ctx.options.enableAspx === 42) {
+ tree.warn(
+ "The default for enableAspx will change to `false` in the fututure. " +
+ "Pass `enableAspx: true` or implement postProcess to silence this warning."
+ );
+ }
+ data =
+ typeof data.d === "string"
+ ? $.parseJSON(data.d)
+ : data.d;
+ }
+ resultDfd.resolveWith(this, [data]);
+ },
+ function (jqXHR, textStatus, errorThrown) {
+ // ajaxDfd was rejected, so we reject resultDfd as well
+ var errorObj = tree._makeHookContext(node, null, {
+ error: jqXHR,
+ args: Array.prototype.slice.call(arguments),
+ message: errorThrown,
+ details: jqXHR.status + ": " + errorThrown,
+ });
+ resultDfd.rejectWith(this, [errorObj]);
+ }
+ );
+
+ // The async Ajax request has now started.
+ // resultDfd will be resolved/rejected after the response arrived,
+ // was postProcessed, and checked.
+ // Now we implement the UI update and add the data to the tree.
+ // We also return this promise to the caller.
+ resultDfd
+ .done(function (data) {
+ tree.nodeSetStatus(ctx, "ok");
+ var children, metaData, noDataRes;
+
+ if ($.isPlainObject(data)) {
+ // We got {foo: 'abc', children: [...]}
+ // Copy extra properties to tree.data.foo
+ _assert(
+ node.isRootNode(),
+ "source may only be an object for root nodes (expecting an array of child objects otherwise)"
+ );
+ _assert(
+ _isArray(data.children),
+ "if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"
+ );
+ metaData = data;
+ children = data.children;
+ delete metaData.children;
+ // Copy some attributes to tree.data
+ $.each(TREE_ATTRS, function (i, attr) {
+ if (metaData[attr] !== undefined) {
+ tree[attr] = metaData[attr];
+ delete metaData[attr];
+ }
+ });
+ // Copy all other attributes to tree.data.NAME
+ $.extend(tree.data, metaData);
+ } else {
+ children = data;
+ }
+ _assert(
+ _isArray(children),
+ "expected array of children"
+ );
+ node._setChildren(children);
+
+ if (tree.options.nodata && children.length === 0) {
+ if (_isFunction(tree.options.nodata)) {
+ noDataRes = tree.options.nodata.call(
+ tree,
+ { type: "nodata" },
+ ctx
+ );
+ } else if (
+ tree.options.nodata === true &&
+ node.isRootNode()
+ ) {
+ noDataRes = tree.options.strings.noData;
+ } else if (
+ typeof tree.options.nodata === "string" &&
+ node.isRootNode()
+ ) {
+ noDataRes = tree.options.nodata;
+ }
+ if (noDataRes) {
+ node.setStatus("nodata", noDataRes);
+ }
+ }
+ // trigger fancytreeloadchildren
+ tree._triggerNodeEvent("loadChildren", node);
+ })
+ .fail(function (error) {
+ var ctxErr;
+
+ if (error === RECURSIVE_REQUEST_ERROR) {
+ node.warn(
+ "Ignored response for obsolete load request #" +
+ requestId +
+ " (expected #" +
+ node._requestId +
+ ")"
+ );
+ return;
+ } else if (error === INVALID_REQUEST_TARGET_ERROR) {
+ node.warn(
+ "Lazy parent node was removed while loading: discarding response."
+ );
+ return;
+ } else if (error.node && error.error && error.message) {
+ // error is already a context object
+ ctxErr = error;
+ } else {
+ ctxErr = tree._makeHookContext(node, null, {
+ error: error, // it can be jqXHR or any custom error
+ args: Array.prototype.slice.call(arguments),
+ message: error
+ ? error.message || error.toString()
+ : "",
+ });
+ if (ctxErr.message === "[object Object]") {
+ ctxErr.message = "";
+ }
+ }
+ node.warn(
+ "Load children failed (" + ctxErr.message + ")",
+ ctxErr
+ );
+ if (
+ tree._triggerNodeEvent(
+ "loadError",
+ ctxErr,
+ null
+ ) !== false
+ ) {
+ tree.nodeSetStatus(
+ ctx,
+ "error",
+ ctxErr.message,
+ ctxErr.details
+ );
+ }
+ })
+ .always(function () {
+ node._requestId = null;
+ if (isAsync) {
+ tree.debugTimeEnd(tag);
+ }
+ });
+
+ return resultDfd.promise();
+ },
+ /** [Not Implemented] */
+ nodeLoadKeyPath: function (ctx, keyPathList) {
+ // TODO: implement and improve
+ // http://code.google.com/p/dynatree/issues/detail?id=222
+ },
+ /**
+ * Remove a single direct child of ctx.node.
+ * @param {EventData} ctx
+ * @param {FancytreeNode} childNode dircect child of ctx.node
+ */
+ nodeRemoveChild: function (ctx, childNode) {
+ var idx,
+ node = ctx.node,
+ // opts = ctx.options,
+ subCtx = $.extend({}, ctx, { node: childNode }),
+ children = node.children;
+
+ // FT.debug("nodeRemoveChild()", node.toString(), childNode.toString());
+
+ if (children.length === 1) {
+ _assert(childNode === children[0], "invalid single child");
+ return this.nodeRemoveChildren(ctx);
+ }
+ if (
+ this.activeNode &&
+ (childNode === this.activeNode ||
+ this.activeNode.isDescendantOf(childNode))
+ ) {
+ this.activeNode.setActive(false); // TODO: don't fire events
+ }
+ if (
+ this.focusNode &&
+ (childNode === this.focusNode ||
+ this.focusNode.isDescendantOf(childNode))
+ ) {
+ this.focusNode = null;
+ }
+ // TODO: persist must take care to clear select and expand cookies
+ this.nodeRemoveMarkup(subCtx);
+ this.nodeRemoveChildren(subCtx);
+ idx = $.inArray(childNode, children);
+ _assert(idx >= 0, "invalid child");
+ // Notify listeners
+ node.triggerModifyChild("remove", childNode);
+ // Unlink to support GC
+ childNode.visit(function (n) {
+ n.parent = null;
+ }, true);
+ this._callHook("treeRegisterNode", this, false, childNode);
+ // remove from child list
+ children.splice(idx, 1);
+ },
+ /**Remove HTML markup for all descendents of ctx.node.
+ * @param {EventData} ctx
+ */
+ nodeRemoveChildMarkup: function (ctx) {
+ var node = ctx.node;
+
+ // FT.debug("nodeRemoveChildMarkup()", node.toString());
+ // TODO: Unlink attr.ftnode to support GC
+ if (node.ul) {
+ if (node.isRootNode()) {
+ $(node.ul).empty();
+ } else {
+ $(node.ul).remove();
+ node.ul = null;
+ }
+ node.visit(function (n) {
+ n.li = n.ul = null;
+ });
+ }
+ },
+ /**Remove all descendants of ctx.node.
+ * @param {EventData} ctx
+ */
+ nodeRemoveChildren: function (ctx) {
+ var //subCtx,
+ tree = ctx.tree,
+ node = ctx.node,
+ children = node.children;
+ // opts = ctx.options;
+
+ // FT.debug("nodeRemoveChildren()", node.toString());
+ if (!children) {
+ return;
+ }
+ if (this.activeNode && this.activeNode.isDescendantOf(node)) {
+ this.activeNode.setActive(false); // TODO: don't fire events
+ }
+ if (this.focusNode && this.focusNode.isDescendantOf(node)) {
+ this.focusNode = null;
+ }
+ // TODO: persist must take care to clear select and expand cookies
+ this.nodeRemoveChildMarkup(ctx);
+ // Unlink children to support GC
+ // TODO: also delete this.children (not possible using visit())
+ // subCtx = $.extend({}, ctx);
+ node.triggerModifyChild("remove", null);
+ node.visit(function (n) {
+ n.parent = null;
+ tree._callHook("treeRegisterNode", tree, false, n);
+ });
+ if (node.lazy) {
+ // 'undefined' would be interpreted as 'not yet loaded' for lazy nodes
+ node.children = [];
+ } else {
+ node.children = null;
+ }
+ if (!node.isRootNode()) {
+ node.expanded = false; // #449, #459
+ }
+ this.nodeRenderStatus(ctx);
+ },
+ /**Remove HTML markup for ctx.node and all its descendents.
+ * @param {EventData} ctx
+ */
+ nodeRemoveMarkup: function (ctx) {
+ var node = ctx.node;
+ // FT.debug("nodeRemoveMarkup()", node.toString());
+ // TODO: Unlink attr.ftnode to support GC
+ if (node.li) {
+ $(node.li).remove();
+ node.li = null;
+ }
+ this.nodeRemoveChildMarkup(ctx);
+ },
+ /**
+ * Create `<li><span>..</span> .. </li>` tags for this node.
+ *
+ * This method takes care that all HTML markup is created that is required
+ * to display this node in its current state.
+ *
+ * Call this method to create new nodes, or after the strucuture
+ * was changed (e.g. after moving this node or adding/removing children)
+ * nodeRenderTitle() and nodeRenderStatus() are implied.
+ *
+ * ```html
+ * <li id='KEY' ftnode=NODE>
+ * <span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'>
+ * <span class="fancytree-expander"></span>
+ * <span class="fancytree-checkbox"></span> // only present in checkbox mode
+ * <span class="fancytree-icon"></span>
+ * <a href="#" class="fancytree-title"> Node 1 </a>
+ * </span>
+ * <ul> // only present if node has children
+ * <li id='KEY' ftnode=NODE> child1 ... </li>
+ * <li id='KEY' ftnode=NODE> child2 ... </li>
+ * </ul>
+ * </li>
+ * ```
+ *
+ * @param {EventData} ctx
+ * @param {boolean} [force=false] re-render, even if html markup was already created
+ * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed
+ * @param {boolean} [collapsed=false] force root node to be collapsed, so we can apply animated expand later
+ */
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ /* This method must take care of all cases where the current data mode
+ * (i.e. node hierarchy) does not match the current markup.
+ *
+ * - node was not yet rendered:
+ * create markup
+ * - node was rendered: exit fast
+ * - children have been added
+ * - children have been removed
+ */
+ var childLI,
+ childNode1,
+ childNode2,
+ i,
+ l,
+ next,
+ subCtx,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ aria = opts.aria,
+ firstTime = false,
+ parent = node.parent,
+ isRootNode = !parent,
+ children = node.children,
+ successorLi = null;
+ // FT.debug("nodeRender(" + !!force + ", " + !!deep + ")", node.toString());
+
+ if (tree._enableUpdate === false) {
+ // tree.debug("no render", tree._enableUpdate);
+ return;
+ }
+ if (!isRootNode && !parent.ul) {
+ // Calling node.collapse on a deep, unrendered node
+ return;
+ }
+ _assert(isRootNode || parent.ul, "parent UL must exist");
+
+ // Render the node
+ if (!isRootNode) {
+ // Discard markup on force-mode, or if it is not linked to parent <ul>
+ if (
+ node.li &&
+ (force || node.li.parentNode !== node.parent.ul)
+ ) {
+ if (node.li.parentNode === node.parent.ul) {
+ // #486: store following node, so we can insert the new markup there later
+ successorLi = node.li.nextSibling;
+ } else {
+ // May happen, when a top-level node was dropped over another
+ this.debug(
+ "Unlinking " +
+ node +
+ " (must be child of " +
+ node.parent +
+ ")"
+ );
+ }
+ // this.debug("nodeRemoveMarkup...");
+ this.nodeRemoveMarkup(ctx);
+ }
+ // Create <li><span /> </li>
+ // node.debug("render...");
+ if (node.li) {
+ // this.nodeRenderTitle(ctx);
+ this.nodeRenderStatus(ctx);
+ } else {
+ // node.debug("render... really");
+ firstTime = true;
+ node.li = document.createElement("li");
+ node.li.ftnode = node;
+
+ if (node.key && opts.generateIds) {
+ node.li.id = opts.idPrefix + node.key;
+ }
+ node.span = document.createElement("span");
+ node.span.className = "fancytree-node";
+ if (aria && !node.tr) {
+ $(node.li).attr("role", "treeitem");
+ }
+ node.li.appendChild(node.span);
+
+ // Create inner HTML for the <span> (expander, checkbox, icon, and title)
+ this.nodeRenderTitle(ctx);
+
+ // Allow tweaking and binding, after node was created for the first time
+ if (opts.createNode) {
+ opts.createNode.call(
+ tree,
+ { type: "createNode" },
+ ctx
+ );
+ }
+ }
+ // Allow tweaking after node state was rendered
+ if (opts.renderNode) {
+ opts.renderNode.call(tree, { type: "renderNode" }, ctx);
+ }
+ }
+
+ // Visit child nodes
+ if (children) {
+ if (isRootNode || node.expanded || deep === true) {
+ // Create a UL to hold the children
+ if (!node.ul) {
+ node.ul = document.createElement("ul");
+ if (
+ (collapsed === true && !_recursive) ||
+ !node.expanded
+ ) {
+ // hide top UL, so we can use an animation to show it later
+ node.ul.style.display = "none";
+ }
+ if (aria) {
+ $(node.ul).attr("role", "group");
+ }
+ if (node.li) {
+ // issue #67
+ node.li.appendChild(node.ul);
+ } else {
+ node.tree.$div.append(node.ul);
+ }
+ }
+ // Add child markup
+ for (i = 0, l = children.length; i < l; i++) {
+ subCtx = $.extend({}, ctx, { node: children[i] });
+ this.nodeRender(subCtx, force, deep, false, true);
+ }
+ // Remove <li> if nodes have moved to another parent
+ childLI = node.ul.firstChild;
+ while (childLI) {
+ childNode2 = childLI.ftnode;
+ if (childNode2 && childNode2.parent !== node) {
+ node.debug(
+ "_fixParent: remove missing " + childNode2,
+ childLI
+ );
+ next = childLI.nextSibling;
+ childLI.parentNode.removeChild(childLI);
+ childLI = next;
+ } else {
+ childLI = childLI.nextSibling;
+ }
+ }
+ // Make sure, that <li> order matches node.children order.
+ childLI = node.ul.firstChild;
+ for (i = 0, l = children.length - 1; i < l; i++) {
+ childNode1 = children[i];
+ childNode2 = childLI.ftnode;
+ if (childNode1 === childNode2) {
+ childLI = childLI.nextSibling;
+ } else {
+ // node.debug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2);
+ node.ul.insertBefore(
+ childNode1.li,
+ childNode2.li
+ );
+ }
+ }
+ }
+ } else {
+ // No children: remove markup if any
+ if (node.ul) {
+ // alert("remove child markup for " + node);
+ this.warn("remove child markup for " + node);
+ this.nodeRemoveChildMarkup(ctx);
+ }
+ }
+ if (!isRootNode) {
+ // Update element classes according to node state
+ // this.nodeRenderStatus(ctx);
+ // Finally add the whole structure to the DOM, so the browser can render
+ if (firstTime) {
+ // #486: successorLi is set, if we re-rendered (i.e. discarded)
+ // existing markup, which we want to insert at the same position.
+ // (null is equivalent to append)
+ // parent.ul.appendChild(node.li);
+ parent.ul.insertBefore(node.li, successorLi);
+ }
+ }
+ },
+ /** Create HTML inside the node's outer `<span>` (i.e. expander, checkbox,
+ * icon, and title).
+ *
+ * nodeRenderStatus() is implied.
+ * @param {EventData} ctx
+ * @param {string} [title] optinal new title
+ */
+ nodeRenderTitle: function (ctx, title) {
+ // set node connector images, links and text
+ var checkbox,
+ className,
+ icon,
+ nodeTitle,
+ role,
+ tabindex,
+ tooltip,
+ iconTooltip,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ aria = opts.aria,
+ level = node.getLevel(),
+ ares = [];
+
+ if (title !== undefined) {
+ node.title = title;
+ }
+ if (!node.span || tree._enableUpdate === false) {
+ // Silently bail out if node was not rendered yet, assuming
+ // node.render() will be called as the node becomes visible
+ return;
+ }
+ // Connector (expanded, expandable or simple)
+ role =
+ aria && node.hasChildren() !== false
+ ? " role='button'"
+ : "";
+ if (level < opts.minExpandLevel) {
+ if (!node.lazy) {
+ node.expanded = true;
+ }
+ if (level > 1) {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-expander fancytree-expander-fixed'></span>"
+ );
+ }
+ // .. else (i.e. for root level) skip expander/connector alltogether
+ } else {
+ ares.push(
+ "<span " + role + " class='fancytree-expander'></span>"
+ );
+ }
+ // Checkbox mode
+ checkbox = FT.evalOption("checkbox", node, node, opts, false);
+
+ if (checkbox && !node.isStatusNode()) {
+ role = aria ? " role='checkbox'" : "";
+ className = "fancytree-checkbox";
+ if (
+ checkbox === "radio" ||
+ (node.parent && node.parent.radiogroup)
+ ) {
+ className += " fancytree-radio";
+ }
+ ares.push(
+ "<span " + role + " class='" + className + "'></span>"
+ );
+ }
+ // Folder or doctype icon
+ if (node.data.iconClass !== undefined) {
+ // 2015-11-16
+ // Handle / warn about backward compatibility
+ if (node.icon) {
+ $.error(
+ "'iconClass' node option is deprecated since v2.14.0: use 'icon' only instead"
+ );
+ } else {
+ node.warn(
+ "'iconClass' node option is deprecated since v2.14.0: use 'icon' instead"
+ );
+ node.icon = node.data.iconClass;
+ }
+ }
+ // If opts.icon is a callback and returns something other than undefined, use that
+ // else if node.icon is a boolean or string, use that
+ // else if opts.icon is a boolean or string, use that
+ // else show standard icon (which may be different for folders or documents)
+ icon = FT.evalOption("icon", node, node, opts, true);
+ // if( typeof icon !== "boolean" ) {
+ // // icon is defined, but not true/false: must be a string
+ // icon = "" + icon;
+ // }
+ if (icon !== false) {
+ role = aria ? " role='presentation'" : "";
+
+ iconTooltip = FT.evalOption(
+ "iconTooltip",
+ node,
+ node,
+ opts,
+ null
+ );
+ iconTooltip = iconTooltip
+ ? " title='" + _escapeTooltip(iconTooltip) + "'"
+ : "";
+
+ if (typeof icon === "string") {
+ if (TEST_IMG.test(icon)) {
+ // node.icon is an image url. Prepend imagePath
+ icon =
+ icon.charAt(0) === "/"
+ ? icon
+ : (opts.imagePath || "") + icon;
+ ares.push(
+ "<img src='" +
+ icon +
+ "' class='fancytree-icon'" +
+ iconTooltip +
+ " alt='' />"
+ );
+ } else {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-custom-icon " +
+ icon +
+ "'" +
+ iconTooltip +
+ "></span>"
+ );
+ }
+ } else if (icon.text) {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-custom-icon " +
+ (icon.addClass || "") +
+ "'" +
+ iconTooltip +
+ ">" +
+ FT.escapeHtml(icon.text) +
+ "</span>"
+ );
+ } else if (icon.html) {
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-custom-icon " +
+ (icon.addClass || "") +
+ "'" +
+ iconTooltip +
+ ">" +
+ icon.html +
+ "</span>"
+ );
+ } else {
+ // standard icon: theme css will take care of this
+ ares.push(
+ "<span " +
+ role +
+ " class='fancytree-icon'" +
+ iconTooltip +
+ "></span>"
+ );
+ }
+ }
+ // Node title
+ nodeTitle = "";
+ if (opts.renderTitle) {
+ nodeTitle =
+ opts.renderTitle.call(
+ tree,
+ { type: "renderTitle" },
+ ctx
+ ) || "";
+ }
+ if (!nodeTitle) {
+ tooltip = FT.evalOption("tooltip", node, node, opts, null);
+ if (tooltip === true) {
+ tooltip = node.title;
+ }
+ // if( node.tooltip ) {
+ // tooltip = node.tooltip;
+ // } else if ( opts.tooltip ) {
+ // tooltip = opts.tooltip === true ? node.title : opts.tooltip.call(tree, node);
+ // }
+ tooltip = tooltip
+ ? " title='" + _escapeTooltip(tooltip) + "'"
+ : "";
+ tabindex = opts.titlesTabbable ? " tabindex='0'" : "";
+
+ nodeTitle =
+ "<span class='fancytree-title'" +
+ tooltip +
+ tabindex +
+ ">" +
+ (opts.escapeTitles
+ ? FT.escapeHtml(node.title)
+ : node.title) +
+ "</span>";
+ }
+ ares.push(nodeTitle);
+ // Note: this will trigger focusout, if node had the focus
+ //$(node.span).html(ares.join("")); // it will cleanup the jQuery data currently associated with SPAN (if any), but it executes more slowly
+ node.span.innerHTML = ares.join("");
+ // Update CSS classes
+ this.nodeRenderStatus(ctx);
+ if (opts.enhanceTitle) {
+ ctx.$title = $(">span.fancytree-title", node.span);
+ nodeTitle =
+ opts.enhanceTitle.call(
+ tree,
+ { type: "enhanceTitle" },
+ ctx
+ ) || "";
+ }
+ },
+ /** Update element classes according to node state.
+ * @param {EventData} ctx
+ */
+ nodeRenderStatus: function (ctx) {
+ // Set classes for current status
+ var $ariaElem,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ // nodeContainer = node[tree.nodeContainerAttrName],
+ hasChildren = node.hasChildren(),
+ isLastSib = node.isLastSibling(),
+ aria = opts.aria,
+ cn = opts._classNames,
+ cnList = [],
+ statusElem = node[tree.statusClassPropName];
+
+ if (!statusElem || tree._enableUpdate === false) {
+ // if this function is called for an unrendered node, ignore it (will be updated on nect render anyway)
+ return;
+ }
+ if (aria) {
+ $ariaElem = $(node.tr || node.li);
+ }
+ // Build a list of class names that we will add to the node <span>
+ cnList.push(cn.node);
+ if (tree.activeNode === node) {
+ cnList.push(cn.active);
+ // $(">span.fancytree-title", statusElem).attr("tabindex", "0");
+ // tree.$container.removeAttr("tabindex");
+ // }else{
+ // $(">span.fancytree-title", statusElem).removeAttr("tabindex");
+ // tree.$container.attr("tabindex", "0");
+ }
+ if (tree.focusNode === node) {
+ cnList.push(cn.focused);
+ }
+ if (node.expanded) {
+ cnList.push(cn.expanded);
+ }
+ if (aria) {
+ if (hasChildren === false) {
+ $ariaElem.removeAttr("aria-expanded");
+ } else {
+ $ariaElem.attr("aria-expanded", Boolean(node.expanded));
+ }
+ }
+ if (node.folder) {
+ cnList.push(cn.folder);
+ }
+ if (hasChildren !== false) {
+ cnList.push(cn.hasChildren);
+ }
+ // TODO: required?
+ if (isLastSib) {
+ cnList.push(cn.lastsib);
+ }
+ if (node.lazy && node.children == null) {
+ cnList.push(cn.lazy);
+ }
+ if (node.partload) {
+ cnList.push(cn.partload);
+ }
+ if (node.partsel) {
+ cnList.push(cn.partsel);
+ }
+ if (FT.evalOption("unselectable", node, node, opts, false)) {
+ cnList.push(cn.unselectable);
+ }
+ if (node._isLoading) {
+ cnList.push(cn.loading);
+ }
+ if (node._error) {
+ cnList.push(cn.error);
+ }
+ if (node.statusNodeType) {
+ cnList.push(cn.statusNodePrefix + node.statusNodeType);
+ }
+ if (node.selected) {
+ cnList.push(cn.selected);
+ if (aria) {
+ $ariaElem.attr("aria-selected", true);
+ }
+ } else if (aria) {
+ $ariaElem.attr("aria-selected", false);
+ }
+ if (node.extraClasses) {
+ cnList.push(node.extraClasses);
+ }
+ // IE6 doesn't correctly evaluate multiple class names,
+ // so we create combined class names that can be used in the CSS
+ if (hasChildren === false) {
+ cnList.push(
+ cn.combinedExpanderPrefix + "n" + (isLastSib ? "l" : "")
+ );
+ } else {
+ cnList.push(
+ cn.combinedExpanderPrefix +
+ (node.expanded ? "e" : "c") +
+ (node.lazy && node.children == null ? "d" : "") +
+ (isLastSib ? "l" : "")
+ );
+ }
+ cnList.push(
+ cn.combinedIconPrefix +
+ (node.expanded ? "e" : "c") +
+ (node.folder ? "f" : "")
+ );
+ // node.span.className = cnList.join(" ");
+ statusElem.className = cnList.join(" ");
+
+ // TODO: we should not set this in the <span> tag also, if we set it here:
+ // Maybe most (all) of the classes should be set in LI instead of SPAN?
+ if (node.li) {
+ // #719: we have to consider that there may be already other classes:
+ $(node.li).toggleClass(cn.lastsib, isLastSib);
+ }
+ },
+ /** Activate node.
+ * flag defaults to true.
+ * If flag is true, the node is activated (must be a synchronous operation)
+ * If flag is false, the node is deactivated (must be a synchronous operation)
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}
+ * @returns {$.Promise}
+ */
+ nodeSetActive: function (ctx, flag, callOpts) {
+ // Handle user click / [space] / [enter], according to clickFolderMode.
+ callOpts = callOpts || {};
+ var subCtx,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ noEvents = callOpts.noEvents === true,
+ noFocus = callOpts.noFocus === true,
+ scroll = callOpts.scrollIntoView !== false,
+ isActive = node === tree.activeNode;
+
+ // flag defaults to true
+ flag = flag !== false;
+ // node.debug("nodeSetActive", flag);
+
+ if (isActive === flag) {
+ // Nothing to do
+ return _getResolvedPromise(node);
+ }
+ // #1042: don't scroll between mousedown/-up when clicking an embedded link
+ if (
+ scroll &&
+ ctx.originalEvent &&
+ $(ctx.originalEvent.target).is("a,:checkbox")
+ ) {
+ node.info("Not scrolling while clicking an embedded link.");
+ scroll = false;
+ }
+ if (
+ flag &&
+ !noEvents &&
+ this._triggerNodeEvent(
+ "beforeActivate",
+ node,
+ ctx.originalEvent
+ ) === false
+ ) {
+ // Callback returned false
+ return _getRejectedPromise(node, ["rejected"]);
+ }
+ if (flag) {
+ if (tree.activeNode) {
+ _assert(
+ tree.activeNode !== node,
+ "node was active (inconsistency)"
+ );
+ subCtx = $.extend({}, ctx, { node: tree.activeNode });
+ tree.nodeSetActive(subCtx, false);
+ _assert(
+ tree.activeNode === null,
+ "deactivate was out of sync?"
+ );
+ }
+
+ if (opts.activeVisible) {
+ // If no focus is set (noFocus: true) and there is no focused node, this node is made visible.
+ // scroll = noFocus && tree.focusNode == null;
+ // #863: scroll by default (unless `scrollIntoView: false` was passed)
+ node.makeVisible({ scrollIntoView: scroll });
+ }
+ tree.activeNode = node;
+ tree.nodeRenderStatus(ctx);
+ if (!noFocus) {
+ tree.nodeSetFocus(ctx);
+ }
+ if (!noEvents) {
+ tree._triggerNodeEvent(
+ "activate",
+ node,
+ ctx.originalEvent
+ );
+ }
+ } else {
+ _assert(
+ tree.activeNode === node,
+ "node was not active (inconsistency)"
+ );
+ tree.activeNode = null;
+ this.nodeRenderStatus(ctx);
+ if (!noEvents) {
+ ctx.tree._triggerNodeEvent(
+ "deactivate",
+ node,
+ ctx.originalEvent
+ );
+ }
+ }
+ return _getResolvedPromise(node);
+ },
+ /** Expand or collapse node, return Deferred.promise.
+ *
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ * @param {object} [opts] additional options. Defaults to `{noAnimation: false, noEvents: false}`
+ * @returns {$.Promise} The deferred will be resolved as soon as the (lazy)
+ * data was retrieved, rendered, and the expand animation finished.
+ */
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ callOpts = callOpts || {};
+ var _afterLoad,
+ dfd,
+ i,
+ l,
+ parents,
+ prevAC,
+ node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ noAnimation = callOpts.noAnimation === true,
+ noEvents = callOpts.noEvents === true;
+
+ // flag defaults to true
+ flag = flag !== false;
+
+ // node.debug("nodeSetExpanded(" + flag + ")");
+
+ if ($(node.li).hasClass(opts._classNames.animating)) {
+ node.warn(
+ "setExpanded(" + flag + ") while animating: ignored."
+ );
+ return _getRejectedPromise(node, ["recursion"]);
+ }
+
+ if ((node.expanded && flag) || (!node.expanded && !flag)) {
+ // Nothing to do
+ // node.debug("nodeSetExpanded(" + flag + "): nothing to do");
+ return _getResolvedPromise(node);
+ } else if (flag && !node.lazy && !node.hasChildren()) {
+ // Prevent expanding of empty nodes
+ // return _getRejectedPromise(node, ["empty"]);
+ return _getResolvedPromise(node);
+ } else if (!flag && node.getLevel() < opts.minExpandLevel) {
+ // Prevent collapsing locked levels
+ return _getRejectedPromise(node, ["locked"]);
+ } else if (
+ !noEvents &&
+ this._triggerNodeEvent(
+ "beforeExpand",
+ node,
+ ctx.originalEvent
+ ) === false
+ ) {
+ // Callback returned false
+ return _getRejectedPromise(node, ["rejected"]);
+ }
+ // If this node inside a collpased node, no animation and scrolling is needed
+ if (!noAnimation && !node.isVisible()) {
+ noAnimation = callOpts.noAnimation = true;
+ }
+
+ dfd = new $.Deferred();
+
+ // Auto-collapse mode: collapse all siblings
+ if (flag && !node.expanded && opts.autoCollapse) {
+ parents = node.getParentList(false, true);
+ prevAC = opts.autoCollapse;
+ try {
+ opts.autoCollapse = false;
+ for (i = 0, l = parents.length; i < l; i++) {
+ // TODO: should return promise?
+ this._callHook(
+ "nodeCollapseSiblings",
+ parents[i],
+ callOpts
+ );
+ }
+ } finally {
+ opts.autoCollapse = prevAC;
+ }
+ }
+ // Trigger expand/collapse after expanding
+ dfd.done(function () {
+ var lastChild = node.getLastChild();
+
+ if (
+ flag &&
+ opts.autoScroll &&
+ !noAnimation &&
+ lastChild &&
+ tree._enableUpdate
+ ) {
+ // Scroll down to last child, but keep current node visible
+ lastChild
+ .scrollIntoView(true, { topNode: node })
+ .always(function () {
+ if (!noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ });
+ } else {
+ if (!noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ }
+ });
+ // vvv Code below is executed after loading finished:
+ _afterLoad = function (callback) {
+ var cn = opts._classNames,
+ isVisible,
+ isExpanded,
+ effect = opts.toggleEffect;
+
+ node.expanded = flag;
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ flag ? "expand" : "collapse"
+ );
+ // Create required markup, but make sure the top UL is hidden, so we
+ // can animate later
+ tree._callHook("nodeRender", ctx, false, false, true);
+
+ // Hide children, if node is collapsed
+ if (node.ul) {
+ isVisible = node.ul.style.display !== "none";
+ isExpanded = !!node.expanded;
+ if (isVisible === isExpanded) {
+ node.warn(
+ "nodeSetExpanded: UL.style.display already set"
+ );
+ } else if (!effect || noAnimation) {
+ node.ul.style.display =
+ node.expanded || !parent ? "" : "none";
+ } else {
+ // The UI toggle() effect works with the ext-wide extension,
+ // while jQuery.animate() has problems when the title span
+ // has position: absolute.
+ // Since jQuery UI 1.12, the blind effect requires the parent
+ // element to have 'position: relative'.
+ // See #716, #717
+ $(node.li).addClass(cn.animating); // #717
+
+ if (_isFunction($(node.ul)[effect.effect])) {
+ // tree.debug( "use jquery." + effect.effect + " method" );
+ $(node.ul)[effect.effect]({
+ duration: effect.duration,
+ always: function () {
+ // node.debug("fancytree-animating end: " + node.li.className);
+ $(this).removeClass(cn.animating); // #716
+ $(node.li).removeClass(cn.animating); // #717
+ callback();
+ },
+ });
+ } else {
+ // The UI toggle() effect works with the ext-wide extension,
+ // while jQuery.animate() has problems when the title span
+ // has positon: absolute.
+ // Since jQuery UI 1.12, the blind effect requires the parent
+ // element to have 'position: relative'.
+ // See #716, #717
+ // tree.debug("use specified effect (" + effect.effect + ") with the jqueryui.toggle method");
+
+ // try to stop an animation that might be already in progress
+ $(node.ul).stop(true, true); //< does not work after resetLazy has been called for a node whose animation wasn't complete and effect was "blind"
+
+ // dirty fix to remove a defunct animation (effect: "blind") after resetLazy has been called
+ $(node.ul)
+ .parent()
+ .find(".ui-effects-placeholder")
+ .remove();
+
+ $(node.ul).toggle(
+ effect.effect,
+ effect.options,
+ effect.duration,
+ function () {
+ // node.debug("fancytree-animating end: " + node.li.className);
+ $(this).removeClass(cn.animating); // #716
+ $(node.li).removeClass(cn.animating); // #717
+ callback();
+ }
+ );
+ }
+ return;
+ }
+ }
+ callback();
+ };
+ // ^^^ Code above is executed after loading finshed.
+
+ // Load lazy nodes, if any. Then continue with _afterLoad()
+ if (flag && node.lazy && node.hasChildren() === undefined) {
+ // node.debug("nodeSetExpanded: load start...");
+ node.load()
+ .done(function () {
+ // node.debug("nodeSetExpanded: load done");
+ if (dfd.notifyWith) {
+ // requires jQuery 1.6+
+ dfd.notifyWith(node, ["loaded"]);
+ }
+ _afterLoad(function () {
+ dfd.resolveWith(node);
+ });
+ })
+ .fail(function (errMsg) {
+ _afterLoad(function () {
+ dfd.rejectWith(node, [
+ "load failed (" + errMsg + ")",
+ ]);
+ });
+ });
+ /*
+ var source = tree._triggerNodeEvent("lazyLoad", node, ctx.originalEvent);
+ _assert(typeof source !== "boolean", "lazyLoad event must return source in data.result");
+ node.debug("nodeSetExpanded: load start...");
+ this._callHook("nodeLoadChildren", ctx, source).done(function(){
+ node.debug("nodeSetExpanded: load done");
+ if(dfd.notifyWith){ // requires jQuery 1.6+
+ dfd.notifyWith(node, ["loaded"]);
+ }
+ _afterLoad.call(tree);
+ }).fail(function(errMsg){
+ dfd.rejectWith(node, ["load failed (" + errMsg + ")"]);
+ });
+ */
+ } else {
+ _afterLoad(function () {
+ dfd.resolveWith(node);
+ });
+ }
+ // node.debug("nodeSetExpanded: returns");
+ return dfd.promise();
+ },
+ /** Focus or blur this node.
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ */
+ nodeSetFocus: function (ctx, flag) {
+ // ctx.node.debug("nodeSetFocus(" + flag + ")");
+ var ctx2,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = tree.options,
+ // et = ctx.originalEvent && ctx.originalEvent.type,
+ isInput = ctx.originalEvent
+ ? $(ctx.originalEvent.target).is(":input")
+ : false;
+
+ flag = flag !== false;
+
+ // (node || tree).debug("nodeSetFocus(" + flag + "), event: " + et + ", isInput: "+ isInput);
+ // Blur previous node if any
+ if (tree.focusNode) {
+ if (tree.focusNode === node && flag) {
+ // node.debug("nodeSetFocus(" + flag + "): nothing to do");
+ return;
+ }
+ ctx2 = $.extend({}, ctx, { node: tree.focusNode });
+ tree.focusNode = null;
+ this._triggerNodeEvent("blur", ctx2);
+ this._callHook("nodeRenderStatus", ctx2);
+ }
+ // Set focus to container and node
+ if (flag) {
+ if (!this.hasFocus()) {
+ node.debug("nodeSetFocus: forcing container focus");
+ this._callHook("treeSetFocus", ctx, true, {
+ calledByNode: true,
+ });
+ }
+ node.makeVisible({ scrollIntoView: false });
+ tree.focusNode = node;
+ if (opts.titlesTabbable) {
+ if (!isInput) {
+ // #621
+ $(node.span).find(".fancytree-title").focus();
+ }
+ }
+ if (opts.aria) {
+ // Set active descendant to node's span ID (create one, if needed)
+ $(tree.$container).attr(
+ "aria-activedescendant",
+ $(node.tr || node.li)
+ .uniqueId()
+ .attr("id")
+ );
+ // "ftal_" + opts.idPrefix + node.key);
+ }
+ // $(node.span).find(".fancytree-title").focus();
+ this._triggerNodeEvent("focus", ctx);
+
+ // determine if we have focus on or inside tree container
+ var hasFancytreeFocus =
+ document.activeElement === tree.$container.get(0) ||
+ $(document.activeElement, tree.$container).length >= 1;
+
+ if (!hasFancytreeFocus) {
+ // We cannot set KB focus to a node, so use the tree container
+ // #563, #570: IE scrolls on every call to .focus(), if the container
+ // is partially outside the viewport. So do it only, when absolutely
+ // necessary.
+ $(tree.$container).focus();
+ }
+
+ // if( opts.autoActivate ){
+ // tree.nodeSetActive(ctx, true);
+ // }
+ if (opts.autoScroll) {
+ node.scrollIntoView();
+ }
+ this._callHook("nodeRenderStatus", ctx);
+ }
+ },
+ /** (De)Select node, return new status (sync).
+ *
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ * @param {object} [opts] additional options. Defaults to {noEvents: false,
+ * propagateDown: null, propagateUp: null,
+ * callback: null,
+ * }
+ * @returns {boolean} previous status
+ */
+ nodeSetSelected: function (ctx, flag, callOpts) {
+ callOpts = callOpts || {};
+ var node = ctx.node,
+ tree = ctx.tree,
+ opts = ctx.options,
+ noEvents = callOpts.noEvents === true,
+ parent = node.parent;
+
+ // flag defaults to true
+ flag = flag !== false;
+
+ // node.debug("nodeSetSelected(" + flag + ")", ctx);
+
+ // Cannot (de)select unselectable nodes directly (only by propagation or
+ // by setting the `.selected` property)
+ if (FT.evalOption("unselectable", node, node, opts, false)) {
+ return;
+ }
+
+ // Remember the user's intent, in case down -> up propagation prevents
+ // applying it to node.selected
+ node._lastSelectIntent = flag; // Confusing use of '!'
+
+ // Nothing to do?
+ if (!!node.selected === flag) {
+ if (opts.selectMode === 3 && node.partsel && !flag) {
+ // If propagation prevented selecting this node last time, we still
+ // want to allow to apply setSelected(false) now
+ } else {
+ return flag;
+ }
+ }
+
+ if (
+ !noEvents &&
+ this._triggerNodeEvent(
+ "beforeSelect",
+ node,
+ ctx.originalEvent
+ ) === false
+ ) {
+ return !!node.selected;
+ }
+ if (flag && opts.selectMode === 1) {
+ // single selection mode (we don't uncheck all tree nodes, for performance reasons)
+ if (tree.lastSelectedNode) {
+ tree.lastSelectedNode.setSelected(false);
+ }
+ node.selected = flag;
+ } else if (
+ opts.selectMode === 3 &&
+ parent &&
+ !parent.radiogroup &&
+ !node.radiogroup
+ ) {
+ // multi-hierarchical selection mode
+ node.selected = flag;
+ node.fixSelection3AfterClick(callOpts);
+ } else if (parent && parent.radiogroup) {
+ node.visitSiblings(function (n) {
+ n._changeSelectStatusAttrs(flag && n === node);
+ }, true);
+ } else {
+ // default: selectMode: 2, multi selection mode
+ node.selected = flag;
+ }
+ this.nodeRenderStatus(ctx);
+ tree.lastSelectedNode = flag ? node : null;
+ if (!noEvents) {
+ tree._triggerNodeEvent("select", ctx);
+ }
+ },
+ /** Show node status (ok, loading, error, nodata) using styles and a dummy child node.
+ *
+ * @param {EventData} ctx
+ * @param status
+ * @param message
+ * @param details
+ * @since 2.3
+ */
+ nodeSetStatus: function (ctx, status, message, details) {
+ var node = ctx.node,
+ tree = ctx.tree;
+
+ function _clearStatusNode() {
+ // Remove dedicated dummy node, if any
+ var firstChild = node.children ? node.children[0] : null;
+ if (firstChild && firstChild.isStatusNode()) {
+ try {
+ // I've seen exceptions here with loadKeyPath...
+ if (node.ul) {
+ node.ul.removeChild(firstChild.li);
+ firstChild.li = null; // avoid leaks (DT issue 215)
+ }
+ } catch (e) {}
+ if (node.children.length === 1) {
+ node.children = [];
+ } else {
+ node.children.shift();
+ }
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ "clearStatusNode"
+ );
+ }
+ }
+ function _setStatusNode(data, type) {
+ // Create/modify the dedicated dummy node for 'loading...' or
+ // 'error!' status. (only called for direct child of the invisible
+ // system root)
+ var firstChild = node.children ? node.children[0] : null;
+ if (firstChild && firstChild.isStatusNode()) {
+ $.extend(firstChild, data);
+ firstChild.statusNodeType = type;
+ tree._callHook("nodeRenderTitle", firstChild);
+ } else {
+ node._setChildren([data]);
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ "setStatusNode"
+ );
+ node.children[0].statusNodeType = type;
+ tree.render();
+ }
+ return node.children[0];
+ }
+
+ switch (status) {
+ case "ok":
+ _clearStatusNode();
+ node._isLoading = false;
+ node._error = null;
+ node.renderStatus();
+ break;
+ case "loading":
+ if (!node.parent) {
+ _setStatusNode(
+ {
+ title:
+ tree.options.strings.loading +
+ (message ? " (" + message + ")" : ""),
+ // icon: true, // needed for 'loding' icon
+ checkbox: false,
+ tooltip: details,
+ },
+ status
+ );
+ }
+ node._isLoading = true;
+ node._error = null;
+ node.renderStatus();
+ break;
+ case "error":
+ _setStatusNode(
+ {
+ title:
+ tree.options.strings.loadError +
+ (message ? " (" + message + ")" : ""),
+ // icon: false,
+ checkbox: false,
+ tooltip: details,
+ },
+ status
+ );
+ node._isLoading = false;
+ node._error = { message: message, details: details };
+ node.renderStatus();
+ break;
+ case "nodata":
+ _setStatusNode(
+ {
+ title: message || tree.options.strings.noData,
+ // icon: false,
+ checkbox: false,
+ tooltip: details,
+ },
+ status
+ );
+ node._isLoading = false;
+ node._error = null;
+ node.renderStatus();
+ break;
+ default:
+ $.error("invalid node status " + status);
+ }
+ },
+ /**
+ *
+ * @param {EventData} ctx
+ */
+ nodeToggleExpanded: function (ctx) {
+ return this.nodeSetExpanded(ctx, !ctx.node.expanded);
+ },
+ /**
+ * @param {EventData} ctx
+ */
+ nodeToggleSelected: function (ctx) {
+ var node = ctx.node,
+ flag = !node.selected;
+
+ // In selectMode: 3 this node may be unselected+partsel, even if
+ // setSelected(true) was called before, due to `unselectable` children.
+ // In this case, we now toggle as `setSelected(false)`
+ if (
+ node.partsel &&
+ !node.selected &&
+ node._lastSelectIntent === true
+ ) {
+ flag = false;
+ node.selected = true; // so it is not considered 'nothing to do'
+ }
+ node._lastSelectIntent = flag;
+ return this.nodeSetSelected(ctx, flag);
+ },
+ /** Remove all nodes.
+ * @param {EventData} ctx
+ */
+ treeClear: function (ctx) {
+ var tree = ctx.tree;
+ tree.activeNode = null;
+ tree.focusNode = null;
+ tree.$div.find(">ul.fancytree-container").empty();
+ // TODO: call destructors and remove reference loops
+ tree.rootNode.children = null;
+ tree._callHook("treeStructureChanged", ctx, "clear");
+ },
+ /** Widget was created (called only once, even it re-initialized).
+ * @param {EventData} ctx
+ */
+ treeCreate: function (ctx) {},
+ /** Widget was destroyed.
+ * @param {EventData} ctx
+ */
+ treeDestroy: function (ctx) {
+ this.$div.find(">ul.fancytree-container").remove();
+ if (this.$source) {
+ this.$source.removeClass("fancytree-helper-hidden");
+ }
+ },
+ /** Widget was (re-)initialized.
+ * @param {EventData} ctx
+ */
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ opts = tree.options;
+
+ //this.debug("Fancytree.treeInit()");
+ // Add container to the TAB chain
+ // See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant
+ // #577: Allow to set tabindex to "0", "-1" and ""
+ tree.$container.attr("tabindex", opts.tabindex);
+
+ // Copy some attributes to tree.data
+ $.each(TREE_ATTRS, function (i, attr) {
+ if (opts[attr] !== undefined) {
+ tree.info("Move option " + attr + " to tree");
+ tree[attr] = opts[attr];
+ delete opts[attr];
+ }
+ });
+
+ if (opts.checkboxAutoHide) {
+ tree.$container.addClass("fancytree-checkbox-auto-hide");
+ }
+ if (opts.rtl) {
+ tree.$container
+ .attr("DIR", "RTL")
+ .addClass("fancytree-rtl");
+ } else {
+ tree.$container
+ .removeAttr("DIR")
+ .removeClass("fancytree-rtl");
+ }
+ if (opts.aria) {
+ tree.$container.attr("role", "tree");
+ if (opts.selectMode !== 1) {
+ tree.$container.attr("aria-multiselectable", true);
+ }
+ }
+ this.treeLoad(ctx);
+ },
+ /** Parse Fancytree from source, as configured in the options.
+ * @param {EventData} ctx
+ * @param {object} [source] optional new source (use last data otherwise)
+ */
+ treeLoad: function (ctx, source) {
+ var metaData,
+ type,
+ $ul,
+ tree = ctx.tree,
+ $container = ctx.widget.element,
+ dfd,
+ // calling context for root node
+ rootCtx = $.extend({}, ctx, { node: this.rootNode });
+
+ if (tree.rootNode.children) {
+ this.treeClear(ctx);
+ }
+ source = source || this.options.source;
+
+ if (!source) {
+ type = $container.data("type") || "html";
+ switch (type) {
+ case "html":
+ // There should be an embedded `<ul>` with initial nodes,
+ // but another `<ul class='fancytree-container'>` is appended
+ // to the tree's <div> on startup anyway.
+ $ul = $container
+ .find(">ul")
+ .not(".fancytree-container")
+ .first();
+
+ if ($ul.length) {
+ $ul.addClass(
+ "ui-fancytree-source fancytree-helper-hidden"
+ );
+ source = $.ui.fancytree.parseHtml($ul);
+ // allow to init tree.data.foo from <ul data-foo=''>
+ this.data = $.extend(
+ this.data,
+ _getElementDataAsDict($ul)
+ );
+ } else {
+ FT.warn(
+ "No `source` option was passed and container does not contain `<ul>`: assuming `source: []`."
+ );
+ source = [];
+ }
+ break;
+ case "json":
+ source = $.parseJSON($container.text());
+ // $container already contains the <ul>, but we remove the plain (json) text
+ // $container.empty();
+ $container
+ .contents()
+ .filter(function () {
+ return this.nodeType === 3;
+ })
+ .remove();
+ if ($.isPlainObject(source)) {
+ // We got {foo: 'abc', children: [...]}
+ _assert(
+ _isArray(source.children),
+ "if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')"
+ );
+ metaData = source;
+ source = source.children;
+ delete metaData.children;
+ // Copy some attributes to tree.data
+ $.each(TREE_ATTRS, function (i, attr) {
+ if (metaData[attr] !== undefined) {
+ tree[attr] = metaData[attr];
+ delete metaData[attr];
+ }
+ });
+ // Copy extra properties to tree.data.foo
+ $.extend(tree.data, metaData);
+ }
+ break;
+ default:
+ $.error("Invalid data-type: " + type);
+ }
+ } else if (typeof source === "string") {
+ // TODO: source is an element ID
+ $.error("Not implemented");
+ }
+
+ // preInit is fired when the widget markup is created, but nodes
+ // not yet loaded
+ tree._triggerTreeEvent("preInit", null);
+
+ // Trigger fancytreeinit after nodes have been loaded
+ dfd = this.nodeLoadChildren(rootCtx, source)
+ .done(function () {
+ tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ "loadChildren"
+ );
+ tree.render();
+ if (ctx.options.selectMode === 3) {
+ tree.rootNode.fixSelection3FromEndNodes();
+ }
+ if (tree.activeNode && tree.options.activeVisible) {
+ tree.activeNode.makeVisible();
+ }
+ tree._triggerTreeEvent("init", null, { status: true });
+ })
+ .fail(function () {
+ tree.render();
+ tree._triggerTreeEvent("init", null, { status: false });
+ });
+ return dfd;
+ },
+ /** Node was inserted into or removed from the tree.
+ * @param {EventData} ctx
+ * @param {boolean} add
+ * @param {FancytreeNode} node
+ */
+ treeRegisterNode: function (ctx, add, node) {
+ ctx.tree._callHook(
+ "treeStructureChanged",
+ ctx,
+ add ? "addNode" : "removeNode"
+ );
+ },
+ /** Widget got focus.
+ * @param {EventData} ctx
+ * @param {boolean} [flag=true]
+ */
+ treeSetFocus: function (ctx, flag, callOpts) {
+ var targetNode;
+
+ flag = flag !== false;
+
+ // this.debug("treeSetFocus(" + flag + "), callOpts: ", callOpts, this.hasFocus());
+ // this.debug(" focusNode: " + this.focusNode);
+ // this.debug(" activeNode: " + this.activeNode);
+ if (flag !== this.hasFocus()) {
+ this._hasFocus = flag;
+ if (!flag && this.focusNode) {
+ // Node also looses focus if widget blurs
+ this.focusNode.setFocus(false);
+ } else if (flag && (!callOpts || !callOpts.calledByNode)) {
+ $(this.$container).focus();
+ }
+ this.$container.toggleClass("fancytree-treefocus", flag);
+ this._triggerTreeEvent(flag ? "focusTree" : "blurTree");
+ if (flag && !this.activeNode) {
+ // #712: Use last mousedowned node ('click' event fires after focusin)
+ targetNode =
+ this._lastMousedownNode || this.getFirstChild();
+ if (targetNode) {
+ targetNode.setFocus();
+ }
+ }
+ }
+ },
+ /** Widget option was set using `$().fancytree("option", "KEY", VALUE)`.
+ *
+ * Note: `key` may reference a nested option, e.g. 'dnd5.scroll'.
+ * In this case `value`contains the complete, modified `dnd5` option hash.
+ * We can check for changed values like
+ * if( value.scroll !== tree.options.dnd5.scroll ) {...}
+ *
+ * @param {EventData} ctx
+ * @param {string} key option name
+ * @param {any} value option value
+ */
+ treeSetOption: function (ctx, key, value) {
+ var tree = ctx.tree,
+ callDefault = true,
+ callCreate = false,
+ callRender = false;
+
+ switch (key) {
+ case "aria":
+ case "checkbox":
+ case "icon":
+ case "minExpandLevel":
+ case "tabindex":
+ // tree._callHook("treeCreate", tree);
+ callCreate = true;
+ callRender = true;
+ break;
+ case "checkboxAutoHide":
+ tree.$container.toggleClass(
+ "fancytree-checkbox-auto-hide",
+ !!value
+ );
+ break;
+ case "escapeTitles":
+ case "tooltip":
+ callRender = true;
+ break;
+ case "rtl":
+ if (value === false) {
+ tree.$container
+ .removeAttr("DIR")
+ .removeClass("fancytree-rtl");
+ } else {
+ tree.$container
+ .attr("DIR", "RTL")
+ .addClass("fancytree-rtl");
+ }
+ callRender = true;
+ break;
+ case "source":
+ callDefault = false;
+ tree._callHook("treeLoad", tree, value);
+ callRender = true;
+ break;
+ }
+ tree.debug(
+ "set option " +
+ key +
+ "=" +
+ value +
+ " <" +
+ typeof value +
+ ">"
+ );
+ if (callDefault) {
+ if (this.widget._super) {
+ // jQuery UI 1.9+
+ this.widget._super.call(this.widget, key, value);
+ } else {
+ // jQuery UI <= 1.8, we have to manually invoke the _setOption method from the base widget
+ $.Widget.prototype._setOption.call(
+ this.widget,
+ key,
+ value
+ );
+ }
+ }
+ if (callCreate) {
+ tree._callHook("treeCreate", tree);
+ }
+ if (callRender) {
+ tree.render(true, false); // force, not-deep
+ }
+ },
+ /** A Node was added, removed, moved, or it's visibility changed.
+ * @param {EventData} ctx
+ */
+ treeStructureChanged: function (ctx, type) {},
+ }
+ );
+
+ /*******************************************************************************
+ * jQuery UI widget boilerplate
+ */
+
+ /**
+ * The plugin (derrived from [jQuery.Widget](http://api.jqueryui.com/jQuery.widget/)).
+ *
+ * **Note:**
+ * These methods implement the standard jQuery UI widget API.
+ * It is recommended to use methods of the {Fancytree} instance instead
+ *
+ * @example
+ * // DEPRECATED: Access jQuery UI widget methods and members:
+ * var tree = $("#tree").fancytree("getTree");
+ * var node = $("#tree").fancytree("getActiveNode");
+ *
+ * // RECOMMENDED: Use the Fancytree object API
+ * var tree = $.ui.fancytree.getTree("#tree");
+ * var node = tree.getActiveNode();
+ *
+ * // or you may already have stored the tree instance upon creation:
+ * import {createTree, version} from 'jquery.fancytree'
+ * const tree = createTree('#tree', { ... });
+ * var node = tree.getActiveNode();
+ *
+ * @see {Fancytree_Static#getTree}
+ * @deprecated Use methods of the {Fancytree} instance instead
+ * @mixin Fancytree_Widget
+ */
+
+ $.widget(
+ "ui.fancytree",
+ /** @lends Fancytree_Widget# */
+ {
+ /**These options will be used as defaults
+ * @type {FancytreeOptions}
+ */
+ options: {
+ activeVisible: true,
+ ajax: {
+ type: "GET",
+ cache: false, // false: Append random '_' argument to the request url to prevent caching.
+ // timeout: 0, // >0: Make sure we get an ajax error if server is unreachable
+ dataType: "json", // Expect json format and pass json object to callbacks.
+ },
+ aria: true,
+ autoActivate: true,
+ autoCollapse: false,
+ autoScroll: false,
+ checkbox: false,
+ clickFolderMode: 4,
+ copyFunctionsToData: false,
+ debugLevel: null, // 0..4 (null: use global setting $.ui.fancytree.debugLevel)
+ disabled: false, // TODO: required anymore?
+ enableAspx: 42, // TODO: this is truethy, but distinguishable from true: default will change to false in the future
+ escapeTitles: false,
+ extensions: [],
+ focusOnSelect: false,
+ generateIds: false,
+ icon: true,
+ idPrefix: "ft_",
+ keyboard: true,
+ keyPathSeparator: "/",
+ minExpandLevel: 1,
+ nodata: true, // (bool, string, or callback) display message, when no data available
+ quicksearch: false,
+ rtl: false,
+ scrollOfs: { top: 0, bottom: 0 },
+ scrollParent: null,
+ selectMode: 2,
+ strings: {
+ loading: "Loading...", // &#8230; would be escaped when escapeTitles is true
+ loadError: "Load error!",
+ moreData: "More...",
+ noData: "No data.",
+ },
+ tabindex: "0",
+ titlesTabbable: false,
+ toggleEffect: { effect: "slideToggle", duration: 200 }, //< "toggle" or "slideToggle" to use jQuery instead of jQueryUI for toggleEffect animation
+ tooltip: false,
+ treeId: null,
+ _classNames: {
+ active: "fancytree-active",
+ animating: "fancytree-animating",
+ combinedExpanderPrefix: "fancytree-exp-",
+ combinedIconPrefix: "fancytree-ico-",
+ error: "fancytree-error",
+ expanded: "fancytree-expanded",
+ focused: "fancytree-focused",
+ folder: "fancytree-folder",
+ hasChildren: "fancytree-has-children",
+ lastsib: "fancytree-lastsib",
+ lazy: "fancytree-lazy",
+ loading: "fancytree-loading",
+ node: "fancytree-node",
+ partload: "fancytree-partload",
+ partsel: "fancytree-partsel",
+ radio: "fancytree-radio",
+ selected: "fancytree-selected",
+ statusNodePrefix: "fancytree-statusnode-",
+ unselectable: "fancytree-unselectable",
+ },
+ // events
+ lazyLoad: null,
+ postProcess: null,
+ },
+ _deprecationWarning: function (name) {
+ var tree = this.tree;
+
+ if (tree && tree.options.debugLevel >= 3) {
+ tree.warn(
+ "$().fancytree('" +
+ name +
+ "') is deprecated (see https://wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Widget.html"
+ );
+ }
+ },
+ /* Set up the widget, Called on first $().fancytree() */
+ _create: function () {
+ this.tree = new Fancytree(this);
+
+ this.$source =
+ this.source || this.element.data("type") === "json"
+ ? this.element
+ : this.element.find(">ul").first();
+ // Subclass Fancytree instance with all enabled extensions
+ var extension,
+ extName,
+ i,
+ opts = this.options,
+ extensions = opts.extensions,
+ base = this.tree;
+
+ for (i = 0; i < extensions.length; i++) {
+ extName = extensions[i];
+ extension = $.ui.fancytree._extensions[extName];
+ if (!extension) {
+ $.error(
+ "Could not apply extension '" +
+ extName +
+ "' (it is not registered, did you forget to include it?)"
+ );
+ }
+ // Add extension options as tree.options.EXTENSION
+ // _assert(!this.tree.options[extName], "Extension name must not exist as option name: " + extName);
+
+ // console.info("extend " + extName, extension.options, this.tree.options[extName])
+ // issue #876: we want to replace custom array-options, not merge them
+ this.tree.options[extName] = _simpleDeepMerge(
+ {},
+ extension.options,
+ this.tree.options[extName]
+ );
+ // this.tree.options[extName] = $.extend(true, {}, extension.options, this.tree.options[extName]);
+
+ // console.info("extend " + extName + " =>", this.tree.options[extName])
+ // console.info("extend " + extName + " org default =>", extension.options)
+
+ // Add a namespace tree.ext.EXTENSION, to hold instance data
+ _assert(
+ this.tree.ext[extName] === undefined,
+ "Extension name must not exist as Fancytree.ext attribute: '" +
+ extName +
+ "'"
+ );
+ // this.tree[extName] = extension;
+ this.tree.ext[extName] = {};
+ // Subclass Fancytree methods using proxies.
+ _subclassObject(this.tree, base, extension, extName);
+ // current extension becomes base for the next extension
+ base = extension;
+ }
+ //
+ if (opts.icons !== undefined) {
+ // 2015-11-16
+ if (opts.icon === true) {
+ this.tree.warn(
+ "'icons' tree option is deprecated since v2.14.0: use 'icon' instead"
+ );
+ opts.icon = opts.icons;
+ } else {
+ $.error(
+ "'icons' tree option is deprecated since v2.14.0: use 'icon' only instead"
+ );
+ }
+ }
+ if (opts.iconClass !== undefined) {
+ // 2015-11-16
+ if (opts.icon) {
+ $.error(
+ "'iconClass' tree option is deprecated since v2.14.0: use 'icon' only instead"
+ );
+ } else {
+ this.tree.warn(
+ "'iconClass' tree option is deprecated since v2.14.0: use 'icon' instead"
+ );
+ opts.icon = opts.iconClass;
+ }
+ }
+ if (opts.tabbable !== undefined) {
+ // 2016-04-04
+ opts.tabindex = opts.tabbable ? "0" : "-1";
+ this.tree.warn(
+ "'tabbable' tree option is deprecated since v2.17.0: use 'tabindex='" +
+ opts.tabindex +
+ "' instead"
+ );
+ }
+ //
+ this.tree._callHook("treeCreate", this.tree);
+ // Note: 'fancytreecreate' event is fired by widget base class
+ // this.tree._triggerTreeEvent("create");
+ },
+
+ /* Called on every $().fancytree() */
+ _init: function () {
+ this.tree._callHook("treeInit", this.tree);
+ // TODO: currently we call bind after treeInit, because treeInit
+ // might change tree.$container.
+ // It would be better, to move event binding into hooks altogether
+ this._bind();
+ },
+
+ /* Use the _setOption method to respond to changes to options. */
+ _setOption: function (key, value) {
+ return this.tree._callHook(
+ "treeSetOption",
+ this.tree,
+ key,
+ value
+ );
+ },
+
+ /** Use the destroy method to clean up any modifications your widget has made to the DOM */
+ _destroy: function () {
+ this._unbind();
+ this.tree._callHook("treeDestroy", this.tree);
+ // In jQuery UI 1.8, you must invoke the destroy method from the base widget
+ // $.Widget.prototype.destroy.call(this);
+ // TODO: delete tree and nodes to make garbage collect easier?
+ // TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method
+ },
+
+ // -------------------------------------------------------------------------
+
+ /* Remove all event handlers for our namespace */
+ _unbind: function () {
+ var ns = this.tree._ns;
+ this.element.off(ns);
+ this.tree.$container.off(ns);
+ $(document).off(ns);
+ },
+ /* Add mouse and kyboard handlers to the container */
+ _bind: function () {
+ var self = this,
+ opts = this.options,
+ tree = this.tree,
+ ns = tree._ns;
+ // selstartEvent = ( $.support.selectstart ? "selectstart" : "mousedown" )
+
+ // Remove all previuous handlers for this tree
+ this._unbind();
+
+ //alert("keydown" + ns + "foc=" + tree.hasFocus() + tree.$container);
+ // tree.debug("bind events; container: ", tree.$container);
+ tree.$container
+ .on("focusin" + ns + " focusout" + ns, function (event) {
+ var node = FT.getNode(event),
+ flag = event.type === "focusin";
+
+ if (!flag && node && $(event.target).is("a")) {
+ // #764
+ node.debug(
+ "Ignored focusout on embedded <a> element."
+ );
+ return;
+ }
+ // tree.treeOnFocusInOut.call(tree, event);
+ // tree.debug("Tree container got event " + event.type, node, event, FT.getEventTarget(event));
+ if (flag) {
+ if (tree._getExpiringValue("focusin")) {
+ // #789: IE 11 may send duplicate focusin events
+ tree.debug("Ignored double focusin.");
+ return;
+ }
+ tree._setExpiringValue("focusin", true, 50);
+
+ if (!node) {
+ // #789: IE 11 may send focusin before mousdown(?)
+ node = tree._getExpiringValue("mouseDownNode");
+ if (node) {
+ tree.debug(
+ "Reconstruct mouse target for focusin from recent event."
+ );
+ }
+ }
+ }
+ if (node) {
+ // For example clicking into an <input> that is part of a node
+ tree._callHook(
+ "nodeSetFocus",
+ tree._makeHookContext(node, event),
+ flag
+ );
+ } else {
+ if (
+ tree.tbody &&
+ $(event.target).parents(
+ "table.fancytree-container > thead"
+ ).length
+ ) {
+ // #767: ignore events in the table's header
+ tree.debug(
+ "Ignore focus event outside table body.",
+ event
+ );
+ } else {
+ tree._callHook("treeSetFocus", tree, flag);
+ }
+ }
+ })
+ .on(
+ "selectstart" + ns,
+ "span.fancytree-title",
+ function (event) {
+ // prevent mouse-drags to select text ranges
+ // tree.debug("<span title> got event " + event.type);
+ event.preventDefault();
+ }
+ )
+ .on("keydown" + ns, function (event) {
+ // TODO: also bind keyup and keypress
+ // tree.debug("got event " + event.type + ", hasFocus:" + tree.hasFocus());
+ // if(opts.disabled || opts.keyboard === false || !tree.hasFocus() ){
+ if (opts.disabled || opts.keyboard === false) {
+ return true;
+ }
+ var res,
+ node = tree.focusNode, // node may be null
+ ctx = tree._makeHookContext(node || tree, event),
+ prevPhase = tree.phase;
+
+ try {
+ tree.phase = "userEvent";
+ // If a 'fancytreekeydown' handler returns false, skip the default
+ // handling (implemented by tree.nodeKeydown()).
+ if (node) {
+ res = tree._triggerNodeEvent(
+ "keydown",
+ node,
+ event
+ );
+ } else {
+ res = tree._triggerTreeEvent("keydown", event);
+ }
+ if (res === "preventNav") {
+ res = true; // prevent keyboard navigation, but don't prevent default handling of embedded input controls
+ } else if (res !== false) {
+ res = tree._callHook("nodeKeydown", ctx);
+ }
+ return res;
+ } finally {
+ tree.phase = prevPhase;
+ }
+ })
+ .on("mousedown" + ns, function (event) {
+ var et = FT.getEventTarget(event);
+ // self.tree.debug("event(" + event.type + "): node: ", et.node);
+ // #712: Store the clicked node, so we can use it when we get a focusin event
+ // ('click' event fires after focusin)
+ // tree.debug("event(" + event.type + "): node: ", et.node);
+ tree._lastMousedownNode = et ? et.node : null;
+ // #789: Store the node also for a short period, so we can use it
+ // in a *resulting* focusin event
+ tree._setExpiringValue(
+ "mouseDownNode",
+ tree._lastMousedownNode
+ );
+ })
+ .on("click" + ns + " dblclick" + ns, function (event) {
+ if (opts.disabled) {
+ return true;
+ }
+ var ctx,
+ et = FT.getEventTarget(event),
+ node = et.node,
+ tree = self.tree,
+ prevPhase = tree.phase;
+
+ // self.tree.debug("event(" + event.type + "): node: ", node);
+ if (!node) {
+ return true; // Allow bubbling of other events
+ }
+ ctx = tree._makeHookContext(node, event);
+ // self.tree.debug("event(" + event.type + "): node: ", node);
+ try {
+ tree.phase = "userEvent";
+ switch (event.type) {
+ case "click":
+ ctx.targetType = et.type;
+ if (node.isPagingNode()) {
+ return (
+ tree._triggerNodeEvent(
+ "clickPaging",
+ ctx,
+ event
+ ) === true
+ );
+ }
+ return tree._triggerNodeEvent(
+ "click",
+ ctx,
+ event
+ ) === false
+ ? false
+ : tree._callHook("nodeClick", ctx);
+ case "dblclick":
+ ctx.targetType = et.type;
+ return tree._triggerNodeEvent(
+ "dblclick",
+ ctx,
+ event
+ ) === false
+ ? false
+ : tree._callHook("nodeDblclick", ctx);
+ }
+ } finally {
+ tree.phase = prevPhase;
+ }
+ });
+ },
+ /** Return the active node or null.
+ * @returns {FancytreeNode}
+ * @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getActiveNode: function () {
+ this._deprecationWarning("getActiveNode");
+ return this.tree.activeNode;
+ },
+ /** Return the matching node or null.
+ * @param {string} key
+ * @returns {FancytreeNode}
+ * @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getNodeByKey: function (key) {
+ this._deprecationWarning("getNodeByKey");
+ return this.tree.getNodeByKey(key);
+ },
+ /** Return the invisible system root node.
+ * @returns {FancytreeNode}
+ * @deprecated Use methods of the Fancytree instance instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getRootNode: function () {
+ this._deprecationWarning("getRootNode");
+ return this.tree.rootNode;
+ },
+ /** Return the current tree instance.
+ * @returns {Fancytree}
+ * @deprecated Use `$.ui.fancytree.getTree()` instead (<a href="Fancytree_Widget.html">example above</a>).
+ */
+ getTree: function () {
+ this._deprecationWarning("getTree");
+ return this.tree;
+ },
+ }
+ );
+
+ // $.ui.fancytree was created by the widget factory. Create a local shortcut:
+ FT = $.ui.fancytree;
+
+ /**
+ * Static members in the `$.ui.fancytree` namespace.
+ * This properties and methods can be accessed without instantiating a concrete
+ * Fancytree instance.
+ *
+ * @example
+ * // Access static members:
+ * var node = $.ui.fancytree.getNode(element);
+ * alert($.ui.fancytree.version);
+ *
+ * @mixin Fancytree_Static
+ */
+ $.extend(
+ $.ui.fancytree,
+ /** @lends Fancytree_Static# */
+ {
+ /** Version number `"MAJOR.MINOR.PATCH"`
+ * @type {string} */
+ version: "2.38.3", // Set to semver by 'grunt release'
+ /** @type {string}
+ * @description `"production" for release builds` */
+ buildType: "production", // Set to 'production' by 'grunt build'
+ /** @type {int}
+ * @description 0: silent .. 5: verbose (default: 3 for release builds). */
+ debugLevel: 3, // Set to 3 by 'grunt build'
+ // Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel
+
+ _nextId: 1,
+ _nextNodeKey: 1,
+ _extensions: {},
+ // focusTree: null,
+
+ /** Expose class object as `$.ui.fancytree._FancytreeClass`.
+ * Useful to extend `$.ui.fancytree._FancytreeClass.prototype`.
+ * @type {Fancytree}
+ */
+ _FancytreeClass: Fancytree,
+ /** Expose class object as $.ui.fancytree._FancytreeNodeClass
+ * Useful to extend `$.ui.fancytree._FancytreeNodeClass.prototype`.
+ * @type {FancytreeNode}
+ */
+ _FancytreeNodeClass: FancytreeNode,
+ /* Feature checks to provide backwards compatibility */
+ jquerySupports: {
+ // http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+ positionMyOfs: isVersionAtLeast($.ui.version, 1, 9),
+ },
+ /** Throw an error if condition fails (debug method).
+ * @param {boolean} cond
+ * @param {string} msg
+ */
+ assert: function (cond, msg) {
+ return _assert(cond, msg);
+ },
+ /** Create a new Fancytree instance on a target element.
+ *
+ * @param {Element | jQueryObject | string} el Target DOM element or selector
+ * @param {FancytreeOptions} [opts] Fancytree options
+ * @returns {Fancytree} new tree instance
+ * @example
+ * var tree = $.ui.fancytree.createTree("#tree", {
+ * source: {url: "my/webservice"}
+ * }); // Create tree for this matching element
+ *
+ * @since 2.25
+ */
+ createTree: function (el, opts) {
+ var $tree = $(el).fancytree(opts);
+ return FT.getTree($tree);
+ },
+ /** Return a function that executes *fn* at most every *timeout* ms.
+ * @param {integer} timeout
+ * @param {function} fn
+ * @param {boolean} [invokeAsap=false]
+ * @param {any} [ctx]
+ */
+ debounce: function (timeout, fn, invokeAsap, ctx) {
+ var timer;
+ if (arguments.length === 3 && typeof invokeAsap !== "boolean") {
+ ctx = invokeAsap;
+ invokeAsap = false;
+ }
+ return function () {
+ var args = arguments;
+ ctx = ctx || this;
+ // eslint-disable-next-line no-unused-expressions
+ invokeAsap && !timer && fn.apply(ctx, args);
+ clearTimeout(timer);
+ timer = setTimeout(function () {
+ // eslint-disable-next-line no-unused-expressions
+ invokeAsap || fn.apply(ctx, args);
+ timer = null;
+ }, timeout);
+ };
+ },
+ /** Write message to console if debugLevel >= 4
+ * @param {string} msg
+ */
+ debug: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 4) {
+ consoleApply("log", arguments);
+ }
+ },
+ /** Write error message to console if debugLevel >= 1.
+ * @param {string} msg
+ */
+ error: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 1) {
+ consoleApply("error", arguments);
+ }
+ },
+ /** Convert `<`, `>`, `&`, `"`, `'`, and `/` to the equivalent entities.
+ *
+ * @param {string} s
+ * @returns {string}
+ */
+ escapeHtml: function (s) {
+ return ("" + s).replace(REX_HTML, function (s) {
+ return ENTITY_MAP[s];
+ });
+ },
+ /** Make jQuery.position() arguments backwards compatible, i.e. if
+ * jQuery UI version <= 1.8, convert
+ * { my: "left+3 center", at: "left bottom", of: $target }
+ * to
+ * { my: "left center", at: "left bottom", of: $target, offset: "3 0" }
+ *
+ * See http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at
+ * and http://jsfiddle.net/mar10/6xtu9a4e/
+ *
+ * @param {object} opts
+ * @returns {object} the (potentially modified) original opts hash object
+ */
+ fixPositionOptions: function (opts) {
+ if (opts.offset || ("" + opts.my + opts.at).indexOf("%") >= 0) {
+ $.error(
+ "expected new position syntax (but '%' is not supported)"
+ );
+ }
+ if (!$.ui.fancytree.jquerySupports.positionMyOfs) {
+ var // parse 'left+3 center' into ['left+3 center', 'left', '+3', 'center', undefined]
+ myParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(
+ opts.my
+ ),
+ atParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(
+ opts.at
+ ),
+ // convert to numbers
+ dx =
+ (myParts[2] ? +myParts[2] : 0) +
+ (atParts[2] ? +atParts[2] : 0),
+ dy =
+ (myParts[4] ? +myParts[4] : 0) +
+ (atParts[4] ? +atParts[4] : 0);
+
+ opts = $.extend({}, opts, {
+ // make a copy and overwrite
+ my: myParts[1] + " " + myParts[3],
+ at: atParts[1] + " " + atParts[3],
+ });
+ if (dx || dy) {
+ opts.offset = "" + dx + " " + dy;
+ }
+ }
+ return opts;
+ },
+ /** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.
+ *
+ * @param {Event} event Mouse event, e.g. click, ...
+ * @returns {object} Return a {node: FancytreeNode, type: TYPE} object
+ * TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+ */
+ getEventTarget: function (event) {
+ var $target,
+ tree,
+ tcn = event && event.target ? event.target.className : "",
+ res = { node: this.getNode(event.target), type: undefined };
+ // We use a fast version of $(res.node).hasClass()
+ // See http://jsperf.com/test-for-classname/2
+ if (/\bfancytree-title\b/.test(tcn)) {
+ res.type = "title";
+ } else if (/\bfancytree-expander\b/.test(tcn)) {
+ res.type =
+ res.node.hasChildren() === false
+ ? "prefix"
+ : "expander";
+ // }else if( /\bfancytree-checkbox\b/.test(tcn) || /\bfancytree-radio\b/.test(tcn) ){
+ } else if (/\bfancytree-checkbox\b/.test(tcn)) {
+ res.type = "checkbox";
+ } else if (/\bfancytree(-custom)?-icon\b/.test(tcn)) {
+ res.type = "icon";
+ } else if (/\bfancytree-node\b/.test(tcn)) {
+ // Somewhere near the title
+ res.type = "title";
+ } else if (event && event.target) {
+ $target = $(event.target);
+ if ($target.is("ul[role=group]")) {
+ // #nnn: Clicking right to a node may hit the surrounding UL
+ tree = res.node && res.node.tree;
+ (tree || FT).debug("Ignoring click on outer UL.");
+ res.node = null;
+ } else if ($target.closest(".fancytree-title").length) {
+ // #228: clicking an embedded element inside a title
+ res.type = "title";
+ } else if ($target.closest(".fancytree-checkbox").length) {
+ // E.g. <svg> inside checkbox span
+ res.type = "checkbox";
+ } else if ($target.closest(".fancytree-expander").length) {
+ res.type = "expander";
+ }
+ }
+ return res;
+ },
+ /** Return a string describing the affected node region for a mouse event.
+ *
+ * @param {Event} event Mouse event, e.g. click, mousemove, ...
+ * @returns {string} 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined
+ */
+ getEventTargetType: function (event) {
+ return this.getEventTarget(event).type;
+ },
+ /** Return a FancytreeNode instance from element, event, or jQuery object.
+ *
+ * @param {Element | jQueryObject | Event} el
+ * @returns {FancytreeNode} matching node or null
+ */
+ getNode: function (el) {
+ if (el instanceof FancytreeNode) {
+ return el; // el already was a FancytreeNode
+ } else if (el instanceof $) {
+ el = el[0]; // el was a jQuery object: use the DOM element
+ } else if (el.originalEvent !== undefined) {
+ el = el.target; // el was an Event
+ }
+ while (el) {
+ if (el.ftnode) {
+ return el.ftnode;
+ }
+ el = el.parentNode;
+ }
+ return null;
+ },
+ /** Return a Fancytree instance, from element, index, event, or jQueryObject.
+ *
+ * @param {Element | jQueryObject | Event | integer | string} [el]
+ * @returns {Fancytree} matching tree or null
+ * @example
+ * $.ui.fancytree.getTree(); // Get first Fancytree instance on page
+ * $.ui.fancytree.getTree(1); // Get second Fancytree instance on page
+ * $.ui.fancytree.getTree(event); // Get tree for this mouse- or keyboard event
+ * $.ui.fancytree.getTree("foo"); // Get tree for this `opts.treeId`
+ * $.ui.fancytree.getTree("#tree"); // Get tree for this matching element
+ *
+ * @since 2.13
+ */
+ getTree: function (el) {
+ var widget,
+ orgEl = el;
+
+ if (el instanceof Fancytree) {
+ return el; // el already was a Fancytree
+ }
+ if (el === undefined) {
+ el = 0; // get first tree
+ }
+ if (typeof el === "number") {
+ el = $(".fancytree-container").eq(el); // el was an integer: return nth instance
+ } else if (typeof el === "string") {
+ // `el` may be a treeId or a selector:
+ el = $("#ft-id-" + orgEl).eq(0);
+ if (!el.length) {
+ el = $(orgEl).eq(0); // el was a selector: use first match
+ }
+ } else if (
+ el instanceof Element ||
+ el instanceof HTMLDocument
+ ) {
+ el = $(el);
+ } else if (el instanceof $) {
+ el = el.eq(0); // el was a jQuery object: use the first
+ } else if (el.originalEvent !== undefined) {
+ el = $(el.target); // el was an Event
+ }
+ // el is a jQuery object wit one element here
+ el = el.closest(":ui-fancytree");
+ widget = el.data("ui-fancytree") || el.data("fancytree"); // the latter is required by jQuery <= 1.8
+ return widget ? widget.tree : null;
+ },
+ /** Return an option value that has a default, but may be overridden by a
+ * callback or a node instance attribute.
+ *
+ * Evaluation sequence:
+ *
+ * If `tree.options.<optionName>` is a callback that returns something, use that.
+ * Else if `node.<optionName>` is defined, use that.
+ * Else if `tree.options.<optionName>` is a value, use that.
+ * Else use `defaultValue`.
+ *
+ * @param {string} optionName name of the option property (on node and tree)
+ * @param {FancytreeNode} node passed to the callback
+ * @param {object} nodeObject where to look for the local option property, e.g. `node` or `node.data`
+ * @param {object} treeOption where to look for the tree option, e.g. `tree.options` or `tree.options.dnd5`
+ * @param {any} [defaultValue]
+ * @returns {any}
+ *
+ * @example
+ * // Check for node.foo, tree,options.foo(), and tree.options.foo:
+ * $.ui.fancytree.evalOption("foo", node, node, tree.options);
+ * // Check for node.data.bar, tree,options.qux.bar(), and tree.options.qux.bar:
+ * $.ui.fancytree.evalOption("bar", node, node.data, tree.options.qux);
+ *
+ * @since 2.22
+ */
+ evalOption: function (
+ optionName,
+ node,
+ nodeObject,
+ treeOptions,
+ defaultValue
+ ) {
+ var ctx,
+ res,
+ tree = node.tree,
+ treeOpt = treeOptions[optionName],
+ nodeOpt = nodeObject[optionName];
+
+ if (_isFunction(treeOpt)) {
+ ctx = {
+ node: node,
+ tree: tree,
+ widget: tree.widget,
+ options: tree.widget.options,
+ typeInfo: tree.types[node.type] || {},
+ };
+ res = treeOpt.call(tree, { type: optionName }, ctx);
+ if (res == null) {
+ res = nodeOpt;
+ }
+ } else {
+ res = nodeOpt == null ? treeOpt : nodeOpt;
+ }
+ if (res == null) {
+ res = defaultValue; // no option set at all: return default
+ }
+ return res;
+ },
+ /** Set expander, checkbox, or node icon, supporting string and object format.
+ *
+ * @param {Element | jQueryObject} span
+ * @param {string} baseClass
+ * @param {string | object} icon
+ * @since 2.27
+ */
+ setSpanIcon: function (span, baseClass, icon) {
+ var $span = $(span);
+
+ if (typeof icon === "string") {
+ $span.attr("class", baseClass + " " + icon);
+ } else {
+ // support object syntax: { text: ligature, addClasse: classname }
+ if (icon.text) {
+ $span.text("" + icon.text);
+ } else if (icon.html) {
+ span.innerHTML = icon.html;
+ }
+ $span.attr(
+ "class",
+ baseClass + " " + (icon.addClass || "")
+ );
+ }
+ },
+ /** Convert a keydown or mouse event to a canonical string like 'ctrl+a',
+ * 'ctrl+shift+f2', 'shift+leftdblclick'.
+ *
+ * This is especially handy for switch-statements in event handlers.
+ *
+ * @param {event}
+ * @returns {string}
+ *
+ * @example
+
+ switch( $.ui.fancytree.eventToString(event) ) {
+ case "-":
+ tree.nodeSetExpanded(ctx, false);
+ break;
+ case "shift+return":
+ tree.nodeSetActive(ctx, true);
+ break;
+ case "down":
+ res = node.navigate(event.which, activate);
+ break;
+ default:
+ handled = false;
+ }
+ if( handled ){
+ event.preventDefault();
+ }
+ */
+ eventToString: function (event) {
+ // Poor-man's hotkeys. See here for a complete implementation:
+ // https://github.com/jeresig/jquery.hotkeys
+ var which = event.which,
+ et = event.type,
+ s = [];
+
+ if (event.altKey) {
+ s.push("alt");
+ }
+ if (event.ctrlKey) {
+ s.push("ctrl");
+ }
+ if (event.metaKey) {
+ s.push("meta");
+ }
+ if (event.shiftKey) {
+ s.push("shift");
+ }
+
+ if (et === "click" || et === "dblclick") {
+ s.push(MOUSE_BUTTONS[event.button] + et);
+ } else if (et === "wheel") {
+ s.push(et);
+ } else if (!IGNORE_KEYCODES[which]) {
+ s.push(
+ SPECIAL_KEYCODES[which] ||
+ String.fromCharCode(which).toLowerCase()
+ );
+ }
+ return s.join("+");
+ },
+ /** Write message to console if debugLevel >= 3
+ * @param {string} msg
+ */
+ info: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 3) {
+ consoleApply("info", arguments);
+ }
+ },
+ /* @deprecated: use eventToString(event) instead.
+ */
+ keyEventToString: function (event) {
+ this.warn(
+ "keyEventToString() is deprecated: use eventToString()"
+ );
+ return this.eventToString(event);
+ },
+ /** Return a wrapped handler method, that provides `this._super`.
+ *
+ * @example
+ // Implement `opts.createNode` event to add the 'draggable' attribute
+ $.ui.fancytree.overrideMethod(ctx.options, "createNode", function(event, data) {
+ // Default processing if any
+ this._super.apply(this, arguments);
+ // Add 'draggable' attribute
+ data.node.span.draggable = true;
+ });
+ *
+ * @param {object} instance
+ * @param {string} methodName
+ * @param {function} handler
+ * @param {object} [context] optional context
+ */
+ overrideMethod: function (instance, methodName, handler, context) {
+ var prevSuper,
+ _super = instance[methodName] || $.noop;
+
+ instance[methodName] = function () {
+ var self = context || this;
+
+ try {
+ prevSuper = self._super;
+ self._super = _super;
+ return handler.apply(self, arguments);
+ } finally {
+ self._super = prevSuper;
+ }
+ };
+ },
+ /**
+ * Parse tree data from HTML <ul> markup
+ *
+ * @param {jQueryObject} $ul
+ * @returns {NodeData[]}
+ */
+ parseHtml: function ($ul) {
+ var classes,
+ className,
+ extraClasses,
+ i,
+ iPos,
+ l,
+ tmp,
+ tmp2,
+ $children = $ul.find(">li"),
+ children = [];
+
+ $children.each(function () {
+ var allData,
+ lowerCaseAttr,
+ $li = $(this),
+ $liSpan = $li.find(">span", this).first(),
+ $liA = $liSpan.length ? null : $li.find(">a").first(),
+ d = { tooltip: null, data: {} };
+
+ if ($liSpan.length) {
+ d.title = $liSpan.html();
+ } else if ($liA && $liA.length) {
+ // If a <li><a> tag is specified, use it literally and extract href/target.
+ d.title = $liA.html();
+ d.data.href = $liA.attr("href");
+ d.data.target = $liA.attr("target");
+ d.tooltip = $liA.attr("title");
+ } else {
+ // If only a <li> tag is specified, use the trimmed string up to
+ // the next child <ul> tag.
+ d.title = $li.html();
+ iPos = d.title.search(/<ul/i);
+ if (iPos >= 0) {
+ d.title = d.title.substring(0, iPos);
+ }
+ }
+ d.title = _trim(d.title);
+
+ // Make sure all fields exist
+ for (i = 0, l = CLASS_ATTRS.length; i < l; i++) {
+ d[CLASS_ATTRS[i]] = undefined;
+ }
+ // Initialize to `true`, if class is set and collect extraClasses
+ classes = this.className.split(" ");
+ extraClasses = [];
+ for (i = 0, l = classes.length; i < l; i++) {
+ className = classes[i];
+ if (CLASS_ATTR_MAP[className]) {
+ d[className] = true;
+ } else {
+ extraClasses.push(className);
+ }
+ }
+ d.extraClasses = extraClasses.join(" ");
+
+ // Parse node options from ID, title and class attributes
+ tmp = $li.attr("title");
+ if (tmp) {
+ d.tooltip = tmp; // overrides <a title='...'>
+ }
+ tmp = $li.attr("id");
+ if (tmp) {
+ d.key = tmp;
+ }
+ // Translate hideCheckbox -> checkbox:false
+ if ($li.attr("hideCheckbox")) {
+ d.checkbox = false;
+ }
+ // Add <li data-NAME='...'> as node.data.NAME
+ allData = _getElementDataAsDict($li);
+ if (allData && !$.isEmptyObject(allData)) {
+ // #507: convert data-hidecheckbox (lower case) to hideCheckbox
+ for (lowerCaseAttr in NODE_ATTR_LOWERCASE_MAP) {
+ if (_hasProp(allData, lowerCaseAttr)) {
+ allData[
+ NODE_ATTR_LOWERCASE_MAP[lowerCaseAttr]
+ ] = allData[lowerCaseAttr];
+ delete allData[lowerCaseAttr];
+ }
+ }
+ // #56: Allow to set special node.attributes from data-...
+ for (i = 0, l = NODE_ATTRS.length; i < l; i++) {
+ tmp = NODE_ATTRS[i];
+ tmp2 = allData[tmp];
+ if (tmp2 != null) {
+ delete allData[tmp];
+ d[tmp] = tmp2;
+ }
+ }
+ // All other data-... goes to node.data...
+ $.extend(d.data, allData);
+ }
+ // Recursive reading of child nodes, if LI tag contains an UL tag
+ $ul = $li.find(">ul").first();
+ if ($ul.length) {
+ d.children = $.ui.fancytree.parseHtml($ul);
+ } else {
+ d.children = d.lazy ? undefined : null;
+ }
+ children.push(d);
+ // FT.debug("parse ", d, children);
+ });
+ return children;
+ },
+ /** Add Fancytree extension definition to the list of globally available extensions.
+ *
+ * @param {object} definition
+ */
+ registerExtension: function (definition) {
+ _assert(
+ definition.name != null,
+ "extensions must have a `name` property."
+ );
+ _assert(
+ definition.version != null,
+ "extensions must have a `version` property."
+ );
+ $.ui.fancytree._extensions[definition.name] = definition;
+ },
+ /** Replacement for the deprecated `jQuery.trim()`.
+ *
+ * @param {string} text
+ */
+ trim: _trim,
+ /** Inverse of escapeHtml().
+ *
+ * @param {string} s
+ * @returns {string}
+ */
+ unescapeHtml: function (s) {
+ var e = document.createElement("div");
+ e.innerHTML = s;
+ return e.childNodes.length === 0
+ ? ""
+ : e.childNodes[0].nodeValue;
+ },
+ /** Write warning message to console if debugLevel >= 2.
+ * @param {string} msg
+ */
+ warn: function (msg) {
+ if ($.ui.fancytree.debugLevel >= 2) {
+ consoleApply("warn", arguments);
+ }
+ },
+ }
+ );
+
+ // Value returned by `require('jquery.fancytree')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.logger.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.logger.js
new file mode 100644
index 0000000..39a4264
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.logger.js
@@ -0,0 +1,309 @@
+/*!
+ * jquery.fancytree.logger.js
+ *
+ * Miscellaneous debug extensions.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var i,
+ FT = $.ui.fancytree,
+ PREFIX = "ft-logger: ",
+ logLine = window.console.log,
+ // HOOK_NAMES = "nodeClick nodeCollapseSiblings".split(" "),
+ TREE_EVENT_NAMES =
+ "beforeRestore beforeUpdateViewport blurTree create init focusTree preInit restore updateViewport".split(
+ " "
+ ),
+ NODE_EVENT_NAMES =
+ "activate activateCell beforeActivate beforeExpand beforeSelect blur click collapse createNode dblclick deactivate defaultGridAction expand enhanceTitle focus keydown keypress lazyLoad loadChildren loadError modifyChild postProcess renderNode renderTitle select".split(
+ " "
+ ),
+ EVENT_NAMES = TREE_EVENT_NAMES.concat(NODE_EVENT_NAMES),
+ // HOOK_NAME_MAP = {},
+ EVENT_NAME_MAP = {};
+
+ /*
+ */
+ // for (i = 0; i < HOOK_NAMES.length; i++) {
+ // HOOK_NAME_MAP[HOOK_NAMES[i]] = true;
+ // }
+ for (i = 0; i < EVENT_NAMES.length; i++) {
+ EVENT_NAME_MAP[EVENT_NAMES[i]] = true;
+ }
+
+ function getBrowserInfo() {
+ var n = navigator.appName,
+ ua = navigator.userAgent,
+ tem,
+ m = ua.match(
+ /(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i
+ );
+
+ if (m && (tem = ua.match(/version\/([.\d]+)/i)) !== null) {
+ m[2] = tem[1];
+ }
+ m = m ? [m[1], m[2]] : [n, navigator.appVersion, "-?"];
+ return m.join(", ");
+ }
+
+ function logEvent(event, data) {
+ var res,
+ self = this,
+ // logName = PREFIX + "event." + event.type,
+ opts = data.options.logger,
+ tree = data.tree,
+ // widget = data.widget,
+ obj = data.node || tree,
+ logName = PREFIX + "event." + event.type + " (" + obj + ")";
+
+ if (
+ !opts.traceEvents ||
+ (opts.traceEvents !== true && $.inArray(name, opts.traceEvents) < 0)
+ ) {
+ return self._super.apply(self, arguments);
+ }
+ if (
+ (self._super && opts.timings === true) ||
+ (opts.timings && $.inArray(name, opts.timings) >= 0)
+ ) {
+ // if( name === "nodeRender" ) { logName += obj; } // allow timing for recursive calls
+ // logName += " (" + obj + ")";
+ window.console.time(logName);
+ res = self._super.apply(self, arguments);
+ window.console.timeEnd(logName);
+ } else {
+ // obj.info(logName, data);
+ logLine(logName, event, data);
+ res = self._super.apply(self, arguments);
+ }
+ return res;
+ }
+
+ function logHook(name, this_, args, extra) {
+ var res,
+ ctx = args[0],
+ opts = ctx.options.logger,
+ obj = ctx.node || ctx.tree,
+ logName = PREFIX + "hook." + name + " (" + obj + ")";
+
+ if (
+ !opts.traceHooks ||
+ (opts.traceHooks !== true && $.inArray(name, opts.traceHooks) < 0)
+ ) {
+ return this_._superApply.call(this_, args);
+ }
+ if (
+ opts.timings === true ||
+ (opts.timings && $.inArray(name, opts.timings) >= 0)
+ ) {
+ // if( name === "nodeRender" ) { logName += obj; } // allow timing for recursive calls
+ // logName += " (" + obj + ")";
+ window.console.time(logName);
+ res = this_._superApply.call(this_, args);
+ window.console.timeEnd(logName);
+ } else {
+ if (extra) {
+ // obj.info(logName, extra, ctx);
+ logLine(logName, extra, ctx);
+ } else {
+ // obj.info(logName, ctx);
+ logLine(logName, ctx);
+ }
+ res = this_._superApply.call(this_, args);
+ }
+ return res;
+ }
+
+ /******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "logger",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ logTarget: null, // optional redirect logging to this <div> tag
+ traceEvents: true, // `true`or list of hook names
+ traceUnhandledEvents: false,
+ traceHooks: false, // `true`or list of event names
+ timings: false, // `true`or list of event names
+ },
+ // Overide virtual methods for this extension.
+ // `this` : is this Fancytree object
+ // `this._super`: the virtual function that was overridden (member of prev. extension or Fancytree)
+ treeCreate: function (ctx) {
+ var tree = ctx.tree,
+ opts = ctx.options;
+
+ if (
+ this.options.extensions[this.options.extensions.length - 1] !==
+ "logger"
+ ) {
+ throw Error(
+ "Fancytree 'logger' extension must be listed as last entry."
+ );
+ }
+ tree.warn(
+ "Fancytree logger extension is enabled (this may be slow).",
+ opts.logger
+ );
+
+ tree.debug(
+ "Fancytree v" +
+ $.ui.fancytree.version +
+ ", buildType='" +
+ $.ui.fancytree.buildType +
+ "'"
+ );
+ tree.debug(
+ "jQuery UI " +
+ jQuery.ui.version +
+ " (uiBackCompat=" +
+ $.uiBackCompat +
+ ")"
+ );
+ tree.debug("jQuery " + jQuery.fn.jquery);
+ tree.debug("Browser: " + getBrowserInfo());
+
+ function _log(event, data) {
+ logLine(
+ PREFIX + "event." + event.type + " (unhandled)",
+ event,
+ data
+ );
+ }
+ $.each(EVENT_NAMES, function (i, name) {
+ if (typeof opts[name] === "function") {
+ // tree.info(PREFIX + "override '" + name + "' event");
+ $.ui.fancytree.overrideMethod(
+ opts,
+ name,
+ logEvent,
+ ctx.widget
+ );
+ } else if (opts.logger.traceUnhandledEvents) {
+ opts[name] = _log;
+ }
+ });
+
+ return logHook("treeCreate", this, arguments);
+ },
+ nodeClick: function (ctx) {
+ return logHook(
+ "nodeClick",
+ this,
+ arguments,
+ FT.eventToString(ctx.originalEvent)
+ );
+ },
+ nodeCollapseSiblings: function (ctx) {
+ return logHook("nodeCollapseSiblings", this, arguments);
+ },
+ nodeDblclick: function (ctx) {
+ return logHook("nodeDblclick", this, arguments);
+ },
+ nodeKeydown: function (ctx) {
+ return logHook(
+ "nodeKeydown",
+ this,
+ arguments,
+ FT.eventToString(ctx.originalEvent)
+ );
+ },
+ nodeLoadChildren: function (ctx, source) {
+ return logHook("nodeLoadChildren", this, arguments);
+ },
+ nodeRemoveChildMarkup: function (ctx) {
+ return logHook("nodeRemoveChildMarkup", this, arguments);
+ },
+ nodeRemoveMarkup: function (ctx) {
+ return logHook("nodeRemoveMarkup", this, arguments);
+ },
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ return logHook("nodeRender", this, arguments);
+ },
+ nodeRenderStatus: function (ctx) {
+ return logHook("nodeRenderStatus", this, arguments);
+ },
+ nodeRenderTitle: function (ctx, title) {
+ return logHook("nodeRenderTitle", this, arguments);
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ return logHook("nodeSetActive", this, arguments);
+ },
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ return logHook("nodeSetExpanded", this, arguments);
+ },
+ nodeSetFocus: function (ctx) {
+ return logHook("nodeSetFocus", this, arguments);
+ },
+ nodeSetSelected: function (ctx, flag, callOpts) {
+ return logHook("nodeSetSelected", this, arguments);
+ },
+ nodeSetStatus: function (ctx, status, message, details) {
+ return logHook("nodeSetStatus", this, arguments);
+ },
+ nodeToggleExpanded: function (ctx) {
+ return logHook("nodeToggleExpanded", this, arguments);
+ },
+ nodeToggleSelected: function (ctx) {
+ return logHook("nodeToggleSelected", this, arguments);
+ },
+ treeClear: function (ctx) {
+ return logHook("treeClear", this, arguments);
+ },
+ // treeCreate: function(ctx) {
+ // return logHook("treeCreate", this, arguments);
+ // },
+ treeDestroy: function (ctx) {
+ return logHook("treeDestroy", this, arguments);
+ },
+ treeInit: function (ctx) {
+ return logHook("treeInit", this, arguments);
+ },
+ treeLoad: function (ctx, source) {
+ return logHook("treeLoad", this, arguments);
+ },
+ treeRegisterNode: function (ctx, add, node) {
+ return logHook("treeRegisterNode", this, arguments);
+ },
+ treeSetFocus: function (ctx, flag, callOpts) {
+ return logHook("treeSetFocus", this, arguments);
+ },
+ treeSetOption: function (ctx, key, value) {
+ return logHook("treeSetOption", this, arguments);
+ },
+ treeStructureChanged: function (ctx, type) {
+ return logHook("treeStructureChanged", this, arguments);
+ },
+ });
+
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.menu.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.menu.js
new file mode 100644
index 0000000..71fee75
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.menu.js
@@ -0,0 +1,185 @@
+/*!
+ * jquery.fancytree.menu.js
+ *
+ * Enable jQuery UI Menu as context menu for tree nodes.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @see http://api.jqueryui.com/menu/
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ $.ui.fancytree.registerExtension({
+ name: "menu",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ enable: true,
+ selector: null, //
+ position: {}, //
+ // Events:
+ create: $.noop, //
+ beforeOpen: $.noop, //
+ open: $.noop, //
+ focus: $.noop, //
+ select: $.noop, //
+ close: $.noop, //
+ },
+ // Override virtual methods for this extension.
+ // `this` : is this extension object
+ // `this._base` : the Fancytree instance
+ // `this._super`: the virtual function that was overridden (member of prev. extension or Fancytree)
+ treeInit: function (ctx) {
+ var opts = ctx.options,
+ tree = ctx.tree;
+
+ this._superApply(arguments);
+
+ // Prepare an object that will be passed with menu events
+ tree.ext.menu.data = {
+ tree: tree,
+ node: null,
+ $menu: null,
+ menuId: null,
+ };
+
+ // tree.$container[0].oncontextmenu = function() {return false;};
+ // Replace the standard browser context menu with out own
+ tree.$container.on(
+ "contextmenu",
+ "span.fancytree-node",
+ function (event) {
+ var node = $.ui.fancytree.getNode(event),
+ ctx = {
+ node: node,
+ tree: node.tree,
+ originalEvent: event,
+ options: tree.options,
+ };
+ tree.ext.menu._openMenu(ctx);
+ return false;
+ }
+ );
+
+ // Use jquery.ui.menu
+ $(opts.menu.selector)
+ .menu({
+ create: function (event, ui) {
+ tree.ext.menu.data.$menu = $(this).menu("widget");
+ var data = $.extend({}, tree.ext.menu.data);
+ opts.menu.create.call(tree, event, data);
+ },
+ focus: function (event, ui) {
+ var data = $.extend({}, tree.ext.menu.data, {
+ menuItem: ui.item,
+ menuId: ui.item.find(">a").attr("href"),
+ });
+ opts.menu.focus.call(tree, event, data);
+ },
+ select: function (event, ui) {
+ var data = $.extend({}, tree.ext.menu.data, {
+ menuItem: ui.item,
+ menuId: ui.item.find(">a").attr("href"),
+ });
+ if (
+ opts.menu.select.call(tree, event, data) !== false
+ ) {
+ tree.ext.menu._closeMenu(ctx);
+ }
+ },
+ })
+ .hide();
+ },
+ treeDestroy: function (ctx) {
+ this._superApply(arguments);
+ },
+ _openMenu: function (ctx) {
+ var data,
+ tree = ctx.tree,
+ opts = ctx.options,
+ $menu = $(opts.menu.selector);
+
+ tree.ext.menu.data.node = ctx.node;
+ data = $.extend({}, tree.ext.menu.data);
+
+ if (
+ opts.menu.beforeOpen.call(tree, ctx.originalEvent, data) ===
+ false
+ ) {
+ return;
+ }
+
+ $(document)
+ .on("keydown.fancytree", function (event) {
+ if (event.which === $.ui.keyCode.ESCAPE) {
+ tree.ext.menu._closeMenu(ctx);
+ }
+ })
+ .on("mousedown.fancytree", function (event) {
+ // Close menu when clicked outside menu
+ if ($(event.target).closest(".ui-menu-item").length === 0) {
+ tree.ext.menu._closeMenu(ctx);
+ }
+ });
+ // $menu.position($.extend({my: "left top", at: "left bottom", of: event}, opts.menu.position));
+ $menu
+ .css("position", "absolute")
+ .show()
+ .position({
+ my: "left top",
+ at: "right top",
+ of: ctx.originalEvent,
+ collision: "fit",
+ })
+ .focus();
+
+ opts.menu.open.call(tree, ctx.originalEvent, data);
+ },
+ _closeMenu: function (ctx) {
+ var $menu,
+ tree = ctx.tree,
+ opts = ctx.options,
+ data = $.extend({}, tree.ext.menu.data);
+ if (opts.menu.close.call(tree, ctx.originalEvent, data) === false) {
+ return;
+ }
+ $menu = $(opts.menu.selector);
+ $(document).off("keydown.fancytree, mousedown.fancytree");
+ $menu.hide();
+ tree.ext.menu.data.node = null;
+ },
+ // ,
+ // nodeClick: function(ctx) {
+ // var event = ctx.originalEvent;
+ // if(event.which === 2 || (event.which === 1 && event.ctrlKey)){
+ // event.preventDefault();
+ // ctx.tree.ext.menu._openMenu(ctx);
+ // return false;
+ // }
+ // this._superApply(arguments);
+ // }
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.multi.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.multi.js
new file mode 100644
index 0000000..ec61fed
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.multi.js
@@ -0,0 +1,128 @@
+/*!
+ * jquery.fancytree.multi.js
+ *
+ * Allow multiple selection of nodes by mouse or keyboard.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+
+ // var isMac = /Mac/.test(navigator.platform);
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "multi",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ allowNoSelect: false, //
+ mode: "sameParent", //
+ // Events:
+ // beforeSelect: $.noop // Return false to prevent cancel/save (data.input is available)
+ },
+
+ treeInit: function (ctx) {
+ this._superApply(arguments);
+ this.$container.addClass("fancytree-ext-multi");
+ if (ctx.options.selectMode === 1) {
+ $.error(
+ "Fancytree ext-multi: selectMode: 1 (single) is not compatible."
+ );
+ }
+ },
+ nodeClick: function (ctx) {
+ var //pluginOpts = ctx.options.multi,
+ tree = ctx.tree,
+ node = ctx.node,
+ activeNode = tree.getActiveNode() || tree.getFirstChild(),
+ isCbClick = ctx.targetType === "checkbox",
+ isExpanderClick = ctx.targetType === "expander",
+ eventStr = $.ui.fancytree.eventToString(ctx.originalEvent);
+
+ switch (eventStr) {
+ case "click":
+ if (isExpanderClick) {
+ break;
+ } // Default handler will expand/collapse
+ if (!isCbClick) {
+ tree.selectAll(false);
+ // Select clicked node (radio-button mode)
+ node.setSelected();
+ }
+ // Default handler will toggle checkbox clicks and activate
+ break;
+ case "shift+click":
+ // node.debug("click")
+ tree.visitRows(
+ function (n) {
+ // n.debug("click2", n===node, node)
+ n.setSelected();
+ if (n === node) {
+ return false;
+ }
+ },
+ {
+ start: activeNode,
+ reverse: activeNode.isBelowOf(node),
+ }
+ );
+ break;
+ case "ctrl+click":
+ case "meta+click": // Mac: [Command]
+ node.toggleSelected();
+ return;
+ }
+ return this._superApply(arguments);
+ },
+ nodeKeydown: function (ctx) {
+ var tree = ctx.tree,
+ node = ctx.node,
+ event = ctx.originalEvent,
+ eventStr = $.ui.fancytree.eventToString(event);
+
+ switch (eventStr) {
+ case "up":
+ case "down":
+ tree.selectAll(false);
+ node.navigate(event.which, true);
+ tree.getActiveNode().setSelected();
+ break;
+ case "shift+up":
+ case "shift+down":
+ node.navigate(event.which, true);
+ tree.getActiveNode().setSelected();
+ break;
+ }
+ return this._superApply(arguments);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.persist.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.persist.js
new file mode 100644
index 0000000..c389732
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.persist.js
@@ -0,0 +1,503 @@
+/*!
+ * jquery.fancytree.persist.js
+ *
+ * Persist tree status in cookiesRemove or highlight tree nodes, based on a filter.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @depends: js-cookie or jquery-cookie
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+ /* global Cookies:false */
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+ var cookieStore = null,
+ localStorageStore = null,
+ sessionStorageStore = null,
+ _assert = $.ui.fancytree.assert,
+ ACTIVE = "active",
+ EXPANDED = "expanded",
+ FOCUS = "focus",
+ SELECTED = "selected";
+
+ // Accessing window.xxxStorage may raise security exceptions (see #1022)
+ try {
+ _assert(window.localStorage && window.localStorage.getItem);
+ localStorageStore = {
+ get: function (key) {
+ return window.localStorage.getItem(key);
+ },
+ set: function (key, value) {
+ window.localStorage.setItem(key, value);
+ },
+ remove: function (key) {
+ window.localStorage.removeItem(key);
+ },
+ };
+ } catch (e) {
+ $.ui.fancytree.warn("Could not access window.localStorage", e);
+ }
+
+ try {
+ _assert(window.sessionStorage && window.sessionStorage.getItem);
+ sessionStorageStore = {
+ get: function (key) {
+ return window.sessionStorage.getItem(key);
+ },
+ set: function (key, value) {
+ window.sessionStorage.setItem(key, value);
+ },
+ remove: function (key) {
+ window.sessionStorage.removeItem(key);
+ },
+ };
+ } catch (e) {
+ $.ui.fancytree.warn("Could not access window.sessionStorage", e);
+ }
+
+ if (typeof Cookies === "function") {
+ // Assume https://github.com/js-cookie/js-cookie
+ cookieStore = {
+ get: Cookies.get,
+ set: function (key, value) {
+ Cookies.set(key, value, this.options.persist.cookie);
+ },
+ remove: Cookies.remove,
+ };
+ } else if ($ && typeof $.cookie === "function") {
+ // Fall back to https://github.com/carhartl/jquery-cookie
+ cookieStore = {
+ get: $.cookie,
+ set: function (key, value) {
+ $.cookie(key, value, this.options.persist.cookie);
+ },
+ remove: $.removeCookie,
+ };
+ }
+
+ /* Recursively load lazy nodes
+ * @param {string} mode 'load', 'expand', false
+ */
+ function _loadLazyNodes(tree, local, keyList, mode, dfd) {
+ var i,
+ key,
+ l,
+ node,
+ foundOne = false,
+ expandOpts = tree.options.persist.expandOpts,
+ deferredList = [],
+ missingKeyList = [];
+
+ keyList = keyList || [];
+ dfd = dfd || $.Deferred();
+
+ for (i = 0, l = keyList.length; i < l; i++) {
+ key = keyList[i];
+ node = tree.getNodeByKey(key);
+ if (node) {
+ if (mode && node.isUndefined()) {
+ foundOne = true;
+ tree.debug(
+ "_loadLazyNodes: " + node + " is lazy: loading..."
+ );
+ if (mode === "expand") {
+ deferredList.push(node.setExpanded(true, expandOpts));
+ } else {
+ deferredList.push(node.load());
+ }
+ } else {
+ tree.debug("_loadLazyNodes: " + node + " already loaded.");
+ node.setExpanded(true, expandOpts);
+ }
+ } else {
+ missingKeyList.push(key);
+ tree.debug("_loadLazyNodes: " + node + " was not yet found.");
+ }
+ }
+
+ $.when.apply($, deferredList).always(function () {
+ // All lazy-expands have finished
+ if (foundOne && missingKeyList.length > 0) {
+ // If we read new nodes from server, try to resolve yet-missing keys
+ _loadLazyNodes(tree, local, missingKeyList, mode, dfd);
+ } else {
+ if (missingKeyList.length) {
+ tree.warn(
+ "_loadLazyNodes: could not load those keys: ",
+ missingKeyList
+ );
+ for (i = 0, l = missingKeyList.length; i < l; i++) {
+ key = keyList[i];
+ local._appendKey(EXPANDED, keyList[i], false);
+ }
+ }
+ dfd.resolve();
+ }
+ });
+ return dfd;
+ }
+
+ /**
+ * [ext-persist] Remove persistence data of the given type(s).
+ * Called like
+ * $.ui.fancytree.getTree("#tree").clearCookies("active expanded focus selected");
+ *
+ * @alias Fancytree#clearPersistData
+ * @requires jquery.fancytree.persist.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.clearPersistData = function (
+ types
+ ) {
+ var local = this.ext.persist,
+ prefix = local.cookiePrefix;
+
+ types = types || "active expanded focus selected";
+ if (types.indexOf(ACTIVE) >= 0) {
+ local._data(prefix + ACTIVE, null);
+ }
+ if (types.indexOf(EXPANDED) >= 0) {
+ local._data(prefix + EXPANDED, null);
+ }
+ if (types.indexOf(FOCUS) >= 0) {
+ local._data(prefix + FOCUS, null);
+ }
+ if (types.indexOf(SELECTED) >= 0) {
+ local._data(prefix + SELECTED, null);
+ }
+ };
+
+ $.ui.fancytree._FancytreeClass.prototype.clearCookies = function (types) {
+ this.warn(
+ "'tree.clearCookies()' is deprecated since v2.27.0: use 'clearPersistData()' instead."
+ );
+ return this.clearPersistData(types);
+ };
+
+ /**
+ * [ext-persist] Return persistence information from cookies
+ *
+ * Called like
+ * $.ui.fancytree.getTree("#tree").getPersistData();
+ *
+ * @alias Fancytree#getPersistData
+ * @requires jquery.fancytree.persist.js
+ */
+ $.ui.fancytree._FancytreeClass.prototype.getPersistData = function () {
+ var local = this.ext.persist,
+ prefix = local.cookiePrefix,
+ delim = local.cookieDelimiter,
+ res = {};
+
+ res[ACTIVE] = local._data(prefix + ACTIVE);
+ res[EXPANDED] = (local._data(prefix + EXPANDED) || "").split(delim);
+ res[SELECTED] = (local._data(prefix + SELECTED) || "").split(delim);
+ res[FOCUS] = local._data(prefix + FOCUS);
+ return res;
+ };
+
+ /******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "persist",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ cookieDelimiter: "~",
+ cookiePrefix: undefined, // 'fancytree-<treeId>-' by default
+ cookie: {
+ raw: false,
+ expires: "",
+ path: "",
+ domain: "",
+ secure: false,
+ },
+ expandLazy: false, // true: recursively expand and load lazy nodes
+ expandOpts: undefined, // optional `opts` argument passed to setExpanded()
+ fireActivate: true, // false: suppress `activate` event after active node was restored
+ overrideSource: true, // true: cookie takes precedence over `source` data attributes.
+ store: "auto", // 'cookie': force cookie, 'local': force localStore, 'session': force sessionStore
+ types: "active expanded focus selected",
+ },
+
+ /* Generic read/write string data to cookie, sessionStorage or localStorage. */
+ _data: function (key, value) {
+ var store = this._local.store;
+
+ if (value === undefined) {
+ return store.get.call(this, key);
+ } else if (value === null) {
+ store.remove.call(this, key);
+ } else {
+ store.set.call(this, key, value);
+ }
+ },
+
+ /* Append `key` to a cookie. */
+ _appendKey: function (type, key, flag) {
+ key = "" + key; // #90
+ var local = this._local,
+ instOpts = this.options.persist,
+ delim = instOpts.cookieDelimiter,
+ cookieName = local.cookiePrefix + type,
+ data = local._data(cookieName),
+ keyList = data ? data.split(delim) : [],
+ idx = $.inArray(key, keyList);
+ // Remove, even if we add a key, so the key is always the last entry
+ if (idx >= 0) {
+ keyList.splice(idx, 1);
+ }
+ // Append key to cookie
+ if (flag) {
+ keyList.push(key);
+ }
+ local._data(cookieName, keyList.join(delim));
+ },
+
+ treeInit: function (ctx) {
+ var tree = ctx.tree,
+ opts = ctx.options,
+ local = this._local,
+ instOpts = this.options.persist;
+
+ // // For 'auto' or 'cookie' mode, the cookie plugin must be available
+ // _assert((instOpts.store !== "auto" && instOpts.store !== "cookie") || cookieStore,
+ // "Missing required plugin for 'persist' extension: js.cookie.js or jquery.cookie.js");
+
+ local.cookiePrefix =
+ instOpts.cookiePrefix || "fancytree-" + tree._id + "-";
+ local.storeActive = instOpts.types.indexOf(ACTIVE) >= 0;
+ local.storeExpanded = instOpts.types.indexOf(EXPANDED) >= 0;
+ local.storeSelected = instOpts.types.indexOf(SELECTED) >= 0;
+ local.storeFocus = instOpts.types.indexOf(FOCUS) >= 0;
+ local.store = null;
+
+ if (instOpts.store === "auto") {
+ instOpts.store = localStorageStore ? "local" : "cookie";
+ }
+ if ($.isPlainObject(instOpts.store)) {
+ local.store = instOpts.store;
+ } else if (instOpts.store === "cookie") {
+ local.store = cookieStore;
+ } else if (instOpts.store === "local") {
+ local.store =
+ instOpts.store === "local"
+ ? localStorageStore
+ : sessionStorageStore;
+ } else if (instOpts.store === "session") {
+ local.store =
+ instOpts.store === "local"
+ ? localStorageStore
+ : sessionStorageStore;
+ }
+ _assert(local.store, "Need a valid store.");
+
+ // Bind init-handler to apply cookie state
+ tree.$div.on("fancytreeinit", function (event) {
+ if (
+ tree._triggerTreeEvent("beforeRestore", null, {}) === false
+ ) {
+ return;
+ }
+
+ var cookie,
+ dfd,
+ i,
+ keyList,
+ node,
+ prevFocus = local._data(local.cookiePrefix + FOCUS), // record this before node.setActive() overrides it;
+ noEvents = instOpts.fireActivate === false;
+
+ // tree.debug("document.cookie:", document.cookie);
+
+ cookie = local._data(local.cookiePrefix + EXPANDED);
+ keyList = cookie && cookie.split(instOpts.cookieDelimiter);
+
+ if (local.storeExpanded) {
+ // Recursively load nested lazy nodes if expandLazy is 'expand' or 'load'
+ // Also remove expand-cookies for unmatched nodes
+ dfd = _loadLazyNodes(
+ tree,
+ local,
+ keyList,
+ instOpts.expandLazy ? "expand" : false,
+ null
+ );
+ } else {
+ // nothing to do
+ dfd = new $.Deferred().resolve();
+ }
+
+ dfd.done(function () {
+ if (local.storeSelected) {
+ cookie = local._data(local.cookiePrefix + SELECTED);
+ if (cookie) {
+ keyList = cookie.split(instOpts.cookieDelimiter);
+ for (i = 0; i < keyList.length; i++) {
+ node = tree.getNodeByKey(keyList[i]);
+ if (node) {
+ if (
+ node.selected === undefined ||
+ (instOpts.overrideSource &&
+ node.selected === false)
+ ) {
+ // node.setSelected();
+ node.selected = true;
+ node.renderStatus();
+ }
+ } else {
+ // node is no longer member of the tree: remove from cookie also
+ local._appendKey(
+ SELECTED,
+ keyList[i],
+ false
+ );
+ }
+ }
+ }
+ // In selectMode 3 we have to fix the child nodes, since we
+ // only stored the selected *top* nodes
+ if (tree.options.selectMode === 3) {
+ tree.visit(function (n) {
+ if (n.selected) {
+ n.fixSelection3AfterClick();
+ return "skip";
+ }
+ });
+ }
+ }
+ if (local.storeActive) {
+ cookie = local._data(local.cookiePrefix + ACTIVE);
+ if (
+ cookie &&
+ (opts.persist.overrideSource || !tree.activeNode)
+ ) {
+ node = tree.getNodeByKey(cookie);
+ if (node) {
+ node.debug("persist: set active", cookie);
+ // We only want to set the focus if the container
+ // had the keyboard focus before
+ node.setActive(true, {
+ noFocus: true,
+ noEvents: noEvents,
+ });
+ }
+ }
+ }
+ if (local.storeFocus && prevFocus) {
+ node = tree.getNodeByKey(prevFocus);
+ if (node) {
+ // node.debug("persist: set focus", cookie);
+ if (tree.options.titlesTabbable) {
+ $(node.span).find(".fancytree-title").focus();
+ } else {
+ $(tree.$container).focus();
+ }
+ // node.setFocus();
+ }
+ }
+ tree._triggerTreeEvent("restore", null, {});
+ });
+ });
+ // Init the tree
+ return this._superApply(arguments);
+ },
+ nodeSetActive: function (ctx, flag, callOpts) {
+ var res,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeActive) {
+ local._data(
+ local.cookiePrefix + ACTIVE,
+ this.activeNode ? this.activeNode.key : null
+ );
+ }
+ return res;
+ },
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ var res,
+ node = ctx.node,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeExpanded) {
+ local._appendKey(EXPANDED, node.key, flag);
+ }
+ return res;
+ },
+ nodeSetFocus: function (ctx, flag) {
+ var res,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeFocus) {
+ local._data(
+ local.cookiePrefix + FOCUS,
+ this.focusNode ? this.focusNode.key : null
+ );
+ }
+ return res;
+ },
+ nodeSetSelected: function (ctx, flag, callOpts) {
+ var res,
+ selNodes,
+ tree = ctx.tree,
+ node = ctx.node,
+ local = this._local;
+
+ flag = flag !== false;
+ res = this._superApply(arguments);
+
+ if (local.storeSelected) {
+ if (tree.options.selectMode === 3) {
+ // In selectMode 3 we only store the the selected *top* nodes.
+ // De-selecting a node may also de-select some parents, so we
+ // calculate the current status again
+ selNodes = $.map(tree.getSelectedNodes(true), function (n) {
+ return n.key;
+ });
+ selNodes = selNodes.join(
+ ctx.options.persist.cookieDelimiter
+ );
+ local._data(local.cookiePrefix + SELECTED, selNodes);
+ } else {
+ // beforeSelect can prevent the change - flag doesn't reflect the node.selected state
+ local._appendKey(SELECTED, node.key, node.selected);
+ }
+ }
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.table.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.table.js
new file mode 100644
index 0000000..ade8e11
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.table.js
@@ -0,0 +1,544 @@
+/*!
+ * jquery.fancytree.table.js
+ *
+ * Render tree as table (aka 'tree grid', 'table tree').
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /******************************************************************************
+ * Private functions and variables
+ */
+ var _assert = $.ui.fancytree.assert;
+
+ function insertFirstChild(referenceNode, newNode) {
+ referenceNode.insertBefore(newNode, referenceNode.firstChild);
+ }
+
+ function insertSiblingAfter(referenceNode, newNode) {
+ referenceNode.parentNode.insertBefore(
+ newNode,
+ referenceNode.nextSibling
+ );
+ }
+
+ /* Show/hide all rows that are structural descendants of `parent`. */
+ function setChildRowVisibility(parent, flag) {
+ parent.visit(function (node) {
+ var tr = node.tr;
+ // currentFlag = node.hide ? false : flag; // fix for ext-filter
+ if (tr) {
+ tr.style.display = node.hide || !flag ? "none" : "";
+ }
+ if (!node.expanded) {
+ return "skip";
+ }
+ });
+ }
+
+ /* Find node that is rendered in previous row. */
+ function findPrevRowNode(node) {
+ var i,
+ last,
+ prev,
+ parent = node.parent,
+ siblings = parent ? parent.children : null;
+
+ if (siblings && siblings.length > 1 && siblings[0] !== node) {
+ // use the lowest descendant of the preceeding sibling
+ i = $.inArray(node, siblings);
+ prev = siblings[i - 1];
+ _assert(prev.tr);
+ // descend to lowest child (with a <tr> tag)
+ while (prev.children && prev.children.length) {
+ last = prev.children[prev.children.length - 1];
+ if (!last.tr) {
+ break;
+ }
+ prev = last;
+ }
+ } else {
+ // if there is no preceding sibling, use the direct parent
+ prev = parent;
+ }
+ return prev;
+ }
+
+ $.ui.fancytree.registerExtension({
+ name: "table",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx)
+ indentation: 16, // indent every node level by 16px
+ mergeStatusColumns: true, // display 'nodata', 'loading', 'error' centered in a single, merged TR
+ nodeColumnIdx: 0, // render node expander, icon, and title to this column (default: #0)
+ },
+ // Overide virtual methods for this extension.
+ // `this` : is this extension object
+ // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
+ treeInit: function (ctx) {
+ var i,
+ n,
+ $row,
+ $tbody,
+ tree = ctx.tree,
+ opts = ctx.options,
+ tableOpts = opts.table,
+ $table = tree.widget.element;
+
+ if (tableOpts.customStatus != null) {
+ if (opts.renderStatusColumns == null) {
+ tree.warn(
+ "The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' instead."
+ );
+ opts.renderStatusColumns = tableOpts.customStatus;
+ } else {
+ $.error(
+ "The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' only instead."
+ );
+ }
+ }
+ if (opts.renderStatusColumns) {
+ if (opts.renderStatusColumns === true) {
+ opts.renderStatusColumns = opts.renderColumns;
+ // } else if( opts.renderStatusColumns === "wide" ) {
+ // opts.renderStatusColumns = _renderStatusNodeWide;
+ }
+ }
+
+ $table.addClass("fancytree-container fancytree-ext-table");
+ $tbody = $table.find(">tbody");
+ if (!$tbody.length) {
+ // TODO: not sure if we can rely on browsers to insert missing <tbody> before <tr>s:
+ if ($table.find(">tr").length) {
+ $.error(
+ "Expected table > tbody > tr. If you see this please open an issue."
+ );
+ }
+ $tbody = $("<tbody>").appendTo($table);
+ }
+
+ tree.tbody = $tbody[0];
+
+ // Prepare row templates:
+ // Determine column count from table header if any
+ tree.columnCount = $("thead >tr", $table)
+ .last()
+ .find(">th", $table).length;
+ // Read TR templates from tbody if any
+ $row = $tbody.children("tr").first();
+ if ($row.length) {
+ n = $row.children("td").length;
+ if (tree.columnCount && n !== tree.columnCount) {
+ tree.warn(
+ "Column count mismatch between thead (" +
+ tree.columnCount +
+ ") and tbody (" +
+ n +
+ "): using tbody."
+ );
+ tree.columnCount = n;
+ }
+ $row = $row.clone();
+ } else {
+ // Only thead is defined: create default row markup
+ _assert(
+ tree.columnCount >= 1,
+ "Need either <thead> or <tbody> with <td> elements to determine column count."
+ );
+ $row = $("<tr />");
+ for (i = 0; i < tree.columnCount; i++) {
+ $row.append("<td />");
+ }
+ }
+ $row.find(">td")
+ .eq(tableOpts.nodeColumnIdx)
+ .html("<span class='fancytree-node' />");
+ if (opts.aria) {
+ $row.attr("role", "row");
+ $row.find("td").attr("role", "gridcell");
+ }
+ tree.rowFragment = document.createDocumentFragment();
+ tree.rowFragment.appendChild($row.get(0));
+
+ // // If tbody contains a second row, use this as status node template
+ // $row = $tbody.children("tr").eq(1);
+ // if( $row.length === 0 ) {
+ // tree.statusRowFragment = tree.rowFragment;
+ // } else {
+ // $row = $row.clone();
+ // tree.statusRowFragment = document.createDocumentFragment();
+ // tree.statusRowFragment.appendChild($row.get(0));
+ // }
+ //
+ $tbody.empty();
+
+ // Make sure that status classes are set on the node's <tr> elements
+ tree.statusClassPropName = "tr";
+ tree.ariaPropName = "tr";
+ this.nodeContainerAttrName = "tr";
+
+ // #489: make sure $container is set to <table>, even if ext-dnd is listed before ext-table
+ tree.$container = $table;
+
+ this._superApply(arguments);
+
+ // standard Fancytree created a root UL
+ $(tree.rootNode.ul).remove();
+ tree.rootNode.ul = null;
+
+ // Add container to the TAB chain
+ // #577: Allow to set tabindex to "0", "-1" and ""
+ this.$container.attr("tabindex", opts.tabindex);
+ // this.$container.attr("tabindex", opts.tabbable ? "0" : "-1");
+ if (opts.aria) {
+ tree.$container
+ .attr("role", "treegrid")
+ .attr("aria-readonly", true);
+ }
+ },
+ nodeRemoveChildMarkup: function (ctx) {
+ var node = ctx.node;
+ // node.debug("nodeRemoveChildMarkup()");
+ node.visit(function (n) {
+ if (n.tr) {
+ $(n.tr).remove();
+ n.tr = null;
+ }
+ });
+ },
+ nodeRemoveMarkup: function (ctx) {
+ var node = ctx.node;
+ // node.debug("nodeRemoveMarkup()");
+ if (node.tr) {
+ $(node.tr).remove();
+ node.tr = null;
+ }
+ this.nodeRemoveChildMarkup(ctx);
+ },
+ /* Override standard render. */
+ nodeRender: function (ctx, force, deep, collapsed, _recursive) {
+ var children,
+ firstTr,
+ i,
+ l,
+ newRow,
+ prevNode,
+ prevTr,
+ subCtx,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = ctx.options,
+ isRootNode = !node.parent;
+
+ if (tree._enableUpdate === false) {
+ // $.ui.fancytree.debug("*** nodeRender _enableUpdate: false");
+ return;
+ }
+ if (!_recursive) {
+ ctx.hasCollapsedParents = node.parent && !node.parent.expanded;
+ }
+ // $.ui.fancytree.debug("*** nodeRender " + node + ", isRoot=" + isRootNode, "tr=" + node.tr, "hcp=" + ctx.hasCollapsedParents, "parent.tr=" + (node.parent && node.parent.tr));
+ if (!isRootNode) {
+ if (node.tr && force) {
+ this.nodeRemoveMarkup(ctx);
+ }
+ if (node.tr) {
+ if (force) {
+ // Set icon, link, and title (normally this is only required on initial render)
+ this.nodeRenderTitle(ctx); // triggers renderColumns()
+ } else {
+ // Update element classes according to node state
+ this.nodeRenderStatus(ctx);
+ }
+ } else {
+ if (ctx.hasCollapsedParents && !deep) {
+ // #166: we assume that the parent will be (recursively) rendered
+ // later anyway.
+ // node.debug("nodeRender ignored due to unrendered parent");
+ return;
+ }
+ // Create new <tr> after previous row
+ // if( node.isStatusNode() ) {
+ // newRow = tree.statusRowFragment.firstChild.cloneNode(true);
+ // } else {
+ newRow = tree.rowFragment.firstChild.cloneNode(true);
+ // }
+ prevNode = findPrevRowNode(node);
+ // $.ui.fancytree.debug("*** nodeRender " + node + ": prev: " + prevNode.key);
+ _assert(prevNode);
+ if (collapsed === true && _recursive) {
+ // hide all child rows, so we can use an animation to show it later
+ newRow.style.display = "none";
+ } else if (deep && ctx.hasCollapsedParents) {
+ // also hide this row if deep === true but any parent is collapsed
+ newRow.style.display = "none";
+ // newRow.style.color = "red";
+ }
+ if (prevNode.tr) {
+ insertSiblingAfter(prevNode.tr, newRow);
+ } else {
+ _assert(
+ !prevNode.parent,
+ "prev. row must have a tr, or be system root"
+ );
+ // tree.tbody.appendChild(newRow);
+ insertFirstChild(tree.tbody, newRow); // #675
+ }
+ node.tr = newRow;
+ if (node.key && opts.generateIds) {
+ node.tr.id = opts.idPrefix + node.key;
+ }
+ node.tr.ftnode = node;
+ // if(opts.aria){
+ // $(node.tr).attr("aria-labelledby", "ftal_" + opts.idPrefix + node.key);
+ // }
+ node.span = $("span.fancytree-node", node.tr).get(0);
+ // Set icon, link, and title (normally this is only required on initial render)
+ this.nodeRenderTitle(ctx);
+ // Allow tweaking, binding, after node was created for the first time
+ // tree._triggerNodeEvent("createNode", ctx);
+ if (opts.createNode) {
+ opts.createNode.call(tree, { type: "createNode" }, ctx);
+ }
+ }
+ }
+ // Allow tweaking after node state was rendered
+ // tree._triggerNodeEvent("renderNode", ctx);
+ if (opts.renderNode) {
+ opts.renderNode.call(tree, { type: "renderNode" }, ctx);
+ }
+ // Visit child nodes
+ // Add child markup
+ children = node.children;
+ if (children && (isRootNode || deep || node.expanded)) {
+ for (i = 0, l = children.length; i < l; i++) {
+ subCtx = $.extend({}, ctx, { node: children[i] });
+ subCtx.hasCollapsedParents =
+ subCtx.hasCollapsedParents || !node.expanded;
+ this.nodeRender(subCtx, force, deep, collapsed, true);
+ }
+ }
+ // Make sure, that <tr> order matches node.children order.
+ if (children && !_recursive) {
+ // we only have to do it once, for the root branch
+ prevTr = node.tr || null;
+ firstTr = tree.tbody.firstChild;
+ // Iterate over all descendants
+ node.visit(function (n) {
+ if (n.tr) {
+ if (
+ !n.parent.expanded &&
+ n.tr.style.display !== "none"
+ ) {
+ // fix after a node was dropped over a collapsed
+ n.tr.style.display = "none";
+ setChildRowVisibility(n, false);
+ }
+ if (n.tr.previousSibling !== prevTr) {
+ node.debug("_fixOrder: mismatch at node: " + n);
+ var nextTr = prevTr ? prevTr.nextSibling : firstTr;
+ tree.tbody.insertBefore(n.tr, nextTr);
+ }
+ prevTr = n.tr;
+ }
+ });
+ }
+ // Update element classes according to node state
+ // if(!isRootNode){
+ // this.nodeRenderStatus(ctx);
+ // }
+ },
+ nodeRenderTitle: function (ctx, title) {
+ var $cb,
+ res,
+ tree = ctx.tree,
+ node = ctx.node,
+ opts = ctx.options,
+ isStatusNode = node.isStatusNode();
+
+ res = this._super(ctx, title);
+
+ if (node.isRootNode()) {
+ return res;
+ }
+ // Move checkbox to custom column
+ if (
+ opts.checkbox &&
+ !isStatusNode &&
+ opts.table.checkboxColumnIdx != null
+ ) {
+ $cb = $("span.fancytree-checkbox", node.span); //.detach();
+ $(node.tr)
+ .find("td")
+ .eq(+opts.table.checkboxColumnIdx)
+ .html($cb);
+ }
+ // Update element classes according to node state
+ this.nodeRenderStatus(ctx);
+
+ if (isStatusNode) {
+ if (opts.renderStatusColumns) {
+ // Let user code write column content
+ opts.renderStatusColumns.call(
+ tree,
+ { type: "renderStatusColumns" },
+ ctx
+ );
+ } else if (opts.table.mergeStatusColumns && node.isTopLevel()) {
+ $(node.tr)
+ .find(">td")
+ .eq(0)
+ .prop("colspan", tree.columnCount)
+ .text(node.title)
+ .addClass("fancytree-status-merged")
+ .nextAll()
+ .remove();
+ } // else: default rendering for status node: leave other cells empty
+ } else if (opts.renderColumns) {
+ opts.renderColumns.call(tree, { type: "renderColumns" }, ctx);
+ }
+ return res;
+ },
+ nodeRenderStatus: function (ctx) {
+ var indent,
+ node = ctx.node,
+ opts = ctx.options;
+
+ this._super(ctx);
+
+ $(node.tr).removeClass("fancytree-node");
+ // indent
+ indent = (node.getLevel() - 1) * opts.table.indentation;
+ if (opts.rtl) {
+ $(node.span).css({ paddingRight: indent + "px" });
+ } else {
+ $(node.span).css({ paddingLeft: indent + "px" });
+ }
+ },
+ /* Expand node, return Deferred.promise. */
+ nodeSetExpanded: function (ctx, flag, callOpts) {
+ // flag defaults to true
+ flag = flag !== false;
+
+ if ((ctx.node.expanded && flag) || (!ctx.node.expanded && !flag)) {
+ // Expanded state isn't changed - just call base implementation
+ return this._superApply(arguments);
+ }
+
+ var dfd = new $.Deferred(),
+ subOpts = $.extend({}, callOpts, {
+ noEvents: true,
+ noAnimation: true,
+ });
+
+ callOpts = callOpts || {};
+
+ function _afterExpand(ok, args) {
+ // ctx.tree.info("ok:" + ok, args);
+ if (ok) {
+ // #1108 minExpandLevel: 2 together with table extension does not work
+ // don't call when 'ok' is false:
+ setChildRowVisibility(ctx.node, flag);
+ if (
+ flag &&
+ ctx.options.autoScroll &&
+ !callOpts.noAnimation &&
+ ctx.node.hasChildren()
+ ) {
+ // Scroll down to last child, but keep current node visible
+ ctx.node
+ .getLastChild()
+ .scrollIntoView(true, { topNode: ctx.node })
+ .always(function () {
+ if (!callOpts.noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.resolveWith(ctx.node);
+ });
+ } else {
+ if (!callOpts.noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.resolveWith(ctx.node);
+ }
+ } else {
+ if (!callOpts.noEvents) {
+ ctx.tree._triggerNodeEvent(
+ flag ? "expand" : "collapse",
+ ctx
+ );
+ }
+ dfd.rejectWith(ctx.node);
+ }
+ }
+ // Call base-expand with disabled events and animation
+ this._super(ctx, flag, subOpts)
+ .done(function () {
+ _afterExpand(true, arguments);
+ })
+ .fail(function () {
+ _afterExpand(false, arguments);
+ });
+ return dfd.promise();
+ },
+ nodeSetStatus: function (ctx, status, message, details) {
+ if (status === "ok") {
+ var node = ctx.node,
+ firstChild = node.children ? node.children[0] : null;
+ if (firstChild && firstChild.isStatusNode()) {
+ $(firstChild.tr).remove();
+ }
+ }
+ return this._superApply(arguments);
+ },
+ treeClear: function (ctx) {
+ this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode));
+ return this._superApply(arguments);
+ },
+ treeDestroy: function (ctx) {
+ this.$container.find("tbody").empty();
+ if (this.$source) {
+ this.$source.removeClass("fancytree-helper-hidden");
+ }
+ return this._superApply(arguments);
+ },
+ /*,
+ treeSetFocus: function(ctx, flag) {
+// alert("treeSetFocus" + ctx.tree.$container);
+ ctx.tree.$container.focus();
+ $.ui.fancytree.focusTree = ctx.tree;
+ }*/
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.themeroller.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.themeroller.js
new file mode 100644
index 0000000..bb2a443
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.themeroller.js
@@ -0,0 +1,125 @@
+/*!
+ * jquery.fancytree.themeroller.js
+ *
+ * Enable jQuery UI ThemeRoller styles.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * @see http://jqueryui.com/themeroller/
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "themeroller",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ activeClass: "ui-state-active", // Class added to active node
+ // activeClass: "ui-state-highlight",
+ addClass: "ui-corner-all", // Class added to all nodes
+ focusClass: "ui-state-focus", // Class added to focused node
+ hoverClass: "ui-state-hover", // Class added to hovered node
+ selectedClass: "ui-state-highlight", // Class added to selected nodes
+ // selectedClass: "ui-state-active"
+ },
+
+ treeInit: function (ctx) {
+ var $el = ctx.widget.element,
+ opts = ctx.options.themeroller;
+
+ this._superApply(arguments);
+
+ if ($el[0].nodeName === "TABLE") {
+ $el.addClass("ui-widget ui-corner-all");
+ $el.find(">thead tr").addClass("ui-widget-header");
+ $el.find(">tbody").addClass("ui-widget-conent");
+ } else {
+ $el.addClass("ui-widget ui-widget-content ui-corner-all");
+ }
+
+ $el.on(
+ "mouseenter mouseleave",
+ ".fancytree-node",
+ function (event) {
+ var node = $.ui.fancytree.getNode(event.target),
+ flag = event.type === "mouseenter";
+
+ $(node.tr ? node.tr : node.span).toggleClass(
+ opts.hoverClass + " " + opts.addClass,
+ flag
+ );
+ }
+ );
+ },
+ treeDestroy: function (ctx) {
+ this._superApply(arguments);
+ ctx.widget.element.removeClass(
+ "ui-widget ui-widget-content ui-corner-all"
+ );
+ },
+ nodeRenderStatus: function (ctx) {
+ var classes = {},
+ node = ctx.node,
+ $el = $(node.tr ? node.tr : node.span),
+ opts = ctx.options.themeroller;
+
+ this._super(ctx);
+ /*
+ .ui-state-highlight: Class to be applied to highlighted or selected elements. Applies "highlight" container styles to an element and its child text, links, and icons.
+ .ui-state-error: Class to be applied to error messaging container elements. Applies "error" container styles to an element and its child text, links, and icons.
+ .ui-state-error-text: An additional class that applies just the error text color without background. Can be used on form labels for instance. Also applies error icon color to child icons.
+
+ .ui-state-default: Class to be applied to clickable button-like elements. Applies "clickable default" container styles to an element and its child text, links, and icons.
+ .ui-state-hover: Class to be applied on mouseover to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+ .ui-state-focus: Class to be applied on keyboard focus to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
+ .ui-state-active: Class to be applied on mousedown to clickable button-like elements. Applies "clickable active" container styles to an element and its child text, links, and icons.
+*/
+ // Set ui-state-* class (handle the case that the same class is assigned
+ // to different states)
+ classes[opts.activeClass] = false;
+ classes[opts.focusClass] = false;
+ classes[opts.selectedClass] = false;
+ if (node.isActive()) {
+ classes[opts.activeClass] = true;
+ }
+ if (node.hasFocus()) {
+ classes[opts.focusClass] = true;
+ }
+ // activeClass takes precedence before selectedClass:
+ if (node.isSelected() && !node.isActive()) {
+ classes[opts.selectedClass] = true;
+ }
+ $el.toggleClass(opts.activeClass, classes[opts.activeClass]);
+ $el.toggleClass(opts.focusClass, classes[opts.focusClass]);
+ $el.toggleClass(opts.selectedClass, classes[opts.selectedClass]);
+ // Additional classes (e.g. 'ui-corner-all')
+ $el.addClass(opts.addClass);
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.ui-deps.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.ui-deps.js
new file mode 100644
index 0000000..ca0a1b9
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.ui-deps.js
@@ -0,0 +1,1449 @@
+/*! jQuery UI - v1.13.2 - 2022-08-16
+* http://jqueryui.com
+* Includes: widget.js, position.js, jquery-patch.js, keycode.js, scroll-parent.js, unique-id.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+( function( factory ) {
+ "use strict";
+
+ if ( typeof define === "function" && define.amd ) {
+
+ // AMD. Register as an anonymous module.
+ define( [ "jquery" ], factory );
+ } else {
+
+ // Browser globals
+ factory( jQuery );
+ }
+} )( function( $ ) {
+"use strict";
+
+$.ui = $.ui || {};
+
+var version = $.ui.version = "1.13.2";
+
+
+/*!
+ * jQuery UI Widget 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+//>>label: Widget
+//>>group: Core
+//>>description: Provides a factory for creating stateful widgets with a common API.
+//>>docs: http://api.jqueryui.com/jQuery.widget/
+//>>demos: http://jqueryui.com/widget/
+
+
+var widgetUuid = 0;
+var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
+var widgetSlice = Array.prototype.slice;
+
+$.cleanData = $.cleanData || ( function( orig ) {
+ return function( elems ) {
+ var events, elem, i;
+ for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
+
+ // Only trigger remove when necessary to save time
+ events = $._data( elem, "events" );
+ if ( events && events.remove ) {
+ $( elem ).triggerHandler( "remove" );
+ }
+ }
+ orig( elems );
+ };
+} )( $.cleanData );
+
+$.widget = $.widget || function( name, base, prototype ) {
+ var existingConstructor, constructor, basePrototype;
+
+ // ProxiedPrototype allows the provided prototype to remain unmodified
+ // so that it can be used as a mixin for multiple widgets (#8876)
+ var proxiedPrototype = {};
+
+ var namespace = name.split( "." )[ 0 ];
+ name = name.split( "." )[ 1 ];
+ var fullName = namespace + "-" + name;
+
+ if ( !prototype ) {
+ prototype = base;
+ base = $.Widget;
+ }
+
+ if ( Array.isArray( prototype ) ) {
+ prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
+ }
+
+ // Create selector for plugin
+ $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
+ return !!$.data( elem, fullName );
+ };
+
+ $[ namespace ] = $[ namespace ] || {};
+ existingConstructor = $[ namespace ][ name ];
+ constructor = $[ namespace ][ name ] = function( options, element ) {
+
+ // Allow instantiation without "new" keyword
+ if ( !this || !this._createWidget ) {
+ return new constructor( options, element );
+ }
+
+ // Allow instantiation without initializing for simple inheritance
+ // must use "new" keyword (the code above always passes args)
+ if ( arguments.length ) {
+ this._createWidget( options, element );
+ }
+ };
+
+ // Extend with the existing constructor to carry over any static properties
+ $.extend( constructor, existingConstructor, {
+ version: prototype.version,
+
+ // Copy the object used to create the prototype in case we need to
+ // redefine the widget later
+ _proto: $.extend( {}, prototype ),
+
+ // Track widgets that inherit from this widget in case this widget is
+ // redefined after a widget inherits from it
+ _childConstructors: []
+ } );
+
+ basePrototype = new base();
+
+ // We need to make the options hash a property directly on the new instance
+ // otherwise we'll modify the options hash on the prototype that we're
+ // inheriting from
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
+ $.each( prototype, function( prop, value ) {
+ if ( typeof value !== "function" ) {
+ proxiedPrototype[ prop ] = value;
+ return;
+ }
+ proxiedPrototype[ prop ] = ( function() {
+ function _super() {
+ return base.prototype[ prop ].apply( this, arguments );
+ }
+
+ function _superApply( args ) {
+ return base.prototype[ prop ].apply( this, args );
+ }
+
+ return function() {
+ var __super = this._super;
+ var __superApply = this._superApply;
+ var returnValue;
+
+ this._super = _super;
+ this._superApply = _superApply;
+
+ returnValue = value.apply( this, arguments );
+
+ this._super = __super;
+ this._superApply = __superApply;
+
+ return returnValue;
+ };
+ } )();
+ } );
+ constructor.prototype = $.widget.extend( basePrototype, {
+
+ // TODO: remove support for widgetEventPrefix
+ // always use the name + a colon as the prefix, e.g., draggable:start
+ // don't prefix for widgets that aren't DOM-based
+ widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
+ }, proxiedPrototype, {
+ constructor: constructor,
+ namespace: namespace,
+ widgetName: name,
+ widgetFullName: fullName
+ } );
+
+ // If this widget is being redefined then we need to find all widgets that
+ // are inheriting from it and redefine all of them so that they inherit from
+ // the new version of this widget. We're essentially trying to replace one
+ // level in the prototype chain.
+ if ( existingConstructor ) {
+ $.each( existingConstructor._childConstructors, function( i, child ) {
+ var childPrototype = child.prototype;
+
+ // Redefine the child widget using the same prototype that was
+ // originally used, but inherit from the new version of the base
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
+ child._proto );
+ } );
+
+ // Remove the list of existing child constructors from the old constructor
+ // so the old child constructors can be garbage collected
+ delete existingConstructor._childConstructors;
+ } else {
+ base._childConstructors.push( constructor );
+ }
+
+ $.widget.bridge( name, constructor );
+
+ return constructor;
+};
+
+$.widget.extend = function( target ) {
+ var input = widgetSlice.call( arguments, 1 );
+ var inputIndex = 0;
+ var inputLength = input.length;
+ var key;
+ var value;
+
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
+ for ( key in input[ inputIndex ] ) {
+ value = input[ inputIndex ][ key ];
+ if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
+
+ // Clone objects
+ if ( $.isPlainObject( value ) ) {
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
+ $.widget.extend( {}, target[ key ], value ) :
+
+ // Don't extend strings, arrays, etc. with objects
+ $.widget.extend( {}, value );
+
+ // Copy everything else by reference
+ } else {
+ target[ key ] = value;
+ }
+ }
+ }
+ }
+ return target;
+};
+
+$.widget.bridge = function( name, object ) {
+ var fullName = object.prototype.widgetFullName || name;
+ $.fn[ name ] = function( options ) {
+ var isMethodCall = typeof options === "string";
+ var args = widgetSlice.call( arguments, 1 );
+ var returnValue = this;
+
+ if ( isMethodCall ) {
+
+ // If this is an empty collection, we need to have the instance method
+ // return undefined instead of the jQuery instance
+ if ( !this.length && options === "instance" ) {
+ returnValue = undefined;
+ } else {
+ this.each( function() {
+ var methodValue;
+ var instance = $.data( this, fullName );
+
+ if ( options === "instance" ) {
+ returnValue = instance;
+ return false;
+ }
+
+ if ( !instance ) {
+ return $.error( "cannot call methods on " + name +
+ " prior to initialization; " +
+ "attempted to call method '" + options + "'" );
+ }
+
+ if ( typeof instance[ options ] !== "function" ||
+ options.charAt( 0 ) === "_" ) {
+ return $.error( "no such method '" + options + "' for " + name +
+ " widget instance" );
+ }
+
+ methodValue = instance[ options ].apply( instance, args );
+
+ if ( methodValue !== instance && methodValue !== undefined ) {
+ returnValue = methodValue && methodValue.jquery ?
+ returnValue.pushStack( methodValue.get() ) :
+ methodValue;
+ return false;
+ }
+ } );
+ }
+ } else {
+
+ // Allow multiple hashes to be passed on init
+ if ( args.length ) {
+ options = $.widget.extend.apply( null, [ options ].concat( args ) );
+ }
+
+ this.each( function() {
+ var instance = $.data( this, fullName );
+ if ( instance ) {
+ instance.option( options || {} );
+ if ( instance._init ) {
+ instance._init();
+ }
+ } else {
+ $.data( this, fullName, new object( options, this ) );
+ }
+ } );
+ }
+
+ return returnValue;
+ };
+};
+
+$.Widget = $.Widget || function( /* options, element */ ) {};
+$.Widget._childConstructors = [];
+
+$.Widget.prototype = {
+ widgetName: "widget",
+ widgetEventPrefix: "",
+ defaultElement: "<div>",
+
+ options: {
+ classes: {},
+ disabled: false,
+
+ // Callbacks
+ create: null
+ },
+
+ _createWidget: function( options, element ) {
+ element = $( element || this.defaultElement || this )[ 0 ];
+ this.element = $( element );
+ this.uuid = widgetUuid++;
+ this.eventNamespace = "." + this.widgetName + this.uuid;
+
+ this.bindings = $();
+ this.hoverable = $();
+ this.focusable = $();
+ this.classesElementLookup = {};
+
+ if ( element !== this ) {
+ $.data( element, this.widgetFullName, this );
+ this._on( true, this.element, {
+ remove: function( event ) {
+ if ( event.target === element ) {
+ this.destroy();
+ }
+ }
+ } );
+ this.document = $( element.style ?
+
+ // Element within the document
+ element.ownerDocument :
+
+ // Element is window or document
+ element.document || element );
+ this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
+ }
+
+ this.options = $.widget.extend( {},
+ this.options,
+ this._getCreateOptions(),
+ options );
+
+ this._create();
+
+ if ( this.options.disabled ) {
+ this._setOptionDisabled( this.options.disabled );
+ }
+
+ this._trigger( "create", null, this._getCreateEventData() );
+ this._init();
+ },
+
+ _getCreateOptions: function() {
+ return {};
+ },
+
+ _getCreateEventData: $.noop,
+
+ _create: $.noop,
+
+ _init: $.noop,
+
+ destroy: function() {
+ var that = this;
+
+ this._destroy();
+ $.each( this.classesElementLookup, function( key, value ) {
+ that._removeClass( value, key );
+ } );
+
+ // We can probably remove the unbind calls in 2.0
+ // all event bindings should go through this._on()
+ this.element
+ .off( this.eventNamespace )
+ .removeData( this.widgetFullName );
+ this.widget()
+ .off( this.eventNamespace )
+ .removeAttr( "aria-disabled" );
+
+ // Clean up events and states
+ this.bindings.off( this.eventNamespace );
+ },
+
+ _destroy: $.noop,
+
+ widget: function() {
+ return this.element;
+ },
+
+ option: function( key, value ) {
+ var options = key;
+ var parts;
+ var curOption;
+ var i;
+
+ if ( arguments.length === 0 ) {
+
+ // Don't return a reference to the internal hash
+ return $.widget.extend( {}, this.options );
+ }
+
+ if ( typeof key === "string" ) {
+
+ // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
+ options = {};
+ parts = key.split( "." );
+ key = parts.shift();
+ if ( parts.length ) {
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
+ for ( i = 0; i < parts.length - 1; i++ ) {
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
+ curOption = curOption[ parts[ i ] ];
+ }
+ key = parts.pop();
+ if ( arguments.length === 1 ) {
+ return curOption[ key ] === undefined ? null : curOption[ key ];
+ }
+ curOption[ key ] = value;
+ } else {
+ if ( arguments.length === 1 ) {
+ return this.options[ key ] === undefined ? null : this.options[ key ];
+ }
+ options[ key ] = value;
+ }
+ }
+
+ this._setOptions( options );
+
+ return this;
+ },
+
+ _setOptions: function( options ) {
+ var key;
+
+ for ( key in options ) {
+ this._setOption( key, options[ key ] );
+ }
+
+ return this;
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "classes" ) {
+ this._setOptionClasses( value );
+ }
+
+ this.options[ key ] = value;
+
+ if ( key === "disabled" ) {
+ this._setOptionDisabled( value );
+ }
+
+ return this;
+ },
+
+ _setOptionClasses: function( value ) {
+ var classKey, elements, currentElements;
+
+ for ( classKey in value ) {
+ currentElements = this.classesElementLookup[ classKey ];
+ if ( value[ classKey ] === this.options.classes[ classKey ] ||
+ !currentElements ||
+ !currentElements.length ) {
+ continue;
+ }
+
+ // We are doing this to create a new jQuery object because the _removeClass() call
+ // on the next line is going to destroy the reference to the current elements being
+ // tracked. We need to save a copy of this collection so that we can add the new classes
+ // below.
+ elements = $( currentElements.get() );
+ this._removeClass( currentElements, classKey );
+
+ // We don't use _addClass() here, because that uses this.options.classes
+ // for generating the string of classes. We want to use the value passed in from
+ // _setOption(), this is the new value of the classes option which was passed to
+ // _setOption(). We pass this value directly to _classes().
+ elements.addClass( this._classes( {
+ element: elements,
+ keys: classKey,
+ classes: value,
+ add: true
+ } ) );
+ }
+ },
+
+ _setOptionDisabled: function( value ) {
+ this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
+
+ // If the widget is becoming disabled, then nothing is interactive
+ if ( value ) {
+ this._removeClass( this.hoverable, null, "ui-state-hover" );
+ this._removeClass( this.focusable, null, "ui-state-focus" );
+ }
+ },
+
+ enable: function() {
+ return this._setOptions( { disabled: false } );
+ },
+
+ disable: function() {
+ return this._setOptions( { disabled: true } );
+ },
+
+ _classes: function( options ) {
+ var full = [];
+ var that = this;
+
+ options = $.extend( {
+ element: this.element,
+ classes: this.options.classes || {}
+ }, options );
+
+ function bindRemoveEvent() {
+ var nodesToBind = [];
+
+ options.element.each( function( _, element ) {
+ var isTracked = $.map( that.classesElementLookup, function( elements ) {
+ return elements;
+ } )
+ .some( function( elements ) {
+ return elements.is( element );
+ } );
+
+ if ( !isTracked ) {
+ nodesToBind.push( element );
+ }
+ } );
+
+ that._on( $( nodesToBind ), {
+ remove: "_untrackClassesElement"
+ } );
+ }
+
+ function processClassString( classes, checkOption ) {
+ var current, i;
+ for ( i = 0; i < classes.length; i++ ) {
+ current = that.classesElementLookup[ classes[ i ] ] || $();
+ if ( options.add ) {
+ bindRemoveEvent();
+ current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
+ } else {
+ current = $( current.not( options.element ).get() );
+ }
+ that.classesElementLookup[ classes[ i ] ] = current;
+ full.push( classes[ i ] );
+ if ( checkOption && options.classes[ classes[ i ] ] ) {
+ full.push( options.classes[ classes[ i ] ] );
+ }
+ }
+ }
+
+ if ( options.keys ) {
+ processClassString( options.keys.match( /\S+/g ) || [], true );
+ }
+ if ( options.extra ) {
+ processClassString( options.extra.match( /\S+/g ) || [] );
+ }
+
+ return full.join( " " );
+ },
+
+ _untrackClassesElement: function( event ) {
+ var that = this;
+ $.each( that.classesElementLookup, function( key, value ) {
+ if ( $.inArray( event.target, value ) !== -1 ) {
+ that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
+ }
+ } );
+
+ this._off( $( event.target ) );
+ },
+
+ _removeClass: function( element, keys, extra ) {
+ return this._toggleClass( element, keys, extra, false );
+ },
+
+ _addClass: function( element, keys, extra ) {
+ return this._toggleClass( element, keys, extra, true );
+ },
+
+ _toggleClass: function( element, keys, extra, add ) {
+ add = ( typeof add === "boolean" ) ? add : extra;
+ var shift = ( typeof element === "string" || element === null ),
+ options = {
+ extra: shift ? keys : extra,
+ keys: shift ? element : keys,
+ element: shift ? this.element : element,
+ add: add
+ };
+ options.element.toggleClass( this._classes( options ), add );
+ return this;
+ },
+
+ _on: function( suppressDisabledCheck, element, handlers ) {
+ var delegateElement;
+ var instance = this;
+
+ // No suppressDisabledCheck flag, shuffle arguments
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
+ handlers = element;
+ element = suppressDisabledCheck;
+ suppressDisabledCheck = false;
+ }
+
+ // No element argument, shuffle and use this.element
+ if ( !handlers ) {
+ handlers = element;
+ element = this.element;
+ delegateElement = this.widget();
+ } else {
+ element = delegateElement = $( element );
+ this.bindings = this.bindings.add( element );
+ }
+
+ $.each( handlers, function( event, handler ) {
+ function handlerProxy() {
+
+ // Allow widgets to customize the disabled handling
+ // - disabled as an array instead of boolean
+ // - disabled class as method for disabling individual parts
+ if ( !suppressDisabledCheck &&
+ ( instance.options.disabled === true ||
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
+ return;
+ }
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+
+ // Copy the guid so direct unbinding works
+ if ( typeof handler !== "string" ) {
+ handlerProxy.guid = handler.guid =
+ handler.guid || handlerProxy.guid || $.guid++;
+ }
+
+ var match = event.match( /^([\w:-]*)\s*(.*)$/ );
+ var eventName = match[ 1 ] + instance.eventNamespace;
+ var selector = match[ 2 ];
+
+ if ( selector ) {
+ delegateElement.on( eventName, selector, handlerProxy );
+ } else {
+ element.on( eventName, handlerProxy );
+ }
+ } );
+ },
+
+ _off: function( element, eventName ) {
+ eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
+ this.eventNamespace;
+ element.off( eventName );
+
+ // Clear the stack to avoid memory leaks (#10056)
+ this.bindings = $( this.bindings.not( element ).get() );
+ this.focusable = $( this.focusable.not( element ).get() );
+ this.hoverable = $( this.hoverable.not( element ).get() );
+ },
+
+ _delay: function( handler, delay ) {
+ function handlerProxy() {
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+ var instance = this;
+ return setTimeout( handlerProxy, delay || 0 );
+ },
+
+ _hoverable: function( element ) {
+ this.hoverable = this.hoverable.add( element );
+ this._on( element, {
+ mouseenter: function( event ) {
+ this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
+ },
+ mouseleave: function( event ) {
+ this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
+ }
+ } );
+ },
+
+ _focusable: function( element ) {
+ this.focusable = this.focusable.add( element );
+ this._on( element, {
+ focusin: function( event ) {
+ this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
+ },
+ focusout: function( event ) {
+ this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
+ }
+ } );
+ },
+
+ _trigger: function( type, event, data ) {
+ var prop, orig;
+ var callback = this.options[ type ];
+
+ data = data || {};
+ event = $.Event( event );
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+
+ // The original event may come from any element
+ // so we need to reset the target on the new event
+ event.target = this.element[ 0 ];
+
+ // Copy original event properties over to the new event
+ orig = event.originalEvent;
+ if ( orig ) {
+ for ( prop in orig ) {
+ if ( !( prop in event ) ) {
+ event[ prop ] = orig[ prop ];
+ }
+ }
+ }
+
+ this.element.trigger( event, data );
+ return !( typeof callback === "function" &&
+ callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
+ event.isDefaultPrevented() );
+ }
+};
+
+$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
+ if ( typeof options === "string" ) {
+ options = { effect: options };
+ }
+
+ var hasOptions;
+ var effectName = !options ?
+ method :
+ options === true || typeof options === "number" ?
+ defaultEffect :
+ options.effect || defaultEffect;
+
+ options = options || {};
+ if ( typeof options === "number" ) {
+ options = { duration: options };
+ } else if ( options === true ) {
+ options = {};
+ }
+
+ hasOptions = !$.isEmptyObject( options );
+ options.complete = callback;
+
+ if ( options.delay ) {
+ element.delay( options.delay );
+ }
+
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
+ element[ method ]( options );
+ } else if ( effectName !== method && element[ effectName ] ) {
+ element[ effectName ]( options.duration, options.easing, callback );
+ } else {
+ element.queue( function( next ) {
+ $( this )[ method ]();
+ if ( callback ) {
+ callback.call( element[ 0 ] );
+ }
+ next();
+ } );
+ }
+ };
+} );
+
+var widget = $.widget;
+
+
+/*!
+ * jQuery UI Position 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/position/
+ */
+
+//>>label: Position
+//>>group: Core
+//>>description: Positions elements relative to other elements.
+//>>docs: http://api.jqueryui.com/position/
+//>>demos: http://jqueryui.com/position/
+
+
+( function() {
+var cachedScrollbarWidth,
+ max = Math.max,
+ abs = Math.abs,
+ rhorizontal = /left|center|right/,
+ rvertical = /top|center|bottom/,
+ roffset = /[\+\-]\d+(\.[\d]+)?%?/,
+ rposition = /^\w+/,
+ rpercent = /%$/,
+ _position = $.fn.position;
+
+function getOffsets( offsets, width, height ) {
+ return [
+ parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
+ parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
+ ];
+}
+
+function parseCss( element, property ) {
+ return parseInt( $.css( element, property ), 10 ) || 0;
+}
+
+function isWindow( obj ) {
+ return obj != null && obj === obj.window;
+}
+
+function getDimensions( elem ) {
+ var raw = elem[ 0 ];
+ if ( raw.nodeType === 9 ) {
+ return {
+ width: elem.width(),
+ height: elem.height(),
+ offset: { top: 0, left: 0 }
+ };
+ }
+ if ( isWindow( raw ) ) {
+ return {
+ width: elem.width(),
+ height: elem.height(),
+ offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
+ };
+ }
+ if ( raw.preventDefault ) {
+ return {
+ width: 0,
+ height: 0,
+ offset: { top: raw.pageY, left: raw.pageX }
+ };
+ }
+ return {
+ width: elem.outerWidth(),
+ height: elem.outerHeight(),
+ offset: elem.offset()
+ };
+}
+
+$.position = $.position || {
+ scrollbarWidth: function() {
+ if ( cachedScrollbarWidth !== undefined ) {
+ return cachedScrollbarWidth;
+ }
+ var w1, w2,
+ div = $( "<div style=" +
+ "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
+ "<div style='height:300px;width:auto;'></div></div>" ),
+ innerDiv = div.children()[ 0 ];
+
+ $( "body" ).append( div );
+ w1 = innerDiv.offsetWidth;
+ div.css( "overflow", "scroll" );
+
+ w2 = innerDiv.offsetWidth;
+
+ if ( w1 === w2 ) {
+ w2 = div[ 0 ].clientWidth;
+ }
+
+ div.remove();
+
+ return ( cachedScrollbarWidth = w1 - w2 );
+ },
+ getScrollInfo: function( within ) {
+ var overflowX = within.isWindow || within.isDocument ? "" :
+ within.element.css( "overflow-x" ),
+ overflowY = within.isWindow || within.isDocument ? "" :
+ within.element.css( "overflow-y" ),
+ hasOverflowX = overflowX === "scroll" ||
+ ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
+ hasOverflowY = overflowY === "scroll" ||
+ ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
+ return {
+ width: hasOverflowY ? $.position.scrollbarWidth() : 0,
+ height: hasOverflowX ? $.position.scrollbarWidth() : 0
+ };
+ },
+ getWithinInfo: function( element ) {
+ var withinElement = $( element || window ),
+ isElemWindow = isWindow( withinElement[ 0 ] ),
+ isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
+ hasOffset = !isElemWindow && !isDocument;
+ return {
+ element: withinElement,
+ isWindow: isElemWindow,
+ isDocument: isDocument,
+ offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
+ scrollLeft: withinElement.scrollLeft(),
+ scrollTop: withinElement.scrollTop(),
+ width: withinElement.outerWidth(),
+ height: withinElement.outerHeight()
+ };
+ }
+};
+
+$.fn.position = function( options ) {
+ if ( !options || !options.of ) {
+ return _position.apply( this, arguments );
+ }
+
+ // Make a copy, we don't want to modify arguments
+ options = $.extend( {}, options );
+
+ var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
+
+ // Make sure string options are treated as CSS selectors
+ target = typeof options.of === "string" ?
+ $( document ).find( options.of ) :
+ $( options.of ),
+
+ within = $.position.getWithinInfo( options.within ),
+ scrollInfo = $.position.getScrollInfo( within ),
+ collision = ( options.collision || "flip" ).split( " " ),
+ offsets = {};
+
+ dimensions = getDimensions( target );
+ if ( target[ 0 ].preventDefault ) {
+
+ // Force left top to allow flipping
+ options.at = "left top";
+ }
+ targetWidth = dimensions.width;
+ targetHeight = dimensions.height;
+ targetOffset = dimensions.offset;
+
+ // Clone to reuse original targetOffset later
+ basePosition = $.extend( {}, targetOffset );
+
+ // Force my and at to have valid horizontal and vertical positions
+ // if a value is missing or invalid, it will be converted to center
+ $.each( [ "my", "at" ], function() {
+ var pos = ( options[ this ] || "" ).split( " " ),
+ horizontalOffset,
+ verticalOffset;
+
+ if ( pos.length === 1 ) {
+ pos = rhorizontal.test( pos[ 0 ] ) ?
+ pos.concat( [ "center" ] ) :
+ rvertical.test( pos[ 0 ] ) ?
+ [ "center" ].concat( pos ) :
+ [ "center", "center" ];
+ }
+ pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
+ pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
+
+ // Calculate offsets
+ horizontalOffset = roffset.exec( pos[ 0 ] );
+ verticalOffset = roffset.exec( pos[ 1 ] );
+ offsets[ this ] = [
+ horizontalOffset ? horizontalOffset[ 0 ] : 0,
+ verticalOffset ? verticalOffset[ 0 ] : 0
+ ];
+
+ // Reduce to just the positions without the offsets
+ options[ this ] = [
+ rposition.exec( pos[ 0 ] )[ 0 ],
+ rposition.exec( pos[ 1 ] )[ 0 ]
+ ];
+ } );
+
+ // Normalize collision option
+ if ( collision.length === 1 ) {
+ collision[ 1 ] = collision[ 0 ];
+ }
+
+ if ( options.at[ 0 ] === "right" ) {
+ basePosition.left += targetWidth;
+ } else if ( options.at[ 0 ] === "center" ) {
+ basePosition.left += targetWidth / 2;
+ }
+
+ if ( options.at[ 1 ] === "bottom" ) {
+ basePosition.top += targetHeight;
+ } else if ( options.at[ 1 ] === "center" ) {
+ basePosition.top += targetHeight / 2;
+ }
+
+ atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
+ basePosition.left += atOffset[ 0 ];
+ basePosition.top += atOffset[ 1 ];
+
+ return this.each( function() {
+ var collisionPosition, using,
+ elem = $( this ),
+ elemWidth = elem.outerWidth(),
+ elemHeight = elem.outerHeight(),
+ marginLeft = parseCss( this, "marginLeft" ),
+ marginTop = parseCss( this, "marginTop" ),
+ collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
+ scrollInfo.width,
+ collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
+ scrollInfo.height,
+ position = $.extend( {}, basePosition ),
+ myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
+
+ if ( options.my[ 0 ] === "right" ) {
+ position.left -= elemWidth;
+ } else if ( options.my[ 0 ] === "center" ) {
+ position.left -= elemWidth / 2;
+ }
+
+ if ( options.my[ 1 ] === "bottom" ) {
+ position.top -= elemHeight;
+ } else if ( options.my[ 1 ] === "center" ) {
+ position.top -= elemHeight / 2;
+ }
+
+ position.left += myOffset[ 0 ];
+ position.top += myOffset[ 1 ];
+
+ collisionPosition = {
+ marginLeft: marginLeft,
+ marginTop: marginTop
+ };
+
+ $.each( [ "left", "top" ], function( i, dir ) {
+ if ( $.ui.position[ collision[ i ] ] ) {
+ $.ui.position[ collision[ i ] ][ dir ]( position, {
+ targetWidth: targetWidth,
+ targetHeight: targetHeight,
+ elemWidth: elemWidth,
+ elemHeight: elemHeight,
+ collisionPosition: collisionPosition,
+ collisionWidth: collisionWidth,
+ collisionHeight: collisionHeight,
+ offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
+ my: options.my,
+ at: options.at,
+ within: within,
+ elem: elem
+ } );
+ }
+ } );
+
+ if ( options.using ) {
+
+ // Adds feedback as second argument to using callback, if present
+ using = function( props ) {
+ var left = targetOffset.left - position.left,
+ right = left + targetWidth - elemWidth,
+ top = targetOffset.top - position.top,
+ bottom = top + targetHeight - elemHeight,
+ feedback = {
+ target: {
+ element: target,
+ left: targetOffset.left,
+ top: targetOffset.top,
+ width: targetWidth,
+ height: targetHeight
+ },
+ element: {
+ element: elem,
+ left: position.left,
+ top: position.top,
+ width: elemWidth,
+ height: elemHeight
+ },
+ horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
+ vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
+ };
+ if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
+ feedback.horizontal = "center";
+ }
+ if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
+ feedback.vertical = "middle";
+ }
+ if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
+ feedback.important = "horizontal";
+ } else {
+ feedback.important = "vertical";
+ }
+ options.using.call( this, props, feedback );
+ };
+ }
+
+ elem.offset( $.extend( position, { using: using } ) );
+ } );
+};
+
+$.ui.position = {
+ fit: {
+ left: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
+ outerWidth = within.width,
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = withinOffset - collisionPosLeft,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
+ newOverRight;
+
+ // Element is wider than within
+ if ( data.collisionWidth > outerWidth ) {
+
+ // Element is initially over the left side of within
+ if ( overLeft > 0 && overRight <= 0 ) {
+ newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
+ withinOffset;
+ position.left += overLeft - newOverRight;
+
+ // Element is initially over right side of within
+ } else if ( overRight > 0 && overLeft <= 0 ) {
+ position.left = withinOffset;
+
+ // Element is initially over both left and right sides of within
+ } else {
+ if ( overLeft > overRight ) {
+ position.left = withinOffset + outerWidth - data.collisionWidth;
+ } else {
+ position.left = withinOffset;
+ }
+ }
+
+ // Too far left -> align with left edge
+ } else if ( overLeft > 0 ) {
+ position.left += overLeft;
+
+ // Too far right -> align with right edge
+ } else if ( overRight > 0 ) {
+ position.left -= overRight;
+
+ // Adjust based on position and margin
+ } else {
+ position.left = max( position.left - collisionPosLeft, position.left );
+ }
+ },
+ top: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
+ outerHeight = data.within.height,
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = withinOffset - collisionPosTop,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
+ newOverBottom;
+
+ // Element is taller than within
+ if ( data.collisionHeight > outerHeight ) {
+
+ // Element is initially over the top of within
+ if ( overTop > 0 && overBottom <= 0 ) {
+ newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
+ withinOffset;
+ position.top += overTop - newOverBottom;
+
+ // Element is initially over bottom of within
+ } else if ( overBottom > 0 && overTop <= 0 ) {
+ position.top = withinOffset;
+
+ // Element is initially over both top and bottom of within
+ } else {
+ if ( overTop > overBottom ) {
+ position.top = withinOffset + outerHeight - data.collisionHeight;
+ } else {
+ position.top = withinOffset;
+ }
+ }
+
+ // Too far up -> align with top
+ } else if ( overTop > 0 ) {
+ position.top += overTop;
+
+ // Too far down -> align with bottom edge
+ } else if ( overBottom > 0 ) {
+ position.top -= overBottom;
+
+ // Adjust based on position and margin
+ } else {
+ position.top = max( position.top - collisionPosTop, position.top );
+ }
+ }
+ },
+ flip: {
+ left: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.offset.left + within.scrollLeft,
+ outerWidth = within.width,
+ offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = collisionPosLeft - offsetLeft,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
+ myOffset = data.my[ 0 ] === "left" ?
+ -data.elemWidth :
+ data.my[ 0 ] === "right" ?
+ data.elemWidth :
+ 0,
+ atOffset = data.at[ 0 ] === "left" ?
+ data.targetWidth :
+ data.at[ 0 ] === "right" ?
+ -data.targetWidth :
+ 0,
+ offset = -2 * data.offset[ 0 ],
+ newOverRight,
+ newOverLeft;
+
+ if ( overLeft < 0 ) {
+ newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
+ outerWidth - withinOffset;
+ if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
+ position.left += myOffset + atOffset + offset;
+ }
+ } else if ( overRight > 0 ) {
+ newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
+ atOffset + offset - offsetLeft;
+ if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
+ position.left += myOffset + atOffset + offset;
+ }
+ }
+ },
+ top: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.offset.top + within.scrollTop,
+ outerHeight = within.height,
+ offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = collisionPosTop - offsetTop,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
+ top = data.my[ 1 ] === "top",
+ myOffset = top ?
+ -data.elemHeight :
+ data.my[ 1 ] === "bottom" ?
+ data.elemHeight :
+ 0,
+ atOffset = data.at[ 1 ] === "top" ?
+ data.targetHeight :
+ data.at[ 1 ] === "bottom" ?
+ -data.targetHeight :
+ 0,
+ offset = -2 * data.offset[ 1 ],
+ newOverTop,
+ newOverBottom;
+ if ( overTop < 0 ) {
+ newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
+ outerHeight - withinOffset;
+ if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
+ position.top += myOffset + atOffset + offset;
+ }
+ } else if ( overBottom > 0 ) {
+ newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
+ offset - offsetTop;
+ if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
+ position.top += myOffset + atOffset + offset;
+ }
+ }
+ }
+ },
+ flipfit: {
+ left: function() {
+ $.ui.position.flip.left.apply( this, arguments );
+ $.ui.position.fit.left.apply( this, arguments );
+ },
+ top: function() {
+ $.ui.position.flip.top.apply( this, arguments );
+ $.ui.position.fit.top.apply( this, arguments );
+ }
+ }
+};
+
+} )();
+
+var position = $.ui.position;
+
+
+/*!
+ * jQuery UI Support for jQuery core 1.8.x and newer 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ */
+
+//>>label: jQuery 1.8+ Support
+//>>group: Core
+//>>description: Support version 1.8.x and newer of jQuery core
+
+
+// Support: jQuery 1.9.x or older
+// $.expr[ ":" ] is deprecated.
+if ( !$.expr.pseudos ) {
+ $.expr.pseudos = $.expr[ ":" ];
+}
+
+// Support: jQuery 1.11.x or older
+// $.unique has been renamed to $.uniqueSort
+if ( !$.uniqueSort ) {
+ $.uniqueSort = $.unique;
+}
+
+// Support: jQuery 2.2.x or older.
+// This method has been defined in jQuery 3.0.0.
+// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
+if ( !$.escapeSelector ) {
+
+ // CSS string/identifier serialization
+ // https://drafts.csswg.org/cssom/#common-serializing-idioms
+ var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
+
+ var fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ };
+
+ $.escapeSelector = function( sel ) {
+ return ( sel + "" ).replace( rcssescape, fcssescape );
+ };
+}
+
+// Support: jQuery 3.4.x or older
+// These methods have been defined in jQuery 3.5.0.
+if ( !$.fn.even || !$.fn.odd ) {
+ $.fn.extend( {
+ even: function() {
+ return this.filter( function( i ) {
+ return i % 2 === 0;
+ } );
+ },
+ odd: function() {
+ return this.filter( function( i ) {
+ return i % 2 === 1;
+ } );
+ }
+ } );
+}
+
+;
+/*!
+ * jQuery UI Keycode 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+//>>label: Keycode
+//>>group: Core
+//>>description: Provide keycodes as keynames
+//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
+
+
+var keycode = $.ui.keyCode = {
+ BACKSPACE: 8,
+ COMMA: 188,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ LEFT: 37,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38
+};
+
+
+/*!
+ * jQuery UI Scroll Parent 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+//>>label: scrollParent
+//>>group: Core
+//>>description: Get the closest ancestor element that is scrollable.
+//>>docs: http://api.jqueryui.com/scrollParent/
+
+
+var scrollParent = $.fn.scrollParent = function( includeHidden ) {
+ var position = this.css( "position" ),
+ excludeStaticParent = position === "absolute",
+ overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
+ scrollParent = this.parents().filter( function() {
+ var parent = $( this );
+ if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
+ return false;
+ }
+ return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
+ parent.css( "overflow-x" ) );
+ } ).eq( 0 );
+
+ return position === "fixed" || !scrollParent.length ?
+ $( this[ 0 ].ownerDocument || document ) :
+ scrollParent;
+};
+
+
+/*!
+ * jQuery UI Unique ID 1.13.2
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+//>>label: uniqueId
+//>>group: Core
+//>>description: Functions to generate and remove uniqueId's
+//>>docs: http://api.jqueryui.com/uniqueId/
+
+
+var uniqueId = $.fn.extend( {
+ uniqueId: ( function() {
+ var uuid = 0;
+
+ return function() {
+ return this.each( function() {
+ if ( !this.id ) {
+ this.id = "ui-id-" + ( ++uuid );
+ }
+ } );
+ };
+ } )(),
+
+ removeUniqueId: function() {
+ return this.each( function() {
+ if ( /^ui-id-\d+$/.test( this.id ) ) {
+ $( this ).removeAttr( "id" );
+ }
+ } );
+ }
+} );
+
+
+
+
+} ); \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.wide.js b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.wide.js
new file mode 100644
index 0000000..742d29c
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/modules/jquery.fancytree.wide.js
@@ -0,0 +1,257 @@
+/*!
+ * jquery.fancytree.wide.js
+ * Support for 100% wide selection bars.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+ */
+
+(function (factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery", "./jquery.fancytree"], factory);
+ } else if (typeof module === "object" && module.exports) {
+ // Node/CommonJS
+ require("./jquery.fancytree");
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+})(function ($) {
+ "use strict";
+
+ var reNumUnit = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/; // split "1.5em" to ["1.5", "em"]
+
+ /*******************************************************************************
+ * Private functions and variables
+ */
+ // var _assert = $.ui.fancytree.assert;
+
+ /* Calculate inner width without scrollbar */
+ // function realInnerWidth($el) {
+ // // http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/
+ // // inst.contWidth = parseFloat(this.$container.css("width"), 10);
+ // // 'Client width without scrollbar' - 'padding'
+ // return $el[0].clientWidth - ($el.innerWidth() - parseFloat($el.css("width"), 10));
+ // }
+
+ /* Create a global embedded CSS style for the tree. */
+ function defineHeadStyleElement(id, cssText) {
+ id = "fancytree-style-" + id;
+ var $headStyle = $("#" + id);
+
+ if (!cssText) {
+ $headStyle.remove();
+ return null;
+ }
+ if (!$headStyle.length) {
+ $headStyle = $("<style />")
+ .attr("id", id)
+ .addClass("fancytree-style")
+ .prop("type", "text/css")
+ .appendTo("head");
+ }
+ try {
+ $headStyle.html(cssText);
+ } catch (e) {
+ // fix for IE 6-8
+ $headStyle[0].styleSheet.cssText = cssText;
+ }
+ return $headStyle;
+ }
+
+ /* Calculate the CSS rules that indent title spans. */
+ function renderLevelCss(
+ containerId,
+ depth,
+ levelOfs,
+ lineOfs,
+ labelOfs,
+ measureUnit
+ ) {
+ var i,
+ prefix = "#" + containerId + " span.fancytree-level-",
+ rules = [];
+
+ for (i = 0; i < depth; i++) {
+ rules.push(
+ prefix +
+ (i + 1) +
+ " span.fancytree-title { padding-left: " +
+ (i * levelOfs + lineOfs) +
+ measureUnit +
+ "; }"
+ );
+ }
+ // Some UI animations wrap the UL inside a DIV and set position:relative on both.
+ // This breaks the left:0 and padding-left:nn settings of the title
+ rules.push(
+ "#" +
+ containerId +
+ " div.ui-effects-wrapper ul li span.fancytree-title, " +
+ "#" +
+ containerId +
+ " li.fancytree-animating span.fancytree-title " + // #716
+ "{ padding-left: " +
+ labelOfs +
+ measureUnit +
+ "; position: static; width: auto; }"
+ );
+ return rules.join("\n");
+ }
+
+ // /**
+ // * [ext-wide] Recalculate the width of the selection bar after the tree container
+ // * was resized.<br>
+ // * May be called explicitly on container resize, since there is no resize event
+ // * for DIV tags.
+ // *
+ // * @alias Fancytree#wideUpdate
+ // * @requires jquery.fancytree.wide.js
+ // */
+ // $.ui.fancytree._FancytreeClass.prototype.wideUpdate = function(){
+ // var inst = this.ext.wide,
+ // prevCw = inst.contWidth,
+ // prevLo = inst.lineOfs;
+
+ // inst.contWidth = realInnerWidth(this.$container);
+ // // Each title is precceeded by 2 or 3 icons (16px + 3 margin)
+ // // + 1px title border and 3px title padding
+ // // TODO: use code from treeInit() below
+ // inst.lineOfs = (this.options.checkbox ? 3 : 2) * 19;
+ // if( prevCw !== inst.contWidth || prevLo !== inst.lineOfs ) {
+ // this.debug("wideUpdate: " + inst.contWidth);
+ // this.visit(function(node){
+ // node.tree._callHook("nodeRenderTitle", node);
+ // });
+ // }
+ // };
+
+ /*******************************************************************************
+ * Extension code
+ */
+ $.ui.fancytree.registerExtension({
+ name: "wide",
+ version: "2.38.3",
+ // Default options for this extension.
+ options: {
+ iconWidth: null, // Adjust this if @fancy-icon-width != "16px"
+ iconSpacing: null, // Adjust this if @fancy-icon-spacing != "3px"
+ labelSpacing: null, // Adjust this if padding between icon and label != "3px"
+ levelOfs: null, // Adjust this if ul padding != "16px"
+ },
+
+ treeCreate: function (ctx) {
+ this._superApply(arguments);
+ this.$container.addClass("fancytree-ext-wide");
+
+ var containerId,
+ cssText,
+ iconSpacingUnit,
+ labelSpacingUnit,
+ iconWidthUnit,
+ levelOfsUnit,
+ instOpts = ctx.options.wide,
+ // css sniffing
+ $dummyLI = $(
+ "<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />"
+ ).appendTo(ctx.tree.$container),
+ $dummyIcon = $dummyLI.find(".fancytree-icon"),
+ $dummyUL = $dummyLI.find("ul"),
+ // $dummyTitle = $dummyLI.find(".fancytree-title"),
+ iconSpacing =
+ instOpts.iconSpacing || $dummyIcon.css("margin-left"),
+ iconWidth = instOpts.iconWidth || $dummyIcon.css("width"),
+ labelSpacing = instOpts.labelSpacing || "3px",
+ levelOfs = instOpts.levelOfs || $dummyUL.css("padding-left");
+
+ $dummyLI.remove();
+
+ iconSpacingUnit = iconSpacing.match(reNumUnit)[2];
+ iconSpacing = parseFloat(iconSpacing, 10);
+ labelSpacingUnit = labelSpacing.match(reNumUnit)[2];
+ labelSpacing = parseFloat(labelSpacing, 10);
+ iconWidthUnit = iconWidth.match(reNumUnit)[2];
+ iconWidth = parseFloat(iconWidth, 10);
+ levelOfsUnit = levelOfs.match(reNumUnit)[2];
+ if (
+ iconSpacingUnit !== iconWidthUnit ||
+ levelOfsUnit !== iconWidthUnit ||
+ labelSpacingUnit !== iconWidthUnit
+ ) {
+ $.error(
+ "iconWidth, iconSpacing, and levelOfs must have the same css measure unit"
+ );
+ }
+ this._local.measureUnit = iconWidthUnit;
+ this._local.levelOfs = parseFloat(levelOfs);
+ this._local.lineOfs =
+ (1 +
+ (ctx.options.checkbox ? 1 : 0) +
+ (ctx.options.icon === false ? 0 : 1)) *
+ (iconWidth + iconSpacing) +
+ iconSpacing;
+ this._local.labelOfs = labelSpacing;
+ this._local.maxDepth = 10;
+
+ // Get/Set a unique Id on the container (if not already exists)
+ containerId = this.$container.uniqueId().attr("id");
+ // Generated css rules for some levels (extended on demand)
+ cssText = renderLevelCss(
+ containerId,
+ this._local.maxDepth,
+ this._local.levelOfs,
+ this._local.lineOfs,
+ this._local.labelOfs,
+ this._local.measureUnit
+ );
+ defineHeadStyleElement(containerId, cssText);
+ },
+ treeDestroy: function (ctx) {
+ // Remove generated css rules
+ defineHeadStyleElement(this.$container.attr("id"), null);
+ return this._superApply(arguments);
+ },
+ nodeRenderStatus: function (ctx) {
+ var containerId,
+ cssText,
+ res,
+ node = ctx.node,
+ level = node.getLevel();
+
+ res = this._super(ctx);
+ // Generate some more level-n rules if required
+ if (level > this._local.maxDepth) {
+ containerId = this.$container.attr("id");
+ this._local.maxDepth *= 2;
+ node.debug(
+ "Define global ext-wide css up to level " +
+ this._local.maxDepth
+ );
+ cssText = renderLevelCss(
+ containerId,
+ this._local.maxDepth,
+ this._local.levelOfs,
+ this._local.lineOfs,
+ this._local.labelSpacing,
+ this._local.measureUnit
+ );
+ defineHeadStyleElement(containerId, cssText);
+ }
+ // Add level-n class to apply indentation padding.
+ // (Setting element style would not work, since it cannot easily be
+ // overriden while animations run)
+ $(node.span).addClass("fancytree-level-" + level);
+ return res;
+ },
+ });
+ // Value returned by `require('jquery.fancytree..')`
+ return $.ui.fancytree;
+}); // End of closure
diff --git a/plugins/55/indexmenu/scripts/fancytree/readme/icons_layout__from ods.png b/plugins/55/indexmenu/scripts/fancytree/readme/icons_layout__from ods.png
new file mode 100644
index 0000000..1ab4b72
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/readme/icons_layout__from ods.png
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-awesome/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.css
new file mode 100644
index 0000000..b5ab63f
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.css
@@ -0,0 +1,588 @@
+/*!
+ * Fancytree "awesome" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: silver;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 10pt;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0pt 0pt;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-awesome/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 10pt;
+ height: 10pt;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-position: 0pt 0pt;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 0px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 10pt;
+ height: 10pt;
+ display: inline-block;
+ margin-left: 3px;
+ background-position: 0pt 0pt;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 10pt;
+ height: 10pt;
+ margin-left: 3px;
+ margin-top: 0px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ margin-top: 0;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 3px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 3px;
+}
+/* Documents */
+/* Folders */
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: none;
+}
+/* Status node icons */
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 1px;
+ min-height: 10pt;
+}
+span.fancytree-title {
+ color: #000;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 10pt;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 3px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 20pt;
+ position: absolute;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 40pt;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-awesome/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: silver;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0pt 0pt;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: silver;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: silver;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+ul.fancytree-container ul {
+ padding: 0.3em 0 0 1em;
+ margin: 0;
+}
+.fancytree-expander,
+.fancytree-checkbox,
+.fancytree-icon {
+ min-width: 10pt;
+ text-align: center;
+}
+svg.fancytree-checkbox,
+svg.fancytree-icon {
+ padding-left: 3px;
+}
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+ border: 1px solid transparent;
+ border-radius: 0;
+}
+span.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+}
+span.fancytree-active span.fancytree-title {
+ background-color: #D4D4D4;
+}
+.fancytree-treefocus span.fancytree-active span.fancytree-title {
+ color: white;
+ background-color: #3875D7;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+ border-collapse: collapse;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused {
+ background-color: #99DEFD;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+ background-color: royalblue;
+}
+/*******************************************************************************
+ * 'columnview' extension
+ */
+table.fancytree-ext-columnview tbody tr td {
+ border: 1px solid gray;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #ccc;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: royalblue;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.less
new file mode 100644
index 0000000..51189b1
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.less
@@ -0,0 +1,134 @@
+/*!
+ * Fancytree "awesome" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "skin-common.less";
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-awesome/";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+@fancy-use-sprites: false; // false: suppress all background images (i.e. icons)
+@fancy-loading-url: none;
+
+@fancy-cst-size: 16px;
+
+@fancy-level-indent: @fancy-cst-size; //@fancy-cst-size;
+@fancy-line-height: @fancy-cst-size; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: @fancy-cst-size;
+@fancy-icon-height: @fancy-cst-size;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false;
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%; //@fancy-cst-size;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: #000;
+@fancy-font-color-dimm: silver;
+@fancy-font-error-color: red;
+
+// set icon color to font color as well
+span.fancytree-node {
+ color: @fancy-font-color;
+}
+
+ul.fancytree-container ul
+{
+ padding: 0 0 0 1em; // 0.3em 0 0 1em;
+ margin: 0;
+}
+
+
+// The standard CSS assumes span.icon, but Fontawesome may use SVG or SPAN
+.fancytree-expander,
+.fancytree-checkbox,
+.fancytree-icon {
+ min-width: @fancy-icon-width;
+ text-align: center;
+ font-size: @fancy-cst-size;
+}
+svg.fancytree-checkbox, // span... is already defined in skin-common-less
+svg.fancytree-icon {
+ padding-left: @fancy-icon-spacing;
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+ border: 1px solid transparent; // reserve some space for status borders
+ border-radius: 0;
+}
+span.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+}
+// span.fancytree-selected span.fancytree-title,
+span.fancytree-active span.fancytree-title {
+ background-color: #D4D4D4; // gray
+}
+// span.fancytree-selected span.fancytree-title {
+// font-style: italic;
+// }
+// .fancytree-treefocus span.fancytree-selected span.fancytree-title,
+.fancytree-treefocus span.fancytree-active span.fancytree-title {
+ color: white;
+ background-color: #3875D7; // blue
+}
+
+// .fancytree-treefocus span.fancytree-selected span.fancytree-title{
+// color: white;
+// background-color: #99DEFD; // blue
+// }
+
+///*******************************************************************************
+// * 'table' extension
+// */
+//table.fancytree-ext-table {
+// border-collapse: collapse;
+// tbody {
+// tr.fancytree-focused {
+// background-color: #99DEFD;
+// }
+// tr.fancytree-active {
+// background-color: royalblue;
+// }
+// // tr.fancytree-selected {
+// // background-color: #99DEFD;
+// // }
+// }
+//}
+//
+///*******************************************************************************
+// * 'columnview' extension
+// */
+//
+//table.fancytree-ext-columnview tbody tr td {
+// border: 1px solid gray;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+// background-color: #ccc;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+// background-color: royalblue;
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.min.css
new file mode 100644
index 0000000..7fa2856
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "awesome" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 10pt;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-awesome/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:10pt;height:10pt;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:0}span.fancytree-custom-icon{width:10pt;height:10pt;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:10pt;height:10pt;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{margin-top:0}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:3px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:none}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:10pt}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:10pt;padding:0 3px 0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}#fancytree-drop-marker{width:20pt;position:absolute;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:40pt}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-awesome/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}ul.fancytree-container ul{padding:.3em 0 0 1em;margin:0}.fancytree-checkbox,.fancytree-expander,.fancytree-icon{min-width:10pt;text-align:center}svg.fancytree-checkbox,svg.fancytree-icon{padding-left:3px}span.fancytree-title{border:1px solid transparent;border-radius:0}span.fancytree-focused span.fancytree-title{outline:1px dotted black}span.fancytree-active span.fancytree-title{background-color:#d4d4d4}.fancytree-treefocus span.fancytree-active span.fancytree-title{color:#fff;background-color:#3875d7}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table tbody tr.fancytree-focused{background-color:#99defd}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#4169e1}table.fancytree-ext-columnview tbody tr td{border:1px solid gray}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#ccc}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#4169e1} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-awesome/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/vline-rtl.gif
new file mode 100644
index 0000000..0400cb3
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-awesome/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/vline.gif
new file mode 100644
index 0000000..1b00ae5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-awesome/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.css
new file mode 100644
index 0000000..f407a96
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.css
@@ -0,0 +1,620 @@
+/*!
+ * Fancytree "bootstrap" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #c0c0c0;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 16px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0em 0em;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-bootstrap-n/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 1em;
+ height: 1em;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-position: 0em 0em;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 0px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 1em;
+ height: 1em;
+ display: inline-block;
+ margin-left: 0.5em;
+ background-position: 0em 0em;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 1em;
+ height: 1em;
+ margin-left: 0.5em;
+ margin-top: 0px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ margin-top: 0;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 0.5em;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 0.5em;
+}
+/* Documents */
+/* Folders */
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: none;
+}
+/* Status node icons */
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 1px;
+ min-height: 1em;
+}
+span.fancytree-title {
+ color: black;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 1em;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 0.5em;
+ border: 1px solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 2em;
+ position: absolute;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 4em;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-bootstrap-n/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #c0c0c0;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0em 0em;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+ul.fancytree-container ul {
+ padding: 0 0 0 1.5em;
+ margin: 0;
+}
+/* Prevent focus frame */
+.fancytree-container:focus {
+ outline: none;
+}
+.fancytree-container span.fancytree-statusnode-error span.fancytree-expander {
+ color: red;
+}
+span.fancytree-node {
+ border: 1px solid transparent;
+ border-radius: 3px;
+ padding-left: 8px;
+}
+span.fancytree-title {
+ border-radius: 3px;
+}
+span.fancytree-node.fancytree-selected {
+ background-color: #80c780;
+ border-color: #80c780;
+}
+span.fancytree-node.fancytree-selected span.fancytree-title {
+ background-color: #80c780;
+}
+span.fancytree-node.fancytree-active {
+ background-color: #6aa3d5;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node:hover {
+ background-color: #e9f2f9;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused {
+ border-color: #428bca;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected {
+ background-color: #5cb85c;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected span.fancytree-title {
+ background-color: #5cb85c;
+}
+.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active {
+ background-color: #428bca;
+ border-color: #428bca;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+ border: 1px solid #eeeeee;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+ background-color: #80c780;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected span.fancytree-node {
+ background-color: #80c780;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected span.fancytree-title {
+ background-color: #80c780;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+ background-color: #6aa3d5;
+}
+table.fancytree-ext-table tbody tr.fancytree-active span.fancytree-node {
+ background-color: #6aa3d5;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr:hover {
+ background-color: #e9f2f9;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-focused span.fancytree-title {
+ outline: 1px dotted #428bca;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {
+ background-color: #5cb85c;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected span.fancytree-node {
+ background-color: #5cb85c;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected span.fancytree-title {
+ background-color: #5cb85c;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {
+ background-color: #428bca;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active span.fancytree-node {
+ background-color: #428bca;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.less
new file mode 100644
index 0000000..20fcbb4
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.less
@@ -0,0 +1,185 @@
+/*!
+ * Fancytree "bootstrap" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+
+// local vars
+// @fancy-my-icon-size: 16px;
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: false; // false: suppress all background images (i.e. icons)
+@fancy-loading-url: none;
+
+@fancy-icon-width: 1em;
+@fancy-icon-height: 1em;
+@fancy-line-height: 1em;
+@fancy-icon-spacing: 0.5em;
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-bootstrap-n/";
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%; //@fancy-cst-size;
+
+ul.fancytree-container ul {
+ padding: 0 0 0 1.5em;
+ margin: 0;
+}
+/* Prevent focus frame */
+.fancytree-container:focus {
+ outline: none;
+}
+
+// Error status node
+.fancytree-container span.fancytree-statusnode-error span.fancytree-expander {
+ color: @fancy-font-error-color;
+}
+
+/////
+// Original bootstrap colors (http://getbootstrap.com/css/#responsive-utilities)
+@gray-darker: lighten(#000, 13.5%); // #222
+@gray-dark: lighten(#000, 20%); // #333
+@gray: lighten(#000, 33.5%); // #555
+@gray-light: lighten(#000, 60%); // #999
+@gray-lighter: lighten(#000, 93.5%); // #eee
+
+@brand-primary: #428bca; // blue
+@brand-success: #5cb85c; // green
+@brand-info: #5bc0de; // light blue
+@brand-warning: #f0ad4e; // orange
+@brand-danger: #d9534f; // red
+
+@border-radius-base: 4px;
+@border-radius-large: 6px;
+@border-radius-small: 3px;
+/////////////
+
+span.fancytree-node {
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ border-radius: @border-radius-small;
+ padding-left: 8px;
+ color: @fancy-font-color; //set icon color to font color as well
+}
+span.fancytree-title {
+ border-radius: @border-radius-small;
+}
+// Inactive tree:
+span.fancytree-node.fancytree-selected { // selected nodes inside inactive tree
+ background-color: lighten(@brand-success, 10%);
+ border-color: lighten(@brand-success, 10%);
+ span.fancytree-title {
+ background-color: lighten(@brand-success, 10%); // green title, even when active
+ }
+}
+span.fancytree-node.fancytree-active { // active nodes inside inactive tree
+ background-color: lighten(@brand-primary, 10%);
+}
+// Active tree:
+.fancytree-container.fancytree-treefocus {
+ span.fancytree-node:hover {
+ background-color: lighten(@brand-primary, 42%);
+ }
+ span.fancytree-node.fancytree-focused {
+ border-color: @brand-primary;
+ }
+ span.fancytree-node.fancytree-selected {
+ background-color: @brand-success;
+ span.fancytree-title {
+ background-color: @brand-success; // green title, even when active
+ }
+ }
+ span.fancytree-node.fancytree-active {
+ background-color: @brand-primary;
+ border-color: @brand-primary;
+ }
+}
+
+///*******************************************************************************
+// * 'table' extension
+// */
+//table.fancytree-ext-table tbody {
+// tr td {
+// border: 1px solid @gray-lighter;
+// }
+// // span.fancytree-node,
+// // span.fancytree-node:hover { // undo standard tree css
+// // border: none;
+// // background: none;
+// // }
+// // // Title get's a white background, when hovered. Undo standard node formatting
+// // span.fancytree-title:hover {
+// // border: none;
+// // background: inherit;
+// // background: transparent;
+// // background: none;
+// // filter: none;
+// // }
+// // dimmed, if inside inactive tree
+// tr.fancytree-selected {
+// background-color: lighten(@brand-success, 10%);
+// span.fancytree-node {
+// background-color: lighten(@brand-success, 10%);
+// }
+// span.fancytree-title {
+// background-color: lighten(@brand-success, 10%); // green title, even when active
+// }
+// }
+// tr.fancytree-active { // dimmed, if inside inactive tree
+// background-color: lighten(@brand-primary, 10%);
+// span.fancytree-node {
+// background-color: lighten(@brand-primary, 10%);
+// }
+// }
+//}
+//
+//table.fancytree-ext-table.fancytree-treefocus tbody {
+// tr:hover {
+// background-color: lighten(@brand-primary, 42%);
+// // outline: 1px solid @brand-primary;
+// }
+// tr.fancytree-focused span.fancytree-title {
+// outline: 1px dotted @brand-primary;
+// }
+// tr.fancytree-active:hover,
+// tr.fancytree-selected:hover {
+// // background-color: #CBE8F6;
+// // outline: 1px solid #26A0DA;
+// }
+// tr.fancytree-selected {
+// background-color: @brand-success;
+// span.fancytree-node {
+// background-color: @brand-success;
+// }
+// span.fancytree-title {
+// background-color: @brand-success; // green title, even when active
+// }
+// }
+// tr.fancytree-active {
+// background-color: @brand-primary;
+// span.fancytree-node {
+// background-color: @brand-primary;
+// }
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.min.css
new file mode 100644
index 0000000..ebfd3b1
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "bootstrap" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-bootstrap-n/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:1em;height:1em;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:0}span.fancytree-custom-icon{width:1em;height:1em;display:inline-block;margin-left:.5em;background-position:0 0}img.fancytree-icon{width:1em;height:1em;margin-left:.5em;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{margin-top:0}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:.5em}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:.5em}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:none}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:1em}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:1em;padding:0 3px 0 3px;margin:0 0 0 .5em;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}#fancytree-drop-marker{width:2em;position:absolute;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:4em}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-bootstrap-n/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}ul.fancytree-container ul{padding:0 0 0 1.5em;margin:0}.fancytree-container:focus{outline:0}.fancytree-container span.fancytree-statusnode-error span.fancytree-expander{color:red}span.fancytree-node{border:1px solid transparent;border-radius:3px;padding-left:8px}span.fancytree-title{border-radius:3px}span.fancytree-node.fancytree-selected{background-color:#80c780;border-color:#80c780}span.fancytree-node.fancytree-selected span.fancytree-title{background-color:#80c780}span.fancytree-node.fancytree-active{background-color:#6aa3d5}.fancytree-container.fancytree-treefocus span.fancytree-node:hover{background-color:#e9f2f9}.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused{border-color:#428bca}.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected{background-color:#5cb85c}.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected span.fancytree-title{background-color:#5cb85c}.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active{background-color:#428bca;border-color:#428bca}table.fancytree-ext-table tbody tr td{border:1px solid #eee}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#80c780}table.fancytree-ext-table tbody tr.fancytree-selected span.fancytree-node{background-color:#80c780}table.fancytree-ext-table tbody tr.fancytree-selected span.fancytree-title{background-color:#80c780}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#6aa3d5}table.fancytree-ext-table tbody tr.fancytree-active span.fancytree-node{background-color:#6aa3d5}table.fancytree-ext-table.fancytree-treefocus tbody tr:hover{background-color:#e9f2f9}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-focused span.fancytree-title{outline:1px dotted #428bca}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected{background-color:#5cb85c}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected span.fancytree-node{background-color:#5cb85c}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected span.fancytree-title{background-color:#5cb85c}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active{background-color:#428bca}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active span.fancytree-node{background-color:#428bca} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/vline-rtl.gif
new file mode 100644
index 0000000..0400cb3
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/vline.gif
new file mode 100644
index 0000000..1b00ae5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap-n/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/boot.css b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/boot.css
new file mode 100644
index 0000000..0e0d2d2
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/boot.css
@@ -0,0 +1,1065 @@
+@font-face {
+ font-family: "Glyphicons Halflings";
+ src: url(../fonts/glyphicons-halflings-regular.eot);
+ src: url(../fonts/glyphicons-halflings-regular.eot?#iefix) format("embedded-opentype"), url(../fonts/glyphicons-halflings-regular.woff2) format("woff2"), url(../fonts/glyphicons-halflings-regular.woff) format("woff"), url(../fonts/glyphicons-halflings-regular.ttf) format("truetype"), url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format("svg")
+}
+
+.glyphicon {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: "Glyphicons Halflings";
+ font-style: normal;
+ font-weight: 400;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale
+}
+
+/*.glyphicon-asterisk:before {*/
+/* content: "\002a"*/
+/*}*/
+
+/*.glyphicon-plus:before {*/
+/* content: "\002b"*/
+/*}*/
+
+/*.glyphicon-eur:before, .glyphicon-euro:before {*/
+/* content: "\20ac"*/
+/*}*/
+
+/*.glyphicon-minus:before {*/
+/* content: "\2212"*/
+/*}*/
+
+/*.glyphicon-cloud:before {*/
+/* content: "\2601"*/
+/*}*/
+
+/*.glyphicon-envelope:before {*/
+/* content: "\2709"*/
+/*}*/
+
+/*.glyphicon-pencil:before {*/
+/* content: "\270f"*/
+/*}*/
+
+/*.glyphicon-glass:before {*/
+/* content: "\e001"*/
+/*}*/
+
+/*.glyphicon-music:before {*/
+/* content: "\e002"*/
+/*}*/
+
+/*.glyphicon-search:before {*/
+/* content: "\e003"*/
+/*}*/
+
+/*.glyphicon-heart:before {*/
+/* content: "\e005"*/
+/*}*/
+
+/*.glyphicon-star:before {*/
+/* content: "\e006"*/
+/*}*/
+
+/*.glyphicon-star-empty:before {*/
+/* content: "\e007"*/
+/*}*/
+
+/*.glyphicon-user:before {*/
+/* content: "\e008"*/
+/*}*/
+
+/*.glyphicon-film:before {*/
+/* content: "\e009"*/
+/*}*/
+
+/*.glyphicon-th-large:before {*/
+/* content: "\e010"*/
+/*}*/
+
+/*.glyphicon-th:before {*/
+/* content: "\e011"*/
+/*}*/
+
+/*.glyphicon-th-list:before {*/
+/* content: "\e012"*/
+/*}*/
+
+/*.glyphicon-ok:before {*/
+/* content: "\e013"*/
+/*}*/
+
+/*.glyphicon-remove:before {*/
+/* content: "\e014"*/
+/*}*/
+
+/*.glyphicon-zoom-in:before {*/
+/* content: "\e015"*/
+/*}*/
+
+/*.glyphicon-zoom-out:before {*/
+/* content: "\e016"*/
+/*}*/
+
+/*.glyphicon-off:before {*/
+/* content: "\e017"*/
+/*}*/
+
+/*.glyphicon-signal:before {*/
+/* content: "\e018"*/
+/*}*/
+
+/*.glyphicon-cog:before {*/
+/* content: "\e019"*/
+/*}*/
+
+/*.glyphicon-trash:before {*/
+/* content: "\e020"*/
+/*}*/
+
+/*.glyphicon-home:before {*/
+/* content: "\e021"*/
+/*}*/
+
+.glyphicon-file:before {
+ content: "\e022"
+}
+
+/*.glyphicon-time:before {*/
+/* content: "\e023"*/
+/*}*/
+
+/*.glyphicon-road:before {*/
+/* content: "\e024"*/
+/*}*/
+
+/*.glyphicon-download-alt:before {*/
+/* content: "\e025"*/
+/*}*/
+
+/*.glyphicon-download:before {*/
+/* content: "\e026"*/
+/*}*/
+
+/*.glyphicon-upload:before {*/
+/* content: "\e027"*/
+/*}*/
+
+/*.glyphicon-inbox:before {*/
+/* content: "\e028"*/
+/*}*/
+
+/*.glyphicon-play-circle:before {*/
+/* content: "\e029"*/
+/*}*/
+
+/*.glyphicon-repeat:before {*/
+/* content: "\e030"*/
+/*}*/
+
+.glyphicon-refresh:before {
+ content: "\e031"
+}
+
+/*.glyphicon-list-alt:before {*/
+/* content: "\e032"*/
+/*}*/
+
+/*.glyphicon-lock:before {*/
+/* content: "\e033"*/
+/*}*/
+
+/*.glyphicon-flag:before {*/
+/* content: "\e034"*/
+/*}*/
+
+/*.glyphicon-headphones:before {*/
+/* content: "\e035"*/
+/*}*/
+
+/*.glyphicon-volume-off:before {*/
+/* content: "\e036"*/
+/*}*/
+
+/*.glyphicon-volume-down:before {*/
+/* content: "\e037"*/
+/*}*/
+
+/*.glyphicon-volume-up:before {*/
+/* content: "\e038"*/
+/*}*/
+
+/*.glyphicon-qrcode:before {*/
+/* content: "\e039"*/
+/*}*/
+
+/*.glyphicon-barcode:before {*/
+/* content: "\e040"*/
+/*}*/
+
+/*.glyphicon-tag:before {*/
+/* content: "\e041"*/
+/*}*/
+
+/*.glyphicon-tags:before {*/
+/* content: "\e042"*/
+/*}*/
+
+/*.glyphicon-book:before {*/
+/* content: "\e043"*/
+/*}*/
+
+/*.glyphicon-bookmark:before {*/
+/* content: "\e044"*/
+/*}*/
+
+/*.glyphicon-print:before {*/
+/* content: "\e045"*/
+/*}*/
+
+/*.glyphicon-camera:before {*/
+/* content: "\e046"*/
+/*}*/
+
+/*.glyphicon-font:before {*/
+/* content: "\e047"*/
+/*}*/
+
+/*.glyphicon-bold:before {*/
+/* content: "\e048"*/
+/*}*/
+
+/*.glyphicon-italic:before {*/
+/* content: "\e049"*/
+/*}*/
+
+/*.glyphicon-text-height:before {*/
+/* content: "\e050"*/
+/*}*/
+
+/*.glyphicon-text-width:before {*/
+/* content: "\e051"*/
+/*}*/
+
+/*.glyphicon-align-left:before {*/
+/* content: "\e052"*/
+/*}*/
+
+/*.glyphicon-align-center:before {*/
+/* content: "\e053"*/
+/*}*/
+
+/*.glyphicon-align-right:before {*/
+/* content: "\e054"*/
+/*}*/
+
+/*.glyphicon-align-justify:before {*/
+/* content: "\e055"*/
+/*}*/
+
+/*.glyphicon-list:before {*/
+/* content: "\e056"*/
+/*}*/
+
+/*.glyphicon-indent-left:before {*/
+/* content: "\e057"*/
+/*}*/
+
+/*.glyphicon-indent-right:before {*/
+/* content: "\e058"*/
+/*}*/
+
+/*.glyphicon-facetime-video:before {*/
+/* content: "\e059"*/
+/*}*/
+
+/*.glyphicon-picture:before {*/
+/* content: "\e060"*/
+/*}*/
+
+/*.glyphicon-map-marker:before {*/
+/* content: "\e062"*/
+/*}*/
+
+/*.glyphicon-adjust:before {*/
+/* content: "\e063"*/
+/*}*/
+
+/*.glyphicon-tint:before {*/
+/* content: "\e064"*/
+/*}*/
+
+/*.glyphicon-edit:before {*/
+/* content: "\e065"*/
+/*}*/
+
+/*.glyphicon-share:before {*/
+/* content: "\e066"*/
+/*}*/
+
+.glyphicon-check:before {
+ content: "\e067"
+}
+
+/*.glyphicon-move:before {*/
+/* content: "\e068"*/
+/*}*/
+
+/*.glyphicon-step-backward:before {*/
+/* content: "\e069"*/
+/*}*/
+
+/*.glyphicon-fast-backward:before {*/
+/* content: "\e070"*/
+/*}*/
+
+/*.glyphicon-backward:before {*/
+/* content: "\e071"*/
+/*}*/
+
+.glyphicon-play:before {
+ content: "\e072"
+}
+
+/*.glyphicon-pause:before {*/
+/* content: "\e073"*/
+/*}*/
+
+/*.glyphicon-stop:before {*/
+/* content: "\e074"*/
+/*}*/
+
+/*.glyphicon-forward:before {*/
+/* content: "\e075"*/
+/*}*/
+
+/*.glyphicon-fast-forward:before {*/
+/* content: "\e076"*/
+/*}*/
+
+/*.glyphicon-step-forward:before {*/
+/* content: "\e077"*/
+/*}*/
+
+/*.glyphicon-eject:before {*/
+/* content: "\e078"*/
+/*}*/
+
+/*.glyphicon-chevron-left:before {*/
+/* content: "\e079"*/
+/*}*/
+
+/*.glyphicon-chevron-right:before {*/
+/* content: "\e080"*/
+/*}*/
+
+/*.glyphicon-plus-sign:before {*/
+/* content: "\e081"*/
+/*}*/
+
+/*.glyphicon-minus-sign:before {*/
+/* content: "\e082"*/
+/*}*/
+
+/*.glyphicon-remove-sign:before {*/
+/* content: "\e083"*/
+/*}*/
+
+/*.glyphicon-ok-sign:before {*/
+/* content: "\e084"*/
+/*}*/
+
+/*.glyphicon-question-sign:before {*/
+/* content: "\e085"*/
+/*}*/
+
+.glyphicon-info-sign:before {
+ content: "\e086"
+}
+
+/*.glyphicon-screenshot:before {*/
+/* content: "\e087"*/
+/*}*/
+
+.glyphicon-remove-circle:before {
+ content: "\e088"
+}
+
+/*.glyphicon-ok-circle:before {*/
+/* content: "\e089"*/
+/*}*/
+
+/*.glyphicon-ban-circle:before {*/
+/* content: "\e090"*/
+/*}*/
+
+/*.glyphicon-arrow-left:before {*/
+/* content: "\e091"*/
+/*}*/
+
+.glyphicon-arrow-right:before {
+ content: "\e092"
+}
+
+/*.glyphicon-arrow-up:before {*/
+/* content: "\e093"*/
+/*}*/
+
+/*.glyphicon-arrow-down:before {*/
+/* content: "\e094"*/
+/*}*/
+
+/*.glyphicon-share-alt:before {*/
+/* content: "\e095"*/
+/*}*/
+
+/*.glyphicon-resize-full:before {*/
+/* content: "\e096"*/
+/*}*/
+
+/*.glyphicon-resize-small:before {*/
+/* content: "\e097"*/
+/*}*/
+
+/*.glyphicon-exclamation-sign:before {*/
+/* content: "\e101"*/
+/*}*/
+
+/*.glyphicon-gift:before {*/
+/* content: "\e102"*/
+/*}*/
+
+/*.glyphicon-leaf:before {*/
+/* content: "\e103"*/
+/*}*/
+
+/*.glyphicon-fire:before {*/
+/* content: "\e104"*/
+/*}*/
+
+/*.glyphicon-eye-open:before {*/
+/* content: "\e105"*/
+/*}*/
+
+/*.glyphicon-eye-close:before {*/
+/* content: "\e106"*/
+/*}*/
+
+.glyphicon-warning-sign:before {
+ content: "\e107"
+}
+
+/*.glyphicon-plane:before {*/
+/* content: "\e108"*/
+/*}*/
+
+/*.glyphicon-calendar:before {*/
+/* content: "\e109"*/
+/*}*/
+
+/*.glyphicon-random:before {*/
+/* content: "\e110"*/
+/*}*/
+
+/*.glyphicon-comment:before {*/
+/* content: "\e111"*/
+/*}*/
+
+/*.glyphicon-magnet:before {*/
+/* content: "\e112"*/
+/*}*/
+
+/*.glyphicon-chevron-up:before {*/
+/* content: "\e113"*/
+/*}*/
+
+/*.glyphicon-chevron-down:before {*/
+/* content: "\e114"*/
+/*}*/
+
+/*.glyphicon-retweet:before {*/
+/* content: "\e115"*/
+/*}*/
+
+/*.glyphicon-shopping-cart:before {*/
+/* content: "\e116"*/
+/*}*/
+
+.glyphicon-folder-close:before {
+ content: "\e117"
+}
+
+.glyphicon-folder-open:before {
+ content: "\e118"
+}
+
+/*.glyphicon-resize-vertical:before {*/
+/* content: "\e119"*/
+/*}*/
+
+/*.glyphicon-resize-horizontal:before {*/
+/* content: "\e120"*/
+/*}*/
+
+/*.glyphicon-hdd:before {*/
+/* content: "\e121"*/
+/*}*/
+
+/*.glyphicon-bullhorn:before {*/
+/* content: "\e122"*/
+/*}*/
+
+/*.glyphicon-bell:before {*/
+/* content: "\e123"*/
+/*}*/
+
+/*.glyphicon-certificate:before {*/
+/* content: "\e124"*/
+/*}*/
+
+/*.glyphicon-thumbs-up:before {*/
+/* content: "\e125"*/
+/*}*/
+
+/*.glyphicon-thumbs-down:before {*/
+/* content: "\e126"*/
+/*}*/
+
+/*.glyphicon-hand-right:before {*/
+/* content: "\e127"*/
+/*}*/
+
+/*.glyphicon-hand-left:before {*/
+/* content: "\e128"*/
+/*}*/
+
+/*.glyphicon-hand-up:before {*/
+/* content: "\e129"*/
+/*}*/
+
+/*.glyphicon-hand-down:before {*/
+/* content: "\e130"*/
+/*}*/
+
+/*.glyphicon-circle-arrow-right:before {*/
+/* content: "\e131"*/
+/*}*/
+
+/*.glyphicon-circle-arrow-left:before {*/
+/* content: "\e132"*/
+/*}*/
+
+/*.glyphicon-circle-arrow-up:before {*/
+/* content: "\e133"*/
+/*}*/
+
+/*.glyphicon-circle-arrow-down:before {*/
+/* content: "\e134"*/
+/*}*/
+
+/*.glyphicon-globe:before {*/
+/* content: "\e135"*/
+/*}*/
+
+/*.glyphicon-wrench:before {*/
+/* content: "\e136"*/
+/*}*/
+
+/*.glyphicon-tasks:before {*/
+/* content: "\e137"*/
+/*}*/
+
+/*.glyphicon-filter:before {*/
+/* content: "\e138"*/
+/*}*/
+
+/*.glyphicon-briefcase:before {*/
+/* content: "\e139"*/
+/*}*/
+
+/*.glyphicon-fullscreen:before {*/
+/* content: "\e140"*/
+/*}*/
+
+/*.glyphicon-dashboard:before {*/
+/* content: "\e141"*/
+/*}*/
+
+/*.glyphicon-paperclip:before {*/
+/* content: "\e142"*/
+/*}*/
+
+/*.glyphicon-heart-empty:before {*/
+/* content: "\e143"*/
+/*}*/
+
+/*.glyphicon-link:before {*/
+/* content: "\e144"*/
+/*}*/
+
+/*.glyphicon-phone:before {*/
+/* content: "\e145"*/
+/*}*/
+
+/*.glyphicon-pushpin:before {*/
+/* content: "\e146"*/
+/*}*/
+
+/*.glyphicon-usd:before {*/
+/* content: "\e148"*/
+/*}*/
+
+/*.glyphicon-gbp:before {*/
+/* content: "\e149"*/
+/*}*/
+
+/*.glyphicon-sort:before {*/
+/* content: "\e150"*/
+/*}*/
+
+/*.glyphicon-sort-by-alphabet:before {*/
+/* content: "\e151"*/
+/*}*/
+
+/*.glyphicon-sort-by-alphabet-alt:before {*/
+/* content: "\e152"*/
+/*}*/
+
+/*.glyphicon-sort-by-order:before {*/
+/* content: "\e153"*/
+/*}*/
+
+/*.glyphicon-sort-by-order-alt:before {*/
+/* content: "\e154"*/
+/*}*/
+
+/*.glyphicon-sort-by-attributes:before {*/
+/* content: "\e155"*/
+/*}*/
+
+/*.glyphicon-sort-by-attributes-alt:before {*/
+/* content: "\e156"*/
+/*}*/
+
+.glyphicon-unchecked:before {
+ content: "\e157"
+}
+
+.glyphicon-expand:before {
+ content: "\e158"
+}
+
+/*.glyphicon-collapse-down:before {*/
+/* content: "\e159"*/
+/*}*/
+
+/*.glyphicon-collapse-up:before {*/
+/* content: "\e160"*/
+/*}*/
+
+/*.glyphicon-log-in:before {*/
+/* content: "\e161"*/
+/*}*/
+
+/*.glyphicon-flash:before {*/
+/* content: "\e162"*/
+/*}*/
+
+/*.glyphicon-log-out:before {*/
+/* content: "\e163"*/
+/*}*/
+
+/*.glyphicon-new-window:before {*/
+/* content: "\e164"*/
+/*}*/
+
+/*.glyphicon-record:before {*/
+/* content: "\e165"*/
+/*}*/
+
+/*.glyphicon-save:before {*/
+/* content: "\e166"*/
+/*}*/
+
+/*.glyphicon-open:before {*/
+/* content: "\e167"*/
+/*}*/
+
+/*.glyphicon-saved:before {*/
+/* content: "\e168"*/
+/*}*/
+
+/*.glyphicon-import:before {*/
+/* content: "\e169"*/
+/*}*/
+
+/*.glyphicon-export:before {*/
+/* content: "\e170"*/
+/*}*/
+
+/*.glyphicon-send:before {*/
+/* content: "\e171"*/
+/*}*/
+
+/*.glyphicon-floppy-disk:before {*/
+/* content: "\e172"*/
+/*}*/
+
+/*.glyphicon-floppy-saved:before {*/
+/* content: "\e173"*/
+/*}*/
+
+/*.glyphicon-floppy-remove:before {*/
+/* content: "\e174"*/
+/*}*/
+
+/*.glyphicon-floppy-save:before {*/
+/* content: "\e175"*/
+/*}*/
+
+/*.glyphicon-floppy-open:before {*/
+/* content: "\e176"*/
+/*}*/
+
+/*.glyphicon-credit-card:before {*/
+/* content: "\e177"*/
+/*}*/
+
+/*.glyphicon-transfer:before {*/
+/* content: "\e178"*/
+/*}*/
+
+/*.glyphicon-cutlery:before {*/
+/* content: "\e179"*/
+/*}*/
+
+/*.glyphicon-header:before {*/
+/* content: "\e180"*/
+/*}*/
+
+/*.glyphicon-compressed:before {*/
+/* content: "\e181"*/
+/*}*/
+
+/*.glyphicon-earphone:before {*/
+/* content: "\e182"*/
+/*}*/
+
+/*.glyphicon-phone-alt:before {*/
+/* content: "\e183"*/
+/*}*/
+
+/*.glyphicon-tower:before {*/
+/* content: "\e184"*/
+/*}*/
+
+/*.glyphicon-stats:before {*/
+/* content: "\e185"*/
+/*}*/
+
+/*.glyphicon-sd-video:before {*/
+/* content: "\e186"*/
+/*}*/
+
+/*.glyphicon-hd-video:before {*/
+/* content: "\e187"*/
+/*}*/
+
+/*.glyphicon-subtitles:before {*/
+/* content: "\e188"*/
+/*}*/
+
+/*.glyphicon-sound-stereo:before {*/
+/* content: "\e189"*/
+/*}*/
+
+/*.glyphicon-sound-dolby:before {*/
+/* content: "\e190"*/
+/*}*/
+
+/*.glyphicon-sound-5-1:before {*/
+/* content: "\e191"*/
+/*}*/
+
+/*.glyphicon-sound-6-1:before {*/
+/* content: "\e192"*/
+/*}*/
+
+/*.glyphicon-sound-7-1:before {*/
+/* content: "\e193"*/
+/*}*/
+
+/*.glyphicon-copyright-mark:before {*/
+/* content: "\e194"*/
+/*}*/
+
+/*.glyphicon-registration-mark:before {*/
+/* content: "\e195"*/
+/*}*/
+
+/*.glyphicon-cloud-download:before {*/
+/* content: "\e197"*/
+/*}*/
+
+/*.glyphicon-cloud-upload:before {*/
+/* content: "\e198"*/
+/*}*/
+
+/*.glyphicon-tree-conifer:before {*/
+/* content: "\e199"*/
+/*}*/
+
+/*.glyphicon-tree-deciduous:before {*/
+/* content: "\e200"*/
+/*}*/
+
+/*.glyphicon-cd:before {*/
+/* content: "\e201"*/
+/*}*/
+
+/*.glyphicon-save-file:before {*/
+/* content: "\e202"*/
+/*}*/
+
+/*.glyphicon-open-file:before {*/
+/* content: "\e203"*/
+/*}*/
+
+/*.glyphicon-level-up:before {*/
+/* content: "\e204"*/
+/*}*/
+
+/*.glyphicon-copy:before {*/
+/* content: "\e205"*/
+/*}*/
+
+/*.glyphicon-paste:before {*/
+/* content: "\e206"*/
+/*}*/
+
+/*.glyphicon-alert:before {*/
+/* content: "\e209"*/
+/*}*/
+
+/*.glyphicon-equalizer:before {*/
+/* content: "\e210"*/
+/*}*/
+
+/*.glyphicon-king:before {*/
+/* content: "\e211"*/
+/*}*/
+
+/*.glyphicon-queen:before {*/
+/* content: "\e212"*/
+/*}*/
+
+/*.glyphicon-pawn:before {*/
+/* content: "\e213"*/
+/*}*/
+
+/*.glyphicon-bishop:before {*/
+/* content: "\e214"*/
+/*}*/
+
+/*.glyphicon-knight:before {*/
+/* content: "\e215"*/
+/*}*/
+
+/*.glyphicon-baby-formula:before {*/
+/* content: "\e216"*/
+/*}*/
+
+/*.glyphicon-tent:before {*/
+/* content: "\26fa"*/
+/*}*/
+
+/*.glyphicon-blackboard:before {*/
+/* content: "\e218"*/
+/*}*/
+
+/*.glyphicon-bed:before {*/
+/* content: "\e219"*/
+/*}*/
+
+/*.glyphicon-apple:before {*/
+/* content: "\f8ff"*/
+/*}*/
+
+/*.glyphicon-erase:before {*/
+/* content: "\e221"*/
+/*}*/
+
+/*.glyphicon-hourglass:before {*/
+/* content: "\231b"*/
+/*}*/
+
+/*.glyphicon-lamp:before {*/
+/* content: "\e223"*/
+/*}*/
+
+/*.glyphicon-duplicate:before {*/
+/* content: "\e224"*/
+/*}*/
+
+/*.glyphicon-piggy-bank:before {*/
+/* content: "\e225"*/
+/*}*/
+
+/*.glyphicon-scissors:before {*/
+/* content: "\e226"*/
+/*}*/
+
+/*.glyphicon-bitcoin:before {*/
+/* content: "\e227"*/
+/*}*/
+
+/*.glyphicon-btc:before {*/
+/* content: "\e227"*/
+/*}*/
+
+/*.glyphicon-xbt:before {*/
+/* content: "\e227"*/
+/*}*/
+
+/*.glyphicon-yen:before {*/
+/* content: "\00a5"*/
+/*}*/
+
+/*.glyphicon-jpy:before {*/
+/* content: "\00a5"*/
+/*}*/
+
+/*.glyphicon-ruble:before {*/
+/* content: "\20bd"*/
+/*}*/
+
+/*.glyphicon-rub:before {*/
+/* content: "\20bd"*/
+/*}*/
+
+/*.glyphicon-scale:before {*/
+/* content: "\e230"*/
+/*}*/
+
+/*.glyphicon-ice-lolly:before {*/
+/* content: "\e231"*/
+/*}*/
+
+/*.glyphicon-ice-lolly-tasted:before {*/
+/* content: "\e232"*/
+/*}*/
+
+/*.glyphicon-education:before {*/
+/* content: "\e233"*/
+/*}*/
+
+/*.glyphicon-option-horizontal:before {*/
+/* content: "\e234"*/
+/*}*/
+
+/*.glyphicon-option-vertical:before {*/
+/* content: "\e235"*/
+/*}*/
+
+/*.glyphicon-menu-hamburger:before {*/
+/* content: "\e236"*/
+/*}*/
+
+/*.glyphicon-modal-window:before {*/
+/* content: "\e237"*/
+/*}*/
+
+/*.glyphicon-oil:before {*/
+/* content: "\e238"*/
+/*}*/
+
+/*.glyphicon-grain:before {*/
+/* content: "\e239"*/
+/*}*/
+
+/*.glyphicon-sunglasses:before {*/
+/* content: "\e240"*/
+/*}*/
+
+/*.glyphicon-text-size:before {*/
+/* content: "\e241"*/
+/*}*/
+
+/*.glyphicon-text-color:before {*/
+/* content: "\e242"*/
+/*}*/
+
+/*.glyphicon-text-background:before {*/
+/* content: "\e243"*/
+/*}*/
+
+/*.glyphicon-object-align-top:before {*/
+/* content: "\e244"*/
+/*}*/
+
+/*.glyphicon-object-align-bottom:before {*/
+/* content: "\e245"*/
+/*}*/
+
+/*.glyphicon-object-align-horizontal:before {*/
+/* content: "\e246"*/
+/*}*/
+
+/*.glyphicon-object-align-left:before {*/
+/* content: "\e247"*/
+/*}*/
+
+/*.glyphicon-object-align-vertical:before {*/
+/* content: "\e248"*/
+/*}*/
+
+/*.glyphicon-object-align-right:before {*/
+/* content: "\e249"*/
+/*}*/
+
+/*.glyphicon-triangle-right:before {*/
+/* content: "\e250"*/
+/*}*/
+
+/*.glyphicon-triangle-left:before {*/
+/* content: "\e251"*/
+/*}*/
+
+/*.glyphicon-triangle-bottom:before {*/
+/* content: "\e252"*/
+/*}*/
+
+/*.glyphicon-triangle-top:before {*/
+/* content: "\e253"*/
+/*}*/
+
+/*.glyphicon-console:before {*/
+/* content: "\e254"*/
+/*}*/
+
+/*.glyphicon-superscript:before {*/
+/* content: "\e255"*/
+/*}*/
+
+/*.glyphicon-subscript:before {*/
+/* content: "\e256"*/
+/*}*/
+
+/*.glyphicon-menu-left:before {*/
+/* content: "\e257"*/
+/*}*/
+
+.glyphicon-menu-right:before {
+ content: "\e258"
+}
+
+.glyphicon-menu-down:before {
+ content: "\e259"
+}
+
+/*.glyphicon-menu-up:before {*/
+/* content: "\e260"*/
+/*}*/
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.css
new file mode 100644
index 0000000..81e1090
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.css
@@ -0,0 +1,680 @@
+/*!
+ * Fancytree "bootstrap" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #333333;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 16px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0em 0em;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-bootstrap/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 1em;
+ height: 1em;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-position: 0em 0em;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 2px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 1em;
+ height: 1em;
+ display: inline-block;
+ margin-left: 0.5em;
+ background-position: 0em 0em;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 1em;
+ height: 1em;
+ margin-left: 0.5em;
+ margin-top: 2px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ margin-top: 0;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 0.5em;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 0.5em;
+}
+/* Documents */
+/* Folders */
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: none;
+}
+/* Status node icons */
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 0px;
+ min-height: 1em;
+}
+span.fancytree-title {
+ color: #333333;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 1em;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 0.5em;
+ border: 1px solid transparent;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ -ms-border-radius: 3px;
+ -o-border-radius: 3px;
+ border-radius: 3px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: #d9534f;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 2em;
+ position: absolute;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 4em;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-bootstrap/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #333333;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: #d9534f;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0em 0em;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #333333;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #333333;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Plain tree
+ * Modifier classes on <ul> container:
+ * table-hover : Enable a light mouse hover effect
+ * fancytree-colorize-selected: Give selected (checked) rows a color
+ */
+ul.fancytree-container ul {
+ padding: 0 0 0 1.5em;
+ margin: 0;
+}
+/* Prevent focus frame */
+.fancytree-container:focus {
+ outline: none;
+}
+.fancytree-container .fancytree-active span.fancytree-title input,
+.fancytree-container.fancytree-colorize-selected .fancytree-selected span.fancytree-title input {
+ color: black;
+}
+.fancytree-container span.fancytree-statusnode-error span.fancytree-expander {
+ color: #d9534f;
+}
+div.fancytree-drag-helper.fancytree-drop-reject,
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-title {
+ color: #d9534f;
+}
+span.fancytree-node.fancytree-drag-source {
+ background-color: #5bc0de !important;
+}
+span.fancytree-node.fancytree-drop-target.fancytree-drop-reject span.fancytree.title {
+ background-color: #d9534f !important;
+}
+span.fancytree-expander {
+ color: #999;
+}
+.fancytree-expanded span.fancytree-expander {
+ color: #333333;
+}
+span.fancytree-node span.fancytree-expander:hover {
+ color: cyan;
+}
+.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected,
+.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected span.fancytree-title {
+ background-color: #80c780;
+ border-color: #80c780;
+ color: #fff;
+}
+.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected:hover span.fancytree-title {
+ background-color: #6ec06e;
+}
+.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title {
+ color: #80c780;
+}
+.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-title:hover {
+ background-color: #f5f5f5;
+}
+.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-selected span.fancytree-title {
+ background-color: #5cb85c;
+}
+.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-selected:hover span.fancytree-title {
+ background-color: #4cae4c;
+}
+.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title {
+ color: #5cb85c;
+}
+.fancytree-plain.fancytree-container span.fancytree-node {
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+.fancytree-plain.fancytree-container span.fancytree-title {
+ border: 1px solid transparent;
+ border-radius: 3px;
+ outline-radius: 3px;
+}
+.fancytree-plain.fancytree-container span.fancytree-title:hover {
+ background-color: #f5f5f5;
+}
+.fancytree-plain.fancytree-container span.fancytree-node.fancytree-active span.fancytree-title {
+ background-color: #5094ce;
+ color: #fff;
+}
+.fancytree-plain.fancytree-container span.fancytree-node.fancytree-active:hover span.fancytree-title {
+ background-color: #3c87c8;
+}
+.fancytree-plain.fancytree-container.fancytree-ext-wide span.fancytree-node.fancytree-active {
+ color: #fff;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused span.fancytree-title {
+ border-color: #337ab7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active span.fancytree-title {
+ background-color: #337ab7;
+ border-color: #337ab7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active:hover span.fancytree-title {
+ background-color: #2e6da4;
+}
+/*******************************************************************************
+ * 'table' extension
+ * Modifier classes on <table>:
+ * table-hover : Enable a light mouse hover effect
+ * fancytree-colorize-selected: Give selected (checked) rows a color
+ */
+table.fancytree-ext-table > tbody > tr > td span.fancytree-title {
+ border: none;
+}
+table.fancytree-ext-table.fancytree-colorize-selected > tbody > tr.fancytree-selected > td {
+ background-color: #80c780;
+}
+table.fancytree-ext-table.fancytree-colorize-selected > tbody > tr.fancytree-selected > td,
+table.fancytree-ext-table.fancytree-colorize-selected > tbody > tr.fancytree-selected > td span.fancytree-title {
+ color: #fff;
+}
+table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus > tbody > tr.fancytree-selected > td {
+ background-color: #5cb85c;
+}
+table.fancytree-ext-table.fancytree-colorize-selected.table-hover > tbody > tr.fancytree-selected:hover > td {
+ background-color: #6ec06e;
+}
+table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus.table-hover > tbody > tr.fancytree-selected:hover > td {
+ background-color: #4cae4c;
+}
+table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus.table-hover > tbody > tr.fancytree-selected.fancytree-active:hover > td,
+table.fancytree-ext-table.fancytree-colorize-selected.table-hover > tbody > tr.fancytree-selected.fancytree-active:hover > td {
+ background-color: #2e6da4;
+}
+table.fancytree-ext-table.fancytree-colorize-selected > tbody > tr.fancytree-active.fancytree-selected {
+ outline-width: 2px;
+ outline-offset: -2px;
+ outline-style: solid;
+ outline-color: #80c780;
+}
+table.fancytree-ext-table.fancytree-container > tbody > tr.fancytree-active > td {
+ background-color: #5094ce;
+}
+table.fancytree-ext-table.fancytree-container > tbody > tr.fancytree-active > td,
+table.fancytree-ext-table.fancytree-container > tbody > tr.fancytree-active > td span.fancytree-title {
+ color: #fff;
+}
+table.fancytree-ext-table.fancytree-treefocus.fancytree-container > tbody > tr.fancytree-focused span.fancytree-title {
+ outline: 1px dotted #000;
+}
+table.fancytree-ext-table.fancytree-treefocus.fancytree-container > tbody > tr.fancytree-active > td {
+ background-color: #337ab7;
+}
+table.fancytree-ext-table.fancytree-treefocus.fancytree-container.table-hover > tbody > tr.fancytree-active:hover > td {
+ background-color: #2e6da4;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.less
new file mode 100644
index 0000000..d2ad725
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.less
@@ -0,0 +1,356 @@
+/*!
+ * Fancytree "bootstrap" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+
+// local vars
+// @fancy-my-icon-size: 16px;
+
+//------------------------------------------------------------------------------
+// Original bootstrap colors
+// See http://getbootstrap.com/css/#less-variables-colors and
+// https://github.com/twbs/bootstrap/blob/master/less/variables.less
+@gray-base: #000;
+@gray-darker: lighten(@gray-base, 13.5%); // #222
+@gray-dark: lighten(@gray-base, 20%); // #333
+@gray: lighten(@gray-base, 33.5%); // #555
+@gray-light: lighten(@gray-base, 46.7%); // #777
+@gray-lighter: lighten(@gray-base, 93.5%); // #eee
+
+@brand-primary: darken(#428bca, 6.5%); // blue, #337ab7
+@brand-success: #5cb85c; // green
+@brand-info: #5bc0de; // light blue
+@brand-warning: #f0ad4e; // orange
+@brand-danger: #d9534f; // red
+
+@font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
+@font-family-serif: Georgia, "Times New Roman", Times, serif;
+//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
+@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
+@font-family-base: @font-family-sans-serif;
+
+@font-size-base: 14px;
+@font-size-large: ceil((@font-size-base * 1.25)); // ~18px
+@font-size-small: ceil((@font-size-base * 0.85)); // ~12px
+
+@border-radius-base: 4px;
+@border-radius-large: 6px;
+@border-radius-small: 3px;
+
+@text-color: @gray-dark;
+//** Default background color used for all tables.
+@table-bg: transparent;
+//** Background color used for `.table-striped`.
+@table-bg-accent: #f9f9f9;
+//** Background color used for `.table-hover`.
+@table-bg-hover: #f5f5f5;
+@table-bg-active: @table-bg-hover;
+
+//** Border color for table and cell borders.
+@table-border-color: #ddd;
+
+//------------------------------------------------------------------------------
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: false; // false: suppress all background images (i.e. icons)
+@fancy-loading-url: none;
+
+@fancy-line-height: 1em; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 0px; // gap between two node borders
+@fancy-icon-width: 1em;
+@fancy-icon-height: 1em;
+@fancy-icon-spacing: 0.5em; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 2px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: @border-radius-small;
+@fancy-node-outline-width: 1px;
+
+@fancy-font-family: @font-family-base;
+@fancy-font-size: @font-size-base;
+@fancy-font-color: @text-color;
+@fancy-font-color-dimm: @gray-dark;
+@fancy-font-error-color: @brand-danger;
+
+@fancy-active-text: #fff;
+@fancy-active-color: @brand-primary;
+@fancy-select-color: @brand-success;
+@fancy-hover-color: @table-bg-hover;
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-bootstrap/";
+
+/*******************************************************************************
+ * Plain tree
+ * Modifier classes on <ul> container:
+ * table-hover : Enable a light mouse hover effect
+ * fancytree-colorize-selected: Give selected (checked) rows a color
+ */
+ul.fancytree-container ul {
+ padding: 0 0 0 1.5em;
+ margin: 0;
+}
+/* Prevent focus frame */
+.fancytree-container:focus {
+ outline: none;
+}
+
+// Active and (optionally) selected nodes are white on colored bg. Undo this for input controls:
+.fancytree-container .fancytree-active span.fancytree-title input,
+.fancytree-container.fancytree-colorize-selected .fancytree-selected span.fancytree-title input {
+ color: black;
+}
+
+// Error status node
+.fancytree-container span.fancytree-statusnode-error span.fancytree-expander {
+ color: @fancy-font-error-color;
+}
+
+// set icon color to font color as well
+span.fancytree-node {
+ color: @fancy-font-color;
+}
+
+//// ------------------------------------------------------------------------------
+//// * Drag'n'drop support
+//// *----------------------------------------------------------------------------
+//// div.fancytree-drag-helper {
+//// }
+//// div.fancytree-drag-helper a {
+//// border: 1px solid gray;
+//// background-color: white;
+//// padding-left: 5px;
+//// padding-right: 5px;
+//// opacity: 0.8;
+//// }
+//// span.fancytree-drag-helper-img {
+//// // position: relative;
+//// // left: -16px;
+//// }
+//div.fancytree-drag-helper.fancytree-drop-reject,
+//div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-title
+//{
+// color: @fancy-font-error-color;
+//}
+//// div.fancytree-drop-accept span.fancytree-drag-helper-img {
+//// .useSprite(2, 7);
+//// }
+//// div.fancytree-drop-reject span.fancytree-drag-helper-img {
+//// .useSprite(1, 7);
+//// }
+//
+//// //--- Drop marker icon ---------------------------------------------------------
+//// #fancytree-drop-marker {
+//// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+//// position: absolute;
+//// .useSprite(0, 8);
+//// margin: 0;
+//// &.fancytree-drop-after,
+//// &.fancytree-drop-before {
+//// width: 4 * @fancy-icon-width; // 64px;
+//// .useSprite(0, 9);
+//// }
+//// &.fancytree-drop-copy {
+//// .useSprite(4, 8);
+//// }
+//// &.fancytree-drop-move {
+//// .useSprite(2, 8);
+//// }
+//// }
+////
+////--- Source node while dragging -----------------------------------------------
+//
+//span.fancytree-node.fancytree-drag-source {
+// background-color: @brand-info !important;
+// span.fancytree.title {
+// // outline: 1px solid @brand-info;
+// // color: @brand-primary;
+// }
+//}
+//
+////--- Target node while dragging cursor is over it -----------------------------
+//
+//span.fancytree-node.fancytree-drop-target {
+// &.fancytree-drop-accept span.fancytree.title {
+// // background-color: @brand-danger !important;
+// // outline: 1px solid @brand-success;
+// // color: white !important;
+// }
+// &.fancytree-drop-reject span.fancytree.title {
+// background-color: @brand-danger !important;
+// // outline: 1px solid @brand-danger;
+// // color: white !important;
+// }
+//}
+//
+//span.fancytree-expander {
+// color: #999; // colpased expander is gray
+//}
+//.fancytree-expanded span.fancytree-expander {
+// color: @fancy-font-color;
+//}
+//span.fancytree-node span.fancytree-expander:hover {
+// color: cyan;
+//}
+
+// Inactive tree:
+.fancytree-plain {
+ &.fancytree-colorize-selected {
+ span.fancytree-node.fancytree-selected,
+ span.fancytree-node.fancytree-selected span.fancytree-title { // selected nodes inside inactive tree
+ background-color: lighten(@fancy-select-color, 10%);
+ border-color: lighten(@fancy-select-color, 10%);
+ color: @fancy-active-text;
+ }
+ span.fancytree-node.fancytree-selected:hover span.fancytree-title {
+ background-color: lighten(@fancy-select-color, 5%);
+ }
+ span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title { // active nodes inside inactive tree
+ color: lighten(@fancy-select-color, 10%);
+ }
+ &.fancytree-treefocus {
+ span.fancytree-title:hover {
+ background-color: @fancy-hover-color;
+ }
+ span.fancytree-node.fancytree-selected span.fancytree-title {
+ background-color: @fancy-select-color;
+ }
+ span.fancytree-node.fancytree-selected:hover span.fancytree-title {
+ background-color: darken(@fancy-select-color, 5%);
+ }
+ span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title {
+ color: @fancy-select-color;
+ }
+ }
+ }
+
+ &.fancytree-container { // adding this class to increase specificity, so we can override .fancytree-colorize-selected
+ span.fancytree-node {
+ margin-top: 2px;
+ margin-bottom: 2px;
+ }
+ span.fancytree-title {
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ border-radius: @border-radius-small;
+ outline-radius: @border-radius-small;
+ }
+ span.fancytree-title:hover {
+ background-color: @fancy-hover-color;
+ }
+ span.fancytree-node.fancytree-active span.fancytree-title { // active nodes inside inactive tree
+ background-color: lighten(@fancy-active-color, 10%);
+ color: @fancy-active-text;
+ }
+ span.fancytree-node.fancytree-active:hover span.fancytree-title {
+ background-color: lighten(@fancy-active-color, 5%);
+ }
+ &.fancytree-ext-wide span.fancytree-node.fancytree-active { // in wide mode, icons of active nodes must be white-on-color
+ color: @fancy-active-text;
+ }
+
+ // Active tree:
+ &.fancytree-treefocus {
+ span.fancytree-node.fancytree-focused span.fancytree-title {
+ border-color: @brand-primary;
+ }
+ span.fancytree-node.fancytree-active span.fancytree-title {
+ background-color: @fancy-active-color;
+ border-color: @fancy-active-color;
+ }
+ span.fancytree-node.fancytree-active:hover span.fancytree-title {
+ background-color: darken(@fancy-active-color, 5%);
+ }
+ }
+ }
+}
+
+///*******************************************************************************
+// * 'table' extension
+// * Modifier classes on <table>:
+// * table-hover : Enable a light mouse hover effect
+// * fancytree-colorize-selected: Give selected (checked) rows a color
+// */
+//table.fancytree-ext-table {
+// >tbody >tr >td span.fancytree-title {
+// border: none;
+// }
+//
+// // Give a separate color for selected (checked) rows
+// // Define *before* the .fancytree-active rules, because active color should
+// // override selected color.
+// &.fancytree-colorize-selected {
+// >tbody >tr.fancytree-selected >td {
+// // dimmed, if inside inactive tree
+// background-color: lighten(@fancy-select-color, 10%);
+// // white text for selected nodes
+// &,
+// span.fancytree-title {
+// color: @fancy-active-text;
+// }
+// }
+// &.fancytree-treefocus >tbody >tr.fancytree-selected >td {
+// background-color: @fancy-select-color;
+// }
+// &.table-hover >tbody >tr.fancytree-selected:hover >td {
+// // dimmed, if inside inactive tree
+// background-color: lighten(@fancy-select-color, 5%);
+// }
+// &.fancytree-treefocus.table-hover >tbody >tr.fancytree-selected:hover >td {
+// background-color: darken(@fancy-select-color, 5%);
+// }
+// &.fancytree-treefocus.table-hover >tbody >tr.fancytree-selected.fancytree-active:hover >td,
+// &.table-hover >tbody >tr.fancytree-selected.fancytree-active:hover >td {
+// background-color: darken(@fancy-active-color, 5%);
+// }
+// >tbody >tr.fancytree-active.fancytree-selected {
+// outline-width: 2px;
+// outline-offset: -2px;
+// outline-style: solid;
+// outline-color: lighten(@fancy-select-color, 10%);
+// }
+// }
+//
+// // General tree (slightly dimmed, since we also define colors for inactive
+// // mode here).
+//
+// &.fancytree-container >tbody >tr.fancytree-active >td {
+// background-color: lighten(@fancy-active-color, 10%);
+// // white text for selected nodes
+// &,
+// span.fancytree-title {
+// color: @fancy-active-text;
+// }
+// }
+//
+// // Reset to standard colors if tree has keyboard focus.
+// // We add .fancytree-container to increase specificity, so we can override
+// // .fancytree-colorize-selected defined above
+//
+// &.fancytree-treefocus.fancytree-container {
+// >tbody >tr.fancytree-focused span.fancytree-title {
+// outline: 1px dotted #000;
+// }
+// >tbody >tr.fancytree-active >td {
+// background-color: @fancy-active-color;
+// }
+// &.table-hover >tbody >tr.fancytree-active:hover >td {
+// background-color: darken(@fancy-active-color, 5%);
+// }
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.min.css
new file mode 100644
index 0000000..60f01d7
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "bootstrap" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:#333}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-bootstrap/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:1em;height:1em;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:2px}span.fancytree-custom-icon{width:1em;height:1em;display:inline-block;margin-left:.5em;background-position:0 0}img.fancytree-icon{width:1em;height:1em;margin-left:.5em;margin-top:2px;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{margin-top:0}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:.5em}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:.5em}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:none}span.fancytree-node{display:inherit;width:100%;margin-top:0;min-height:1em}span.fancytree-title{color:#333;cursor:pointer;display:inline-block;vertical-align:top;min-height:1em;padding:0 3px 0 3px;margin:0 0 0 .5em;border:1px solid transparent;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}span.fancytree-node.fancytree-error span.fancytree-title{color:#d9534f}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}#fancytree-drop-marker{width:2em;position:absolute;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:4em}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-bootstrap/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}table.fancytree-ext-table{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:#333}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:#d9534f}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:#333;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:#333;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}ul.fancytree-container ul{padding:0 0 0 1.5em;margin:0}.fancytree-container:focus{outline:0}.fancytree-container .fancytree-active span.fancytree-title input,.fancytree-container.fancytree-colorize-selected .fancytree-selected span.fancytree-title input{color:#000}.fancytree-container span.fancytree-statusnode-error span.fancytree-expander{color:#d9534f}div.fancytree-drag-helper.fancytree-drop-reject,div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-title{color:#d9534f}span.fancytree-node.fancytree-drag-source{background-color:#5bc0de!important}span.fancytree-node.fancytree-drop-target.fancytree-drop-reject span.fancytree.title{background-color:#d9534f!important}span.fancytree-expander{color:#999}.fancytree-expanded span.fancytree-expander{color:#333}span.fancytree-node span.fancytree-expander:hover{color:#0ff}.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected,.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected span.fancytree-title{background-color:#80c780;border-color:#80c780;color:#fff}.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-selected:hover span.fancytree-title{background-color:#6ec06e}.fancytree-plain.fancytree-colorize-selected span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title{color:#80c780}.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-title:hover{background-color:#f5f5f5}.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-selected span.fancytree-title{background-color:#5cb85c}.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-selected:hover span.fancytree-title{background-color:#4cae4c}.fancytree-plain.fancytree-colorize-selected.fancytree-treefocus span.fancytree-node.fancytree-active.fancytree-selected span.fancytree-title{color:#5cb85c}.fancytree-plain.fancytree-container span.fancytree-node{margin-top:2px;margin-bottom:2px}.fancytree-plain.fancytree-container span.fancytree-title{border:1px solid transparent;border-radius:3px;outline-radius:3px}.fancytree-plain.fancytree-container span.fancytree-title:hover{background-color:#f5f5f5}.fancytree-plain.fancytree-container span.fancytree-node.fancytree-active span.fancytree-title{background-color:#5094ce;color:#fff}.fancytree-plain.fancytree-container span.fancytree-node.fancytree-active:hover span.fancytree-title{background-color:#3c87c8}.fancytree-plain.fancytree-container.fancytree-ext-wide span.fancytree-node.fancytree-active{color:#fff}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused span.fancytree-title{border-color:#337ab7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active span.fancytree-title{background-color:#337ab7;border-color:#337ab7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active:hover span.fancytree-title{background-color:#2e6da4}table.fancytree-ext-table>tbody>tr>td span.fancytree-title{border:none}table.fancytree-ext-table.fancytree-colorize-selected>tbody>tr.fancytree-selected>td{background-color:#80c780}table.fancytree-ext-table.fancytree-colorize-selected>tbody>tr.fancytree-selected>td,table.fancytree-ext-table.fancytree-colorize-selected>tbody>tr.fancytree-selected>td span.fancytree-title{color:#fff}table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus>tbody>tr.fancytree-selected>td{background-color:#5cb85c}table.fancytree-ext-table.fancytree-colorize-selected.table-hover>tbody>tr.fancytree-selected:hover>td{background-color:#6ec06e}table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus.table-hover>tbody>tr.fancytree-selected:hover>td{background-color:#4cae4c}table.fancytree-ext-table.fancytree-colorize-selected.fancytree-treefocus.table-hover>tbody>tr.fancytree-selected.fancytree-active:hover>td,table.fancytree-ext-table.fancytree-colorize-selected.table-hover>tbody>tr.fancytree-selected.fancytree-active:hover>td{background-color:#2e6da4}table.fancytree-ext-table.fancytree-colorize-selected>tbody>tr.fancytree-active.fancytree-selected{outline-width:2px;outline-offset:-2px;outline-style:solid;outline-color:#80c780}table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td{background-color:#5094ce}table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td,table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td span.fancytree-title{color:#fff}table.fancytree-ext-table.fancytree-treefocus.fancytree-container>tbody>tr.fancytree-focused span.fancytree-title{outline:1px dotted #000}table.fancytree-ext-table.fancytree-treefocus.fancytree-container>tbody>tr.fancytree-active>td{background-color:#337ab7}table.fancytree-ext-table.fancytree-treefocus.fancytree-container.table-hover>tbody>tr.fancytree-active:hover>td{background-color:#2e6da4} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/vline-rtl.gif
new file mode 100644
index 0000000..0400cb3
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/vline.gif
new file mode 100644
index 0000000..1b00ae5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-bootstrap/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-common.less
new file mode 100644
index 0000000..c1f9690
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-custom-1/README.md b/plugins/55/indexmenu/scripts/fancytree/skin-custom-1/README.md
new file mode 100644
index 0000000..c1703a7
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-custom-1/README.md
@@ -0,0 +1,14 @@
+### Creating Custom Skins
+
+1. Create a folder like this (recommended name: 'src/skin-custom-...')
+2. For a start, copy files from one of the existing skin folders (src/skin-...)
+ to the custom folder:
+ - ui.fancytree.less (required)
+ - icons.gif (if needed)
+ - loading.gif (if needed)
+3. cd to your fancytree folder and run `grunt dev` from the console.<br>
+ Note: NPM and Grunt are required.
+ Read [how to install the toolset](https://github.com/mar10/fancytree/wiki/HowtoContribute#install-the-source-code-and-tools-for-debugging-and-contributing).
+4. Edit and save your ui.fancytree.less file.<br>
+ The `ui.fancytree.css` will be generated and updated automatically from
+ the LESS file.
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-lion/icons-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-lion/icons-rtl.gif
new file mode 100644
index 0000000..a4eeb9e
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-lion/icons-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-lion/icons.gif b/plugins/55/indexmenu/scripts/fancytree/skin-lion/icons.gif
new file mode 100644
index 0000000..1ca2af6
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-lion/icons.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-lion/loading.gif b/plugins/55/indexmenu/scripts/fancytree/skin-lion/loading.gif
new file mode 100644
index 0000000..5b33f7e
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-lion/loading.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-lion/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-lion/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-lion/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.css
new file mode 100644
index 0000000..708fb69
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.css
@@ -0,0 +1,757 @@
+/*!
+ * Fancytree "Lion" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*
+ Lion colors:
+ gray highlight bar: #D4D4D4
+ blue highlight-bar and -border #3875D7
+
+*/
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #c0c0c0;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 16px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-lion/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-image: url("../skin-lion/icons.gif");
+ background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 0px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 16px;
+ height: 16px;
+ margin-left: 3px;
+ margin-top: 0px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-lion/icons.gif");
+ margin-top: 0;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover {
+ background-position: 0px -64px;
+}
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover {
+ background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+ background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+ background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+ background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+ background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+ background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ background-position: -48px -96px;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 3px;
+ background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+ background-position: -16px -32px;
+}
+span.fancytree-checkbox.fancytree-radio {
+ background-position: 0px -48px;
+}
+span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -16px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+ background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -80px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio {
+ background-position: -64px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -80px -48px;
+}
+.fancytree-selected span.fancytree-checkbox {
+ background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -48px -32px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio {
+ background-position: -32px -48px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -48px -48px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+ background-position: 0px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: 0px -48px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -32px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -32px -48px;
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+ background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+ background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: url("../skin-lion/loading.gif");
+ background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 1px;
+ min-height: 16px;
+}
+span.fancytree-title {
+ color: black;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 16px;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 3px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+ background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+ background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 32px;
+ position: absolute;
+ background-position: 0px -128px;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 64px;
+ background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+ background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+ background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl span.fancytree-connector,
+.fancytree-container.fancytree-rtl span.fancytree-expander,
+.fancytree-container.fancytree-rtl span.fancytree-icon,
+.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img {
+ background-image: url("../skin-lion/icons-rtl.gif");
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-lion/icons-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-lion/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+#fancytree-drop-marker.fancytree-rtl {
+ background-image: url("../skin-lion/icons-rtl.gif");
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #c0c0c0;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+ background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+ background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+ border: 1px solid transparent;
+ border-radius: 0;
+}
+span.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+}
+span.fancytree-selected span.fancytree-title,
+span.fancytree-active span.fancytree-title {
+ background-color: #D4D4D4;
+}
+span.fancytree-selected span.fancytree-title {
+ font-style: italic;
+}
+.fancytree-treefocus span.fancytree-selected span.fancytree-title,
+.fancytree-treefocus span.fancytree-active span.fancytree-title {
+ color: white;
+ background-color: #3875D7;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+ border-collapse: collapse;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused {
+ background-color: #99DEFD;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+ background-color: royalblue;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+ background-color: #99DEFD;
+}
+/*******************************************************************************
+ * 'columnview' extension
+ */
+table.fancytree-ext-columnview tbody tr td {
+ border: 1px solid gray;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #ccc;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: royalblue;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.less
new file mode 100644
index 0000000..aa511e3
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.less
@@ -0,0 +1,100 @@
+ /*!
+ * Fancytree "Lion" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+/*
+ Lion colors:
+ gray highlight bar: #D4D4D4
+ blue highlight-bar and -border #3875D7
+
+*/
+// Import common styles
+@import "skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-line-height: 16px;
+@fancy-icon-spacing: 3px;
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-lion/";
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%;
+
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+ border: 1px solid transparent; // reserve some space for status borders
+ border-radius: 0;
+}
+span.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+}
+span.fancytree-selected span.fancytree-title,
+span.fancytree-active span.fancytree-title {
+ background-color: #D4D4D4; // gray
+}
+span.fancytree-selected span.fancytree-title {
+ font-style: italic;
+}
+.fancytree-treefocus span.fancytree-selected span.fancytree-title,
+.fancytree-treefocus span.fancytree-active span.fancytree-title {
+ color: white;
+ background-color: #3875D7; // blue
+}
+
+///*******************************************************************************
+// * 'table' extension
+// */
+//table.fancytree-ext-table {
+// border-collapse: collapse;
+// tbody {
+// tr.fancytree-focused {
+// background-color: #99DEFD;
+// }
+// tr.fancytree-active {
+// background-color: royalblue;
+// }
+// tr.fancytree-selected {
+// background-color: #99DEFD;
+// }
+// }
+//}
+//
+///*******************************************************************************
+// * 'columnview' extension
+// */
+//
+//table.fancytree-ext-columnview tbody tr td {
+// border: 1px solid gray;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+// background-color: #ccc;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+// background-color: royalblue;
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.min.css
new file mode 100644
index 0000000..6fa65e0
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-lion/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "Lion" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-lion/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url("../skin-lion/icons.gif");background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:0}span.fancytree-custom-icon{width:16px;height:16px;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-lion/icons.gif");margin-top:0}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}span.fancytree-checkbox.fancytree-radio{background-position:0 -48px}span.fancytree-checkbox.fancytree-radio:hover{background-position:-16px -48px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio{background-position:-64px -48px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover{background-position:-80px -48px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-selected span.fancytree-checkbox.fancytree-radio{background-position:-32px -48px}.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-48px -48px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover{background-position:0 -48px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-32px -48px}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:url("../skin-lion/loading.gif");background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:16px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:16px;padding:0 3px 0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl span.fancytree-connector,.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,.fancytree-container.fancytree-rtl span.fancytree-expander,.fancytree-container.fancytree-rtl span.fancytree-icon{background-image:url("../skin-lion/icons-rtl.gif")}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-lion/icons-rtl.gif")}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-lion/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}#fancytree-drop-marker.fancytree-rtl{background-image:url("../skin-lion/icons-rtl.gif")}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}span.fancytree-title{border:1px solid transparent;border-radius:0}span.fancytree-focused span.fancytree-title{outline:1px dotted black}span.fancytree-active span.fancytree-title,span.fancytree-selected span.fancytree-title{background-color:#d4d4d4}span.fancytree-selected span.fancytree-title{font-style:italic}.fancytree-treefocus span.fancytree-active span.fancytree-title,.fancytree-treefocus span.fancytree-selected span.fancytree-title{color:#fff;background-color:#3875d7}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table tbody tr.fancytree-focused{background-color:#99defd}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#4169e1}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#99defd}table.fancytree-ext-columnview tbody tr td{border:1px solid gray}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#ccc}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#4169e1} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-lion/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-lion/vline-rtl.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-lion/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-lion/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-lion/vline.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-lion/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-material/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-material/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-material/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.css
new file mode 100644
index 0000000..e104e1a
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.css
@@ -0,0 +1,581 @@
+/*!
+ * Fancytree "material" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: silver;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: "Roboto Regular", tahoma, arial, helvetica;
+ font-size: 24px;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 24px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-material/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 24px;
+ height: 24px;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 0px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 24px;
+ height: 24px;
+ display: inline-block;
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 24px;
+ height: 24px;
+ margin-left: 3px;
+ margin-top: 0px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ margin-top: 0;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 3px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 3px;
+}
+/* Documents */
+/* Folders */
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: none;
+}
+/* Status node icons */
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 1px;
+ min-height: 24px;
+}
+span.fancytree-title {
+ color: #212121;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 24px;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 3px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 48px;
+ position: absolute;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 96px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-material/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: "Roboto Regular", tahoma, arial, helvetica;
+ font-size: 24px;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: silver;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: silver;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: silver;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*
+https://material.io/guidelines/components/data-tables.html#data-tables-structure
+*/
+ul.fancytree-container ul {
+ padding: 0.3em 0 0 1em;
+ margin: 0;
+ font-size: 24px;
+ color: #212121;
+}
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain span.fancytree-selected span.fancytree-title {
+ background-color: #f5f5f5;
+}
+.fancytree-plain span.fancytree-selected span.fancytree-title:hover,
+.fancytree-plain span.fancytree-active span.fancytree-title {
+ background-color: #eeeeee;
+}
+.fancytree-container span.fancytree-checkbox {
+ color: #ff4081;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+ border-collapse: collapse;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused,
+table.fancytree-ext-table tbody tr.fancytree-selected {
+ background-color: #f5f5f5;
+}
+table.fancytree-ext-table tbody tr.fancytree-active,
+table.fancytree-ext-table tbody tr:hover {
+ background-color: #eeeeee;
+}
+/*******************************************************************************
+ * 'columnview' extension
+ */
+table.fancytree-ext-columnview tbody tr td {
+ border: 1px solid gray;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #ccc;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: royalblue;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.less
new file mode 100644
index 0000000..c929e84
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.less
@@ -0,0 +1,131 @@
+/*!
+ * Fancytree "material" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "skin-common.less";
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-material/";
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*
+https://material.io/guidelines/components/data-tables.html#data-tables-structure
+*/
+// local vars
+@fancy-cst-size: 18px;
+@fancy-cst-primary-color: #3f51b5; // primary app color (of indigo-pink)
+@fancy-cst-secondary-color: #ff4081; // secondary app color (of indigo-pink): checkbox
+@fancy-cst-black-87: #212121; // 87% black: table content
+@fancy-cst-black-54: #757575; // 54% black: column headers
+@fancy-cst-select-bg: #f5f5f5; // Grey 100: selected row backround
+@fancy-cst-hover-bg: #eeeeee; // Grey 200: hovered row backround
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: false; // false: suppress all background images (i.e. icons)
+@fancy-loading-url: none;
+
+@fancy-level-indent: @fancy-cst-size; //@fancy-cst-size;
+@fancy-line-height: @fancy-cst-size; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: @fancy-cst-size;
+@fancy-icon-height: @fancy-cst-size;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false;
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%; //@fancy-cst-size;
+@fancy-font-family: "Roboto Regular", tahoma, arial, helvetica;
+@fancy-font-color: @fancy-cst-black-87;
+@fancy-font-color-dimm: silver;
+@fancy-font-error-color: red;
+
+
+ul.fancytree-container ul
+{
+ padding: 0 0 0 1em; //0.3em 0 0 1em;
+ margin: 0;
+ //font-size: @fancy-cst-size;
+ //color: @fancy-cst-black-87;
+}
+
+ul.fancytree-container span.fancytree-icon.material-icons
+{
+ font-size: @fancy-cst-size;
+ color: @fancy-cst-black-87;
+}
+
+
+// set icon color to font color as well
+span.fancytree-node {
+ color: @fancy-font-color;
+}
+span.fancytree-expander {
+ font-size: @fancy-cst-size;
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+
+ .fancytree-plain {
+ span.fancytree-selected span.fancytree-title {
+ background-color: @fancy-cst-select-bg;
+ }
+ span.fancytree-selected span.fancytree-title:hover,
+ span.fancytree-active span.fancytree-title {
+ background-color: @fancy-cst-hover-bg;
+ }
+}
+
+.fancytree-container span.fancytree-checkbox {
+ color: @fancy-cst-secondary-color;
+}
+
+///*******************************************************************************
+// * 'table' extension
+// */
+//table.fancytree-ext-table {
+// border-collapse: collapse;
+// tbody {
+// tr.fancytree-focused, tr.fancytree-selected {
+// background-color: @fancy-cst-select-bg;
+// }
+// tr.fancytree-active, tr:hover {
+// background-color: @fancy-cst-hover-bg;
+// }
+// }
+//}
+//
+///*******************************************************************************
+// * 'columnview' extension
+// */
+//
+//table.fancytree-ext-columnview tbody tr td {
+// border: 1px solid gray;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+// background-color: #ccc;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+// background-color: royalblue;
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.min.css
new file mode 100644
index 0000000..15b8226
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-material/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "material" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:"Roboto Regular",tahoma,arial,helvetica;font-size:24px;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 24px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-material/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:24px;height:24px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:0}span.fancytree-custom-icon{width:24px;height:24px;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:24px;height:24px;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{margin-top:0}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:3px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:none}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:24px}span.fancytree-title{color:#212121;cursor:pointer;display:inline-block;vertical-align:top;min-height:24px;padding:0 3px 0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}#fancytree-drop-marker{width:48px;position:absolute;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:96px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-material/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}table.fancytree-ext-table{font-family:"Roboto Regular",tahoma,arial,helvetica;font-size:24px;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}ul.fancytree-container ul{padding:.3em 0 0 1em;margin:0;font-size:24px;color:#212121}.fancytree-plain span.fancytree-selected span.fancytree-title{background-color:#f5f5f5}.fancytree-plain span.fancytree-active span.fancytree-title,.fancytree-plain span.fancytree-selected span.fancytree-title:hover{background-color:#eee}.fancytree-container span.fancytree-checkbox{color:#ff4081}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table tbody tr.fancytree-focused,table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#f5f5f5}table.fancytree-ext-table tbody tr.fancytree-active,table.fancytree-ext-table tbody tr:hover{background-color:#eee}table.fancytree-ext-columnview tbody tr td{border:1px solid gray}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#ccc}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#4169e1} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-material/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-material/vline-rtl.gif
new file mode 100644
index 0000000..0400cb3
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-material/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-material/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-material/vline.gif
new file mode 100644
index 0000000..1b00ae5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-material/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-mdi/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-mdi/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-mdi/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-mdi/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-mdi/ui.fancytree.less
new file mode 100644
index 0000000..56615f4
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-mdi/ui.fancytree.less
@@ -0,0 +1,131 @@
+/*!
+ * Fancytree "material" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "skin-common.less";
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-mdi/";
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*
+https://material.io/guidelines/components/data-tables.html#data-tables-structure
+*/
+// local vars
+@fancy-cst-size: 18px;
+@fancy-cst-primary-color: #3f51b5; // primary app color (of indigo-pink)
+@fancy-cst-secondary-color: #ff4081; // secondary app color (of indigo-pink): checkbox
+@fancy-cst-black-87: #212121; // 87% black: table content
+@fancy-cst-black-54: #757575; // 54% black: column headers
+@fancy-cst-select-bg: #f5f5f5; // Grey 100: selected row backround
+@fancy-cst-hover-bg: #eeeeee; // Grey 200: hovered row backround
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: false; // false: suppress all background images (i.e. icons)
+@fancy-loading-url: none;
+
+@fancy-level-indent: @fancy-cst-size; //@fancy-cst-size;
+@fancy-line-height: @fancy-cst-size; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: @fancy-cst-size;
+@fancy-icon-height: @fancy-cst-size;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: -2px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false;
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%; //@fancy-cst-size;
+@fancy-font-family: "Roboto Regular", tahoma, arial, helvetica;
+@fancy-font-color: @fancy-cst-black-87;
+@fancy-font-color-dimm: silver;
+@fancy-font-error-color: red;
+
+
+ul.fancytree-container ul
+{
+ padding: 0 0 0 1em; //0.3em 0 0 1em;
+ margin: 0;
+ //font-size: @fancy-cst-size;
+ //color: @fancy-cst-black-87;
+}
+
+ul.fancytree-container span.fancytree-icon.mdi
+{
+ font-size: @fancy-cst-size;
+ color: @fancy-cst-black-87;
+}
+
+
+// set icon color to font color as well
+span.fancytree-node {
+ color: @fancy-font-color;
+}
+span.fancytree-expander {
+ font-size: @fancy-cst-size;
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+
+ .fancytree-plain {
+ span.fancytree-selected span.fancytree-title {
+ background-color: @fancy-cst-select-bg;
+ }
+ span.fancytree-selected span.fancytree-title:hover,
+ span.fancytree-active span.fancytree-title {
+ background-color: @fancy-cst-hover-bg;
+ }
+}
+
+.fancytree-container span.fancytree-checkbox {
+ color: @fancy-cst-secondary-color;
+}
+
+///*******************************************************************************
+// * 'table' extension
+// */
+//table.fancytree-ext-table {
+// border-collapse: collapse;
+// tbody {
+// tr.fancytree-focused, tr.fancytree-selected {
+// background-color: @fancy-cst-select-bg;
+// }
+// tr.fancytree-active, tr:hover {
+// background-color: @fancy-cst-hover-bg;
+// }
+// }
+//}
+//
+///*******************************************************************************
+// * 'columnview' extension
+// */
+//
+//table.fancytree-ext-columnview tbody tr td {
+// border: 1px solid gray;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+// background-color: #ccc;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+// background-color: royalblue;
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-mdi/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-mdi/vline-rtl.gif
new file mode 100644
index 0000000..0400cb3
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-mdi/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-mdi/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-mdi/vline.gif
new file mode 100644
index 0000000..1b00ae5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-mdi/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/icons-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/icons-rtl.gif
new file mode 100644
index 0000000..443e1e4
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/icons-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/icons.gif b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/icons.gif
new file mode 100644
index 0000000..0097b1f
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/icons.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/loading.gif b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/loading.gif
new file mode 100644
index 0000000..ef88497
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/loading.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.css
new file mode 100644
index 0000000..00f79bd
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.css
@@ -0,0 +1,716 @@
+/*!
+ * Fancytree "ThemeRoller" skin.
+ * This file should be included after a jQuery Themeroller style sheet.
+ * It is meant to be used together with the ext-themeroller extension.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #c0c0c0;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 16px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-themeroller/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-image: url("../skin-themeroller/icons.gif");
+ background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 2px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 16px;
+ height: 16px;
+ margin-left: 3px;
+ margin-top: 2px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-themeroller/icons.gif");
+ margin-top: 0;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover {
+ background-position: 0px -64px;
+}
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover {
+ background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+ background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+ background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+ background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+ background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+ background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ background-position: -48px -96px;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 3px;
+ background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+ background-position: -16px -32px;
+}
+span.fancytree-checkbox.fancytree-radio {
+ background-position: 0px -48px;
+}
+span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -16px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+ background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -80px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio {
+ background-position: -64px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -80px -48px;
+}
+.fancytree-selected span.fancytree-checkbox {
+ background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -48px -32px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio {
+ background-position: -32px -48px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -48px -48px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+ background-position: 0px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: 0px -48px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -32px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -32px -48px;
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+ background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+ background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: url("../skin-themeroller/loading.gif");
+ background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 0px;
+ min-height: 20px;
+}
+span.fancytree-title {
+ color: black;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 20px;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 3px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+ background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+ background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 32px;
+ position: absolute;
+ background-position: 0px -128px;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 64px;
+ background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+ background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+ background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl span.fancytree-connector,
+.fancytree-container.fancytree-rtl span.fancytree-expander,
+.fancytree-container.fancytree-rtl span.fancytree-icon,
+.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img {
+ background-image: url("../skin-themeroller/icons-rtl.gif");
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-themeroller/icons-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-themeroller/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+#fancytree-drop-marker.fancytree-rtl {
+ background-image: url("../skin-themeroller/icons-rtl.gif");
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #c0c0c0;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+ background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+ background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain span.fancytree-node {
+ border: 1px solid transparent;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+ border: 1px solid transparent;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.less
new file mode 100644
index 0000000..d82ee14
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.less
@@ -0,0 +1,64 @@
+/*!
+ * Fancytree "ThemeRoller" skin.
+ * This file should be included after a jQuery Themeroller style sheet.
+ * It is meant to be used together with the ext-themeroller extension.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+
+@fancy-line-height: 20px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 0px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 2px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-themeroller/";
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain {
+ span.fancytree-node {
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ }
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody {
+ tr td {
+ border: 1px solid transparent;
+ }
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.min.css
new file mode 100644
index 0000000..d22ab1f
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/ui.fancytree.min.css
@@ -0,0 +1,8 @@
+/*!
+ * Fancytree "ThemeRoller" skin.
+ * This file should be included after a jQuery Themeroller style sheet.
+ * It is meant to be used together with the ext-themeroller extension.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-themeroller/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url("../skin-themeroller/icons.gif");background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:2px}span.fancytree-custom-icon{width:16px;height:16px;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:2px;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-themeroller/icons.gif");margin-top:0}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}span.fancytree-checkbox.fancytree-radio{background-position:0 -48px}span.fancytree-checkbox.fancytree-radio:hover{background-position:-16px -48px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio{background-position:-64px -48px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover{background-position:-80px -48px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-selected span.fancytree-checkbox.fancytree-radio{background-position:-32px -48px}.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-48px -48px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover{background-position:0 -48px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-32px -48px}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:url("../skin-themeroller/loading.gif");background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:0;min-height:20px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:20px;padding:0 3px 0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl span.fancytree-connector,.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,.fancytree-container.fancytree-rtl span.fancytree-expander,.fancytree-container.fancytree-rtl span.fancytree-icon{background-image:url("../skin-themeroller/icons-rtl.gif")}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-themeroller/icons-rtl.gif")}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-themeroller/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}#fancytree-drop-marker.fancytree-rtl{background-image:url("../skin-themeroller/icons-rtl.gif")}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}.fancytree-plain span.fancytree-node{border:1px solid transparent}table.fancytree-ext-table tbody tr td{border:1px solid transparent} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/vline-rtl.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/vline.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-themeroller/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-typicons/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-typicons/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-typicons/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-typicons/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-typicons/ui.fancytree.less
new file mode 100644
index 0000000..976bc4f
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-typicons/ui.fancytree.less
@@ -0,0 +1,138 @@
+/*!
+ * Fancytree "awesome" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "skin-common.less";
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-typicons/";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+@fancy-use-sprites: false; // false: suppress all background images (i.e. icons)
+@fancy-loading-url: none;
+
+@fancy-cst-size: 18px;
+
+@fancy-level-indent: @fancy-cst-size; //@fancy-cst-size;
+@fancy-line-height: @fancy-cst-size; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: @fancy-cst-size;
+@fancy-icon-height: @fancy-cst-size;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: -6px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false;
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%; //@fancy-cst-size;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: #000;
+@fancy-font-color-dimm: silver;
+@fancy-font-error-color: red;
+
+// set icon color to font color as well
+span.fancytree-node {
+ color: @fancy-font-color;
+}
+
+ul.fancytree-container ul
+{
+ padding: 0 0 0 1em; // 0.3em 0 0 1em;
+ margin: 0;
+}
+
+
+// The standard CSS assumes span.icon, but Fontawesome may use SVG or SPAN
+.fancytree-expander,
+.fancytree-checkbox,
+.fancytree-icon {
+ min-width: @fancy-icon-width;
+ text-align: center;
+ font-size: (@fancy-cst-size +2px);
+}
+svg.fancytree-checkbox, // span... is already defined in skin-common-less
+svg.fancytree-icon {
+ padding-left: @fancy-icon-spacing;
+}
+span.fancytree-expander {
+ font-size: (@fancy-cst-size *4/5);
+ margin-top: -1px;
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+ border: 1px solid transparent; // reserve some space for status borders
+ border-radius: 0;
+}
+span.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+}
+// span.fancytree-selected span.fancytree-title,
+span.fancytree-active span.fancytree-title {
+ background-color: #D4D4D4; // gray
+}
+// span.fancytree-selected span.fancytree-title {
+// font-style: italic;
+// }
+// .fancytree-treefocus span.fancytree-selected span.fancytree-title,
+.fancytree-treefocus span.fancytree-active span.fancytree-title {
+ color: white;
+ background-color: #3875D7; // blue
+}
+
+// .fancytree-treefocus span.fancytree-selected span.fancytree-title{
+// color: white;
+// background-color: #99DEFD; // blue
+// }
+
+///*******************************************************************************
+// * 'table' extension
+// */
+//table.fancytree-ext-table {
+// border-collapse: collapse;
+// tbody {
+// tr.fancytree-focused {
+// background-color: #99DEFD;
+// }
+// tr.fancytree-active {
+// background-color: royalblue;
+// }
+// // tr.fancytree-selected {
+// // background-color: #99DEFD;
+// // }
+// }
+//}
+//
+///*******************************************************************************
+// * 'columnview' extension
+// */
+//
+//table.fancytree-ext-columnview tbody tr td {
+// border: 1px solid gray;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+// background-color: #ccc;
+//}
+//table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+// background-color: royalblue;
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-typicons/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-typicons/vline-rtl.gif
new file mode 100644
index 0000000..0400cb3
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-typicons/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-typicons/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-typicons/vline.gif
new file mode 100644
index 0000000..1b00ae5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-typicons/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-vista/icons-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-vista/icons-rtl.gif
new file mode 100644
index 0000000..443e1e4
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-vista/icons-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-vista/icons.gif b/plugins/55/indexmenu/scripts/fancytree/skin-vista/icons.gif
new file mode 100644
index 0000000..0097b1f
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-vista/icons.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-vista/loading.gif b/plugins/55/indexmenu/scripts/fancytree/skin-vista/loading.gif
new file mode 100644
index 0000000..ef88497
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-vista/loading.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-vista/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-vista/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-vista/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.css
new file mode 100644
index 0000000..3920b04
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.css
@@ -0,0 +1,763 @@
+/*!
+ * Fancytree "Vista" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*
+both:
+ unselected background: #FCFCFC 'nearly white'
+ hover bar (unselected, inactive): #F8FCFE..#EFF9FE (border: #D8F0FA) 'very light blue'
+ active node: #F6FBFD..#D5EFFC (border: #99DEFD) 'light blue'
+ active node with hover: #F2F9FD..#C4E8FA (border: #B6E6FB)
+
+Tree view:
+ active node, tree inactive: #FAFAFB..#E5E5E5 (border: #D9D9D9) 'light gray, selected, but tree not active'
+
+List view:
+ selected bar: --> active bar
+ focus bar: active + border 1px dotted #090402 (inside the blue border)
+
+ table left/right border: #EDEDED 'light gray'
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #c0c0c0;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 16px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-vista/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-image: url("../skin-vista/icons.gif");
+ background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 0px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 16px;
+ height: 16px;
+ margin-left: 3px;
+ margin-top: 0px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-vista/icons.gif");
+ margin-top: 0;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover {
+ background-position: 0px -64px;
+}
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover {
+ background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+ background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+ background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+ background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+ background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+ background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ background-position: -48px -96px;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 3px;
+ background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+ background-position: -16px -32px;
+}
+span.fancytree-checkbox.fancytree-radio {
+ background-position: 0px -48px;
+}
+span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -16px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+ background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -80px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio {
+ background-position: -64px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -80px -48px;
+}
+.fancytree-selected span.fancytree-checkbox {
+ background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -48px -32px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio {
+ background-position: -32px -48px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -48px -48px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+ background-position: 0px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: 0px -48px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -32px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -32px -48px;
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+ background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+ background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: url("../skin-vista/loading.gif");
+ background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 1px;
+ min-height: 16px;
+}
+span.fancytree-title {
+ color: black;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 16px;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 3px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+ background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+ background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 32px;
+ position: absolute;
+ background-position: 0px -128px;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 64px;
+ background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+ background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+ background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl span.fancytree-connector,
+.fancytree-container.fancytree-rtl span.fancytree-expander,
+.fancytree-container.fancytree-rtl span.fancytree-icon,
+.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img {
+ background-image: url("../skin-vista/icons-rtl.gif");
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-vista/icons-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-vista/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+#fancytree-drop-marker.fancytree-rtl {
+ background-image: url("../skin-vista/icons-rtl.gif");
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #c0c0c0;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+ background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+ background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+ border: 1px solid transparent;
+}
+span.fancytree-title:hover {
+ background-color: #F2F7FD;
+ border-color: #B8D6FB;
+}
+span.fancytree-focused span.fancytree-title {
+ background-color: #EFEBDE;
+ outline: 1px dotted gray;
+}
+span.fancytree-selected span.fancytree-title {
+ font-style: italic;
+}
+span.fancytree-active span.fancytree-title {
+ border: 1px solid #99DEFD;
+ background-color: #D8F0FA;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+ border-collapse: collapse;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused {
+ background-color: #99DEFD;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+ background-color: royalblue;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+ background-color: #99FDDE;
+}
+/*******************************************************************************
+ * 'columnview' extension
+ */
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #ccc;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: royalblue;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.less
new file mode 100644
index 0000000..5d7ae40
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.less
@@ -0,0 +1,117 @@
+/*!
+ * Fancytree "Vista" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+/*
+both:
+ unselected background: #FCFCFC 'nearly white'
+ hover bar (unselected, inactive): #F8FCFE..#EFF9FE (border: #D8F0FA) 'very light blue'
+ active node: #F6FBFD..#D5EFFC (border: #99DEFD) 'light blue'
+ active node with hover: #F2F9FD..#C4E8FA (border: #B6E6FB)
+
+Tree view:
+ active node, tree inactive: #FAFAFB..#E5E5E5 (border: #D9D9D9) 'light gray, selected, but tree not active'
+
+List view:
+ selected bar: --> active bar
+ focus bar: active + border 1px dotted #090402 (inside the blue border)
+
+ table left/right border: #EDEDED 'light gray'
+ */
+
+// Import common styles
+@import "skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-line-height: 16px;
+@fancy-icon-spacing: 3px;
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-vista/";
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%;
+
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+}
+span.fancytree-title:hover {
+ background-color: #F2F7FD; // light blue
+ border-color: #B8D6FB; // darker light blue
+}
+.fancytree-folder span.fancytree-title {
+ // font-weight: bold;
+}
+span.fancytree-focused span.fancytree-title {
+ background-color: #EFEBDE; // gray
+ outline: 1px dotted gray;
+}
+span.fancytree-has-children span.fancytree-title {
+ // font-style: oblique;
+}
+span.fancytree-expanded span.fancytree-title {
+}
+span.fancytree-selected span.fancytree-title {
+ font-style: italic;
+}
+span.fancytree-active span.fancytree-title {
+ border: 1px solid #99DEFD;
+ background-color: #D8F0FA;
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+
+table.fancytree-ext-table {
+ border-collapse: collapse;
+ tbody tr.fancytree-focused {
+ background-color: #99DEFD;
+ }
+ tbody tr.fancytree-active {
+ background-color: royalblue;
+ }
+ tbody tr.fancytree-selected {
+ background-color: #99FDDE;
+ }
+}
+
+/*******************************************************************************
+ * 'columnview' extension
+ */
+
+table.fancytree-ext-columnview {
+ span.fancytree-node.fancytree-expanded {
+ background-color: #ccc;
+ }
+ span.fancytree-node.fancytree-active {
+ background-color: royalblue;
+ }
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.min.css
new file mode 100644
index 0000000..232eb27
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-vista/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "Vista" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-vista/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url("../skin-vista/icons.gif");background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:0}span.fancytree-custom-icon{width:16px;height:16px;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-vista/icons.gif");margin-top:0}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}span.fancytree-checkbox.fancytree-radio{background-position:0 -48px}span.fancytree-checkbox.fancytree-radio:hover{background-position:-16px -48px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio{background-position:-64px -48px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover{background-position:-80px -48px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-selected span.fancytree-checkbox.fancytree-radio{background-position:-32px -48px}.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-48px -48px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover{background-position:0 -48px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-32px -48px}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:url("../skin-vista/loading.gif");background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:16px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:16px;padding:0 3px 0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl span.fancytree-connector,.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,.fancytree-container.fancytree-rtl span.fancytree-expander,.fancytree-container.fancytree-rtl span.fancytree-icon{background-image:url("../skin-vista/icons-rtl.gif")}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-vista/icons-rtl.gif")}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-vista/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}#fancytree-drop-marker.fancytree-rtl{background-image:url("../skin-vista/icons-rtl.gif")}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}span.fancytree-title{border:1px solid transparent}span.fancytree-title:hover{background-color:#f2f7fd;border-color:#b8d6fb}span.fancytree-focused span.fancytree-title{background-color:#efebde;outline:1px dotted gray}span.fancytree-selected span.fancytree-title{font-style:italic}span.fancytree-active span.fancytree-title{border:1px solid #99defd;background-color:#d8f0fa}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table tbody tr.fancytree-focused{background-color:#99defd}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#4169e1}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#99fdde}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#ccc}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#4169e1} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-vista/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-vista/vline-rtl.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-vista/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-vista/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-vista/vline.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-vista/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win7/icons-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win7/icons-rtl.gif
new file mode 100644
index 0000000..443e1e4
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win7/icons-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win7/icons.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win7/icons.gif
new file mode 100644
index 0000000..0097b1f
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win7/icons.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win7/loading.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win7/loading.gif
new file mode 100644
index 0000000..ef88497
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win7/loading.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win7/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-win7/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win7/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.css
new file mode 100644
index 0000000..fdd5191
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.css
@@ -0,0 +1,822 @@
+/*!
+ * Fancytree "Win7" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #c0c0c0;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 16px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-win7/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-image: url("../skin-win7/icons.gif");
+ background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 2px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 16px;
+ height: 16px;
+ margin-left: 3px;
+ margin-top: 2px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-win7/icons.gif");
+ margin-top: 0;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover {
+ background-position: 0px -64px;
+}
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover {
+ background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+ background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+ background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+ background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+ background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+ background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ background-position: -48px -96px;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 3px;
+ background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+ background-position: -16px -32px;
+}
+span.fancytree-checkbox.fancytree-radio {
+ background-position: 0px -48px;
+}
+span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -16px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+ background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -80px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio {
+ background-position: -64px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -80px -48px;
+}
+.fancytree-selected span.fancytree-checkbox {
+ background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -48px -32px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio {
+ background-position: -32px -48px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -48px -48px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+ background-position: 0px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: 0px -48px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -32px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -32px -48px;
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+ background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+ background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: url("../skin-win7/loading.gif");
+ background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 1px;
+ min-height: 20px;
+}
+span.fancytree-title {
+ color: black;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 20px;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 3px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ -ms-border-radius: 3px;
+ -o-border-radius: 3px;
+ border-radius: 3px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+ background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+ background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 32px;
+ position: absolute;
+ background-position: 0px -128px;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 64px;
+ background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+ background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+ background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl span.fancytree-connector,
+.fancytree-container.fancytree-rtl span.fancytree-expander,
+.fancytree-container.fancytree-rtl span.fancytree-icon,
+.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img {
+ background-image: url("../skin-win7/icons-rtl.gif");
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-win7/icons-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-win7/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+#fancytree-drop-marker.fancytree-rtl {
+ background-image: url("../skin-win7/icons-rtl.gif");
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #c0c0c0;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+ background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+ background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-active .fancytree-title,
+span.fancytree-selected .fancytree-title {
+ border-color: #d9d9d9;
+ background: #e5e5e5;
+ color: inherit;
+ background: -moz-linear-gradient(top, #fafafb 0%, #e5e5e5 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafb), color-stop(100%, #e5e5e5));
+ background: -webkit-linear-gradient(top, #fafafb 0%, #e5e5e5 100%);
+ background: -o-linear-gradient(top, #fafafb 0%, #e5e5e5 100%);
+ background: -ms-linear-gradient(top, #fafafb 0%, #e5e5e5 100%);
+ background: linear-gradient(to bottom, #fafafb 0%, #e5e5e5 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fafafb', endColorstr='#e5e5e5', GradientType=0);
+}
+span.fancytree-selected .fancytree-title {
+ font-style: italic;
+}
+.fancytree-treefocus span.fancytree-active .fancytree-title,
+.fancytree-treefocus span.fancytree-selected .fancytree-title {
+ border-color: #99defd;
+ background: #f6fbfd;
+ color: inherit;
+ background: -moz-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f6fbfd), color-stop(100%, #d5effc));
+ background: -webkit-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+ background: -o-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+ background: -ms-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+ background: linear-gradient(to bottom, #f6fbfd 0%, #d5effc 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0);
+}
+.fancytree-treefocus span.fancytree-focused span.fancytree-title {
+ border: 1px solid #719acb;
+}
+span.fancytree-title:hover {
+ border-color: #d8f0fa;
+ background: #f8fcfe;
+ color: inherit;
+ background: -moz-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f8fcfe), color-stop(100%, #eff9fe));
+ background: -webkit-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+ background: -o-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+ background: -ms-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+ background: linear-gradient(to bottom, #f8fcfe 0%, #eff9fe 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0);
+}
+span.fancytree-active .fancytree-title:hover,
+span.fancytree-selected .fancytree-title:hover {
+ border-color: #719acb;
+ background: #f2f9fd;
+ color: inherit;
+ background: -moz-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f2f9fd), color-stop(100%, #c4e8fa));
+ background: -webkit-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+ background: -o-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+ background: -ms-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+ background: linear-gradient(to bottom, #f2f9fd 0%, #c4e8fa 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0);
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+ border: 1px solid #ededed;
+}
+table.fancytree-ext-table tbody tr:hover {
+ border-color: inherit;
+ background: #f8fcfe;
+ color: inherit;
+ background: -moz-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f8fcfe), color-stop(100%, #eff9fe));
+ background: -webkit-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+ background: -o-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+ background: -ms-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+ background: linear-gradient(to bottom, #f8fcfe 0%, #eff9fe 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0);
+ outline: 1px solid #d8f0fa;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused {
+ outline: 1px dotted #090402;
+}
+table.fancytree-ext-table tbody span.fancytree-focused span.fancytree-title {
+ outline: solid dotted black;
+}
+table.fancytree-ext-table tbody span.fancytree-title:hover {
+ border: 1px solid transparent;
+ background: inherit;
+ background: transparent;
+ background: none;
+ filter: none;
+}
+table.fancytree-ext-table tbody tr.fancytree-active:hover,
+table.fancytree-ext-table tbody tr.fancytree-selected:hover {
+ border-color: inherit;
+ background: #f2f9fd;
+ color: inherit;
+ background: -moz-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f2f9fd), color-stop(100%, #c4e8fa));
+ background: -webkit-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+ background: -o-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+ background: -ms-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+ background: linear-gradient(to bottom, #f2f9fd 0%, #c4e8fa 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0);
+ outline: 1px solid #B6E6FB;
+}
+table.fancytree-ext-table tbody tr.fancytree-active,
+table.fancytree-ext-table tbody tr.fancytree-selected {
+ border-color: inherit;
+ background: #f6fbfd;
+ color: inherit;
+ background: -moz-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f6fbfd), color-stop(100%, #d5effc));
+ background: -webkit-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+ background: -o-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+ background: -ms-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+ background: linear-gradient(to bottom, #f6fbfd 0%, #d5effc 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0);
+ outline: 1px solid #99DEFD;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.less
new file mode 100644
index 0000000..f075c49
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.less
@@ -0,0 +1,157 @@
+/*!
+ * Fancytree "Win7" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Fancytree Win7 styles
+
+// both:
+// unselected background: #FCFCFC 'nearly white', no border
+//
+// hover bar (unselected, inactive): #fcfdfe..#EFF9FE (border: #b8d6fb) 'very light blue'
+// background: #f8fcfe; //
+// background: -moz-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%);
+
+// active node: #F6FBFD..#D5EFFC (border: #719acb) 'light blue'
+// background: #f6fbfd;
+// background: -moz-linear-gradient(top, #f6fbfd 0%, #d5effc 100%);
+
+// active node with hover: #F2F9FD..#C4E8FA (border: #B6E6FB)
+// background: #f2f9fd;
+// background: -moz-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%);
+
+// Tree view:
+// active node, tree inactive: #FAFAFB..#E5E5E5 (border: #D9D9D9) 'light gray, selected, but tree not active'
+// background: #fafafb;
+// background: -moz-linear-gradient(top, #fafafb 0%, #e5e5e5 100%);
+
+// List view:
+// selected bar: --> active bar
+// focus bar: active + border 1px dotted #090402 (inside the blue border)
+
+// table left/right border: #EDEDED 'light gray'
+
+// Import common styles
+@import "skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+
+@fancy-line-height: 20px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 2px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 3px;
+@fancy-node-outline-width: 1px;
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-win7/";
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%;
+
+ul.fancytree-container {
+
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+}
+// active nodes inside an UN-focused tree are gray instead of blue
+span.fancytree-active .fancytree-title,
+span.fancytree-selected .fancytree-title {
+ .spanStyleMixin(inherit, #e5e5e5, #d9d9d9, #fafafb, #e5e5e5);
+}
+span.fancytree-selected .fancytree-title {
+ font-style: italic;
+}
+// Markers inside an active tree
+.fancytree-treefocus {
+ span.fancytree-active .fancytree-title,
+ span.fancytree-selected .fancytree-title {
+ .spanStyleMixin(inherit, #f6fbfd, #99defd, #f6fbfd, #d5effc);
+ }
+ span.fancytree-focused span.fancytree-title {
+ border: @fancy-node-border-width solid #719acb;
+ }
+}
+// Hover is always colored (even if tree is inactive)
+span.fancytree-title:hover {
+ .spanStyleMixin(inherit, #f8fcfe, #d8f0fa, #f8fcfe, #eff9fe);
+}
+span.fancytree-active .fancytree-title:hover,
+span.fancytree-selected .fancytree-title:hover {
+ .spanStyleMixin(inherit, #f2f9fd, #719acb, #f2f9fd, #c4e8fa);
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+
+table.fancytree-ext-table tbody {
+ tr td {
+ border: 1px solid #ededed;
+ }
+ tr:hover {
+ .spanStyleMixin(inherit, #f8fcfe, inherit, #f8fcfe, #eff9fe);
+ outline: 1px solid #d8f0fa;
+ }
+ // tr:hover td {
+ // outline: 1px solid #D8F0FA;
+ // }
+ tr.fancytree-focused {
+ // background-color: #99DEFD;
+ outline: 1px dotted #090402;
+ }
+ span.fancytree-focused span.fancytree-title {
+ outline: solid dotted black;
+ }
+
+ // Title gets a white background, when hovered. Undo standard node formatting
+ span.fancytree-title:hover {
+ border: 1px solid transparent;
+ background: inherit;
+ background: transparent;
+ background: none;
+ filter: none;
+ }
+
+ tr.fancytree-active:hover,
+ tr.fancytree-selected:hover {
+ .spanStyleMixin(inherit, #f2f9fd, inherit, #f2f9fd, #c4e8fa);
+ outline: 1px solid #B6E6FB;
+ }
+ tr.fancytree-active,
+ tr.fancytree-selected {
+ .spanStyleMixin(inherit, #f6fbfd, inherit, #f6fbfd, #d5effc);
+ outline: 1px solid #99DEFD;
+ }
+ // tr.fancytree-selected .fancytree-title {
+ // font-style: italic;
+ // }
+
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.min.css
new file mode 100644
index 0000000..bcbe5eb
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win7/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "Win7" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-win7/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url("../skin-win7/icons.gif");background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:2px}span.fancytree-custom-icon{width:16px;height:16px;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:2px;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-win7/icons.gif");margin-top:0}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}span.fancytree-checkbox.fancytree-radio{background-position:0 -48px}span.fancytree-checkbox.fancytree-radio:hover{background-position:-16px -48px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio{background-position:-64px -48px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover{background-position:-80px -48px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-selected span.fancytree-checkbox.fancytree-radio{background-position:-32px -48px}.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-48px -48px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover{background-position:0 -48px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-32px -48px}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:url("../skin-win7/loading.gif");background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:20px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:20px;padding:0 3px 0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl span.fancytree-connector,.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,.fancytree-container.fancytree-rtl span.fancytree-expander,.fancytree-container.fancytree-rtl span.fancytree-icon{background-image:url("../skin-win7/icons-rtl.gif")}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-win7/icons-rtl.gif")}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-win7/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}#fancytree-drop-marker.fancytree-rtl{background-image:url("../skin-win7/icons-rtl.gif")}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}span.fancytree-active .fancytree-title,span.fancytree-selected .fancytree-title{border-color:#d9d9d9;background:#e5e5e5;color:inherit;background:-moz-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fafafb),color-stop(100%,#e5e5e5));background:-webkit-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:-o-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:-ms-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:linear-gradient(to bottom,#fafafb 0,#e5e5e5 100%)}span.fancytree-selected .fancytree-title{font-style:italic}.fancytree-treefocus span.fancytree-active .fancytree-title,.fancytree-treefocus span.fancytree-selected .fancytree-title{border-color:#99defd;background:#f6fbfd;color:inherit;background:-moz-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f6fbfd),color-stop(100%,#d5effc));background:-webkit-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-o-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-ms-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:linear-gradient(to bottom,#f6fbfd 0,#d5effc 100%)}.fancytree-treefocus span.fancytree-focused span.fancytree-title{border:1px solid #719acb}span.fancytree-title:hover{border-color:#d8f0fa;background:#f8fcfe;color:inherit;background:-moz-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f8fcfe),color-stop(100%,#eff9fe));background:-webkit-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-o-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-ms-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:linear-gradient(to bottom,#f8fcfe 0,#eff9fe 100%)}span.fancytree-active .fancytree-title:hover,span.fancytree-selected .fancytree-title:hover{border-color:#719acb;background:#f2f9fd;color:inherit;background:-moz-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f2f9fd),color-stop(100%,#c4e8fa));background:-webkit-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-o-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-ms-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:linear-gradient(to bottom,#f2f9fd 0,#c4e8fa 100%)}table.fancytree-ext-table tbody tr td{border:1px solid #ededed}table.fancytree-ext-table tbody tr:hover{border-color:inherit;background:#f8fcfe;color:inherit;background:-moz-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f8fcfe),color-stop(100%,#eff9fe));background:-webkit-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-o-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-ms-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:linear-gradient(to bottom,#f8fcfe 0,#eff9fe 100%);outline:1px solid #d8f0fa}table.fancytree-ext-table tbody tr.fancytree-focused{outline:1px dotted #090402}table.fancytree-ext-table tbody span.fancytree-focused span.fancytree-title{outline:solid dotted black}table.fancytree-ext-table tbody span.fancytree-title:hover{border:1px solid transparent;background:inherit;background:0 0;background:0 0;filter:none}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{border-color:inherit;background:#f2f9fd;color:inherit;background:-moz-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f2f9fd),color-stop(100%,#c4e8fa));background:-webkit-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-o-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-ms-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:linear-gradient(to bottom,#f2f9fd 0,#c4e8fa 100%);outline:1px solid #B6E6FB}table.fancytree-ext-table tbody tr.fancytree-active,table.fancytree-ext-table tbody tr.fancytree-selected{border-color:inherit;background:#f6fbfd;color:inherit;background:-moz-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f6fbfd),color-stop(100%,#d5effc));background:-webkit-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-o-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-ms-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:linear-gradient(to bottom,#f6fbfd 0,#d5effc 100%);outline:1px solid #99DEFD} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win7/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win7/vline-rtl.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win7/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win7/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win7/vline.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win7/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/icons-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/icons-rtl.gif
new file mode 100644
index 0000000..443e1e4
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/icons-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/icons.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/icons.gif
new file mode 100644
index 0000000..0097b1f
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/icons.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/loading.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/loading.gif
new file mode 100644
index 0000000..ef88497
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/loading.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.css
new file mode 100644
index 0000000..73113d6
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.css
@@ -0,0 +1,767 @@
+/*!
+ * Fancytree "win8" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #c0c0c0;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 16px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-win8-n/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-image: url("../skin-win8-n/icons.gif");
+ background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 0px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 16px;
+ height: 16px;
+ margin-left: 3px;
+ margin-top: 0px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-win8-n/icons.gif");
+ margin-top: 0;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover {
+ background-position: 0px -64px;
+}
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover {
+ background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+ background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+ background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+ background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+ background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+ background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ background-position: -48px -96px;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 3px;
+ background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+ background-position: -16px -32px;
+}
+span.fancytree-checkbox.fancytree-radio {
+ background-position: 0px -48px;
+}
+span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -16px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+ background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -80px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio {
+ background-position: -64px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -80px -48px;
+}
+.fancytree-selected span.fancytree-checkbox {
+ background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -48px -32px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio {
+ background-position: -32px -48px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -48px -48px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+ background-position: 0px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: 0px -48px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -32px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -32px -48px;
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+ background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+ background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: url("../skin-win8-n/loading.gif");
+ background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 1px;
+ min-height: 16px;
+}
+span.fancytree-title {
+ color: black;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 16px;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 3px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+ background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+ background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 32px;
+ position: absolute;
+ background-position: 0px -128px;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 64px;
+ background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+ background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+ background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl span.fancytree-connector,
+.fancytree-container.fancytree-rtl span.fancytree-expander,
+.fancytree-container.fancytree-rtl span.fancytree-icon,
+.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img {
+ background-image: url("../skin-win8-n/icons-rtl.gif");
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-win8-n/icons-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-win8-n/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+#fancytree-drop-marker.fancytree-rtl {
+ background-image: url("../skin-win8-n/icons-rtl.gif");
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #c0c0c0;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+ background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+ background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain span.fancytree-node {
+ border: 1px solid transparent;
+}
+.fancytree-plain span.fancytree-node:hover {
+ background-color: #E5F3FB;
+ border-color: #70C0E7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused {
+ border-color: #3399FF;
+}
+.fancytree-plain span.fancytree-node.fancytree-active,
+.fancytree-plain span.fancytree-node.fancytree-selected {
+ background-color: #F7F7F7;
+ border-color: #DEDEDE;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active,
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected,
+.fancytree-plain span.fancytree-node.fancytree-active:hover,
+.fancytree-plain span.fancytree-node.fancytree-selected:hover {
+ background-color: #CBE8F6;
+ border-color: #26A0DA;
+}
+.fancytree-plain .fancytree-node.fancytree-selected {
+ font-style: italic;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+ border: 1px solid #EDEDED;
+}
+table.fancytree-ext-table tbody span.fancytree-node,
+table.fancytree-ext-table tbody span.fancytree-node:hover {
+ border: none;
+ background: none;
+}
+table.fancytree-ext-table tbody tr:hover {
+ background-color: #E5F3FB;
+ outline: 1px solid #70C0E7;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+}
+table.fancytree-ext-table tbody tr.fancytree-active:hover,
+table.fancytree-ext-table tbody tr.fancytree-selected:hover {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+ background-color: #F7F7F7;
+ outline: 1px solid #DEDEDE;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+ background-color: #F7F7F7;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {
+ background-color: #CBE8F6;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.less
new file mode 100644
index 0000000..633827e
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.less
@@ -0,0 +1,145 @@
+/*!
+ * Fancytree "win8" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Borders have NO radius and NO gradients are used!
+
+// both:
+// unselected background: white
+// hover bar (unselected, inactive): #E5F3FB (border: #70C0E7) 'very light blue'
+// active node: #CBE8F6 (border: #26A0DA) 'light blue'
+// active node with hover: wie active node
+
+// Tree view:
+// active node, tree inactive: #F7F7F7 (border: #DEDEDE) 'light gray, selected, but tree not active'
+
+// List view:
+// selected bar: --> active bar
+// focus bar: transparent(white) + border 1px solid #3399FF ()
+
+// table left/right border: #EDEDED 'light gray'
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// Set to `true` to inline icon sprite into CSS:
+// @fancy-inline-sprites: true;
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-line-height: 16px;
+@fancy-icon-spacing: 3px;
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-win8-n/";
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain {
+ span.fancytree-node {
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ }
+ span.fancytree-node:hover {
+ background-color: #E5F3FB;
+ border-color: #70C0E7;
+ }
+ &.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused {
+ border-color: #3399FF;
+ // outline: 1px solid #3399FF;
+ }
+ span.fancytree-node.fancytree-active,
+ span.fancytree-node.fancytree-selected { // active/selcted nodes inside inactive tree
+ background-color: #F7F7F7;
+ border-color: #DEDEDE;
+ }
+ &.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active,
+ &.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected,
+ span.fancytree-node.fancytree-active:hover,
+ span.fancytree-node.fancytree-selected:hover {
+ background-color: #CBE8F6;
+ border-color: #26A0DA;
+ }
+ .fancytree-node.fancytree-selected {
+ font-style: italic;
+ }
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody {
+ tr td {
+ border: 1px solid #EDEDED;
+ }
+ span.fancytree-node,
+ span.fancytree-node:hover { // undo standard tree css
+ border: none;
+ background: none;
+ }
+ // Title gets a white background, when hovered. Undo standard node formatting
+ // span.fancytree-title:hover {
+ // border: none; //1px solid transparent;
+ // background: inherit;
+ // background: transparent;
+ // background: none;
+ // filter: none;
+ // }
+ tr:hover {
+ background-color: #E5F3FB;
+ outline: 1px solid #70C0E7;
+ }
+ // tr:hover td {
+ // outline: 1px solid #D8F0FA;
+ // }
+ // tr.fancytree-focused {
+ // border-color: #3399FF;
+ // outline: 1px dotted black;
+ // }
+ tr.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+ }
+
+ tr.fancytree-active:hover,
+ tr.fancytree-selected:hover {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+ }
+ tr.fancytree-active { // dimmed, if inside inactive tree
+ background-color: #F7F7F7;
+ outline: 1px solid #DEDEDE;
+ }
+ tr.fancytree-selected { // dimmed, if inside inactive tree
+ background-color: #F7F7F7;
+ }
+}
+
+table.fancytree-ext-table.fancytree-treefocus tbody {
+ tr.fancytree-active {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+ }
+ tr.fancytree-selected {
+ background-color: #CBE8F6;
+ }
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.min.css
new file mode 100644
index 0000000..8dfa9fd
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "win8" skin (highlighting the node span instead of title-only).
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-win8-n/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url("../skin-win8-n/icons.gif");background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:0}span.fancytree-custom-icon{width:16px;height:16px;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-win8-n/icons.gif");margin-top:0}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}span.fancytree-checkbox.fancytree-radio{background-position:0 -48px}span.fancytree-checkbox.fancytree-radio:hover{background-position:-16px -48px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio{background-position:-64px -48px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover{background-position:-80px -48px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-selected span.fancytree-checkbox.fancytree-radio{background-position:-32px -48px}.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-48px -48px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover{background-position:0 -48px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-32px -48px}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:url("../skin-win8-n/loading.gif");background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:16px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:16px;padding:0 3px 0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl span.fancytree-connector,.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,.fancytree-container.fancytree-rtl span.fancytree-expander,.fancytree-container.fancytree-rtl span.fancytree-icon{background-image:url("../skin-win8-n/icons-rtl.gif")}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-win8-n/icons-rtl.gif")}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-win8-n/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}#fancytree-drop-marker.fancytree-rtl{background-image:url("../skin-win8-n/icons-rtl.gif")}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}.fancytree-plain span.fancytree-node{border:1px solid transparent}.fancytree-plain span.fancytree-node:hover{background-color:#e5f3fb;border-color:#70c0e7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused{border-color:#39f}.fancytree-plain span.fancytree-node.fancytree-active,.fancytree-plain span.fancytree-node.fancytree-selected{background-color:#f7f7f7;border-color:#dedede}.fancytree-plain span.fancytree-node.fancytree-active:hover,.fancytree-plain span.fancytree-node.fancytree-selected:hover,.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active,.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected{background-color:#cbe8f6;border-color:#26a0da}.fancytree-plain .fancytree-node.fancytree-selected{font-style:italic}table.fancytree-ext-table tbody tr td{border:1px solid #ededed}table.fancytree-ext-table tbody span.fancytree-node,table.fancytree-ext-table tbody span.fancytree-node:hover{border:none;background:0 0}table.fancytree-ext-table tbody tr:hover{background-color:#e5f3fb;outline:1px solid #70C0E7}table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title{outline:1px dotted black}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{background-color:#cbe8f6;outline:1px solid #26A0DA}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#f7f7f7;outline:1px solid #DEDEDE}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#f7f7f7}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active{background-color:#cbe8f6;outline:1px solid #26A0DA}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected{background-color:#cbe8f6} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/vline-rtl.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/vline.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-n/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/icons-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/icons-rtl.gif
new file mode 100644
index 0000000..0ce1c5b
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/icons-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/icons.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/icons.gif
new file mode 100644
index 0000000..f3abe16
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/icons.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/loading.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/loading.gif
new file mode 100644
index 0000000..8031e44
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/loading.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.css
new file mode 100644
index 0000000..e4aff21
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.css
@@ -0,0 +1,775 @@
+/*!
+ * Fancytree "Win8" 32x32 skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #c0c0c0;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 32px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-win8-xxl/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 32px;
+ height: 32px;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-image: url("../skin-win8-xxl/icons.gif");
+ background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 0px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 32px;
+ height: 32px;
+ display: inline-block;
+ margin-left: 6px;
+ background-position: 0px 0px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 32px;
+ height: 32px;
+ margin-left: 6px;
+ margin-top: 0px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-win8-xxl/icons.gif");
+ margin-top: 0;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover {
+ background-position: 0px -128px;
+}
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover {
+ background-position: -32px -128px;
+}
+.fancytree-exp-c span.fancytree-expander {
+ background-position: 0px -160px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ background-position: -32px -160px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+ background-position: 0px -192px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ background-position: -32px -192px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+ background-position: -128px -160px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ background-position: -160px -160px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ background-position: -128px -192px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ background-position: -160px -192px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+ background-position: -64px -160px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ background-position: -96px -160px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+ background-position: -64px -192px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ background-position: -96px -192px;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 6px;
+ background-position: 0px -64px;
+}
+span.fancytree-checkbox:hover {
+ background-position: -32px -64px;
+}
+span.fancytree-checkbox.fancytree-radio {
+ background-position: 0px -96px;
+}
+span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -32px -96px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+ background-position: -128px -64px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -160px -64px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio {
+ background-position: -128px -96px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -160px -96px;
+}
+.fancytree-selected span.fancytree-checkbox {
+ background-position: -64px -64px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -96px -64px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio {
+ background-position: -64px -96px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -96px -96px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+ background-position: 0px -64px;
+}
+.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: 0px -96px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -128px -64px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -64px -64px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -64px -96px;
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 6px;
+ background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ background-position: -64px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -96px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+ background-position: -128px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ background-position: -160px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ background-position: 0px -32px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -32px -32px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ background-position: -64px -32px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -96px -32px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+ background-position: -128px -32px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ background-position: -160px -32px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: url("../skin-win8-xxl/loading.gif");
+ background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ background-position: 0px -224px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 1px;
+ min-height: 32px;
+}
+span.fancytree-title {
+ color: black;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 32px;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 6px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+ background-position: -64px -224px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+ background-position: -32px -224px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 64px;
+ position: absolute;
+ background-position: 0px -256px;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 128px;
+ background-position: 0px -288px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+ background-position: -128px -256px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+ background-position: -64px -256px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl span.fancytree-connector,
+.fancytree-container.fancytree-rtl span.fancytree-expander,
+.fancytree-container.fancytree-rtl span.fancytree-icon,
+.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img {
+ background-image: url("../skin-win8-xxl/icons-rtl.gif");
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-win8-xxl/icons-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-win8-xxl/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+#fancytree-drop-marker.fancytree-rtl {
+ background-image: url("../skin-win8-xxl/icons-rtl.gif");
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #c0c0c0;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+ background-position: 0px -160px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+ background-position: -32px -160px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain span.fancytree-title {
+ border: 1px solid transparent;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title {
+ border-color: #3399ff;
+}
+.fancytree-plain span.fancytree-active span.fancytree-title,
+.fancytree-plain span.fancytree-selected span.fancytree-title {
+ background-color: #f7f7f7;
+ border-color: #dedede;
+}
+.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title {
+ font-style: italic;
+}
+.fancytree-plain span.fancytree-node:hover span.fancytree-title {
+ background-color: #eff9fe;
+ border-color: #70c0e7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title {
+ background-color: #cbe8f6;
+ border-color: #26a0da;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+ border: 1px solid #EDEDED;
+}
+table.fancytree-ext-table tbody span.fancytree-node,
+table.fancytree-ext-table tbody span.fancytree-node:hover {
+ border: none;
+ background: none;
+}
+table.fancytree-ext-table tbody tr:hover {
+ background-color: #E5F3FB;
+ outline: 1px solid #70C0E7;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+}
+table.fancytree-ext-table tbody tr.fancytree-active:hover,
+table.fancytree-ext-table tbody tr.fancytree-selected:hover {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+ background-color: #F7F7F7;
+ outline: 1px solid #DEDEDE;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+ background-color: #F7F7F7;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {
+ background-color: #CBE8F6;
+}
+ul.fancytree-container {
+ font-size: 20pt;
+ padding: 6px;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.less
new file mode 100644
index 0000000..2241d97
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.less
@@ -0,0 +1,40 @@
+/*!
+ * Fancytree "Win8" 32x32 skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "../skin-common.less";
+
+// Import standard win8
+@import "../skin-win8/ui.fancytree.less";
+
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+
+@fancy-level-indent: 32px;
+@fancy-line-height: 32px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 32px;
+@fancy-icon-height: 32px;
+@fancy-icon-spacing: 6px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-win8-xxl/";
+
+ul.fancytree-container {
+// font-family: tahoma, arial, helvetica;
+ font-size: 20pt;
+ padding: 6px;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.min.css
new file mode 100644
index 0000000..9c7e9ca
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/ui.fancytree.min.css
@@ -0,0 +1,11 @@
+/*!
+ * Fancytree "Win8" 32x32 skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 32px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-win8-xxl/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:32px;height:32px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url("../skin-win8-xxl/icons.gif");background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:0}span.fancytree-custom-icon{width:32px;height:32px;display:inline-block;margin-left:6px;background-position:0 0}img.fancytree-icon{width:32px;height:32px;margin-left:6px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-win8-xxl/icons.gif");margin-top:0}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover{background-position:0 -128px}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover{background-position:-32px -128px}.fancytree-exp-c span.fancytree-expander{background-position:0 -160px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-32px -160px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -192px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-32px -192px}.fancytree-exp-cd span.fancytree-expander{background-position:-128px -160px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-160px -160px}.fancytree-exp-cdl span.fancytree-expander{background-position:-128px -192px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-160px -192px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-64px -160px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-96px -160px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-64px -192px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-96px -192px}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:6px;background-position:0 -64px}span.fancytree-checkbox:hover{background-position:-32px -64px}span.fancytree-checkbox.fancytree-radio{background-position:0 -96px}span.fancytree-checkbox.fancytree-radio:hover{background-position:-32px -96px}.fancytree-partsel span.fancytree-checkbox{background-position:-128px -64px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-160px -64px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio{background-position:-128px -96px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover{background-position:-160px -96px}.fancytree-selected span.fancytree-checkbox{background-position:-64px -64px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-96px -64px}.fancytree-selected span.fancytree-checkbox.fancytree-radio{background-position:-64px -96px}.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-96px -96px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -64px}.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover{background-position:0 -96px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-128px -64px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-64px -64px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-64px -96px}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:6px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-64px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-96px 0}.fancytree-ico-e span.fancytree-icon{background-position:-128px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-160px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -32px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-32px -32px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-64px -32px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-96px -32px}.fancytree-ico-ef span.fancytree-icon{background-position:-128px -32px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-160px -32px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:url("../skin-win8-xxl/loading.gif");background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -224px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:32px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:32px;padding:0 3px 0 3px;margin:0 0 0 6px;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-64px -224px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-32px -224px}#fancytree-drop-marker{width:64px;position:absolute;background-position:0 -256px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:128px;background-position:0 -288px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-128px -256px}#fancytree-drop-marker.fancytree-drop-move{background-position:-64px -256px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl span.fancytree-connector,.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,.fancytree-container.fancytree-rtl span.fancytree-expander,.fancytree-container.fancytree-rtl span.fancytree-icon{background-image:url("../skin-win8-xxl/icons-rtl.gif")}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-win8-xxl/icons-rtl.gif")}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-win8-xxl/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}#fancytree-drop-marker.fancytree-rtl{background-image:url("../skin-win8-xxl/icons-rtl.gif")}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -160px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-32px -160px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-plain span.fancytree-title{border:1px solid transparent}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title{border-color:#39f}.fancytree-plain span.fancytree-active span.fancytree-title,.fancytree-plain span.fancytree-selected span.fancytree-title{background-color:#f7f7f7;border-color:#dedede}.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title{font-style:italic}.fancytree-plain span.fancytree-node:hover span.fancytree-title{background-color:#eff9fe;border-color:#70c0e7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title{background-color:#cbe8f6;border-color:#26a0da}table.fancytree-ext-table tbody tr td{border:1px solid #ededed}table.fancytree-ext-table tbody span.fancytree-node,table.fancytree-ext-table tbody span.fancytree-node:hover{border:none;background:0 0}table.fancytree-ext-table tbody tr:hover{background-color:#e5f3fb;outline:1px solid #70C0E7}table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title{outline:1px dotted black}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{background-color:#cbe8f6;outline:1px solid #26A0DA}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#f7f7f7;outline:1px solid #DEDEDE}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#f7f7f7}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active{background-color:#cbe8f6;outline:1px solid #26A0DA}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected{background-color:#cbe8f6}ul.fancytree-container{font-size:20pt;padding:6px} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/vline-rtl.gif
new file mode 100644
index 0000000..8b5a279
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/vline.gif
new file mode 100644
index 0000000..214e4dd
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8-xxl/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8/icons-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8/icons-rtl.gif
new file mode 100644
index 0000000..443e1e4
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8/icons-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8/icons.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8/icons.gif
new file mode 100644
index 0000000..0097b1f
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8/icons.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8/loading.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8/loading.gif
new file mode 100644
index 0000000..ef88497
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8/loading.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-win8/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.css
new file mode 100644
index 0000000..8a0ba4b
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.css
@@ -0,0 +1,765 @@
+/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #c0c0c0;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 16px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-win8/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-image: url("../skin-win8/icons.gif");
+ background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 2px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 16px;
+ height: 16px;
+ margin-left: 3px;
+ margin-top: 2px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-win8/icons.gif");
+ margin-top: 0;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover {
+ background-position: 0px -64px;
+}
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover {
+ background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+ background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+ background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+ background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+ background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+ background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ background-position: -48px -96px;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 3px;
+ background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+ background-position: -16px -32px;
+}
+span.fancytree-checkbox.fancytree-radio {
+ background-position: 0px -48px;
+}
+span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -16px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+ background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -80px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio {
+ background-position: -64px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -80px -48px;
+}
+.fancytree-selected span.fancytree-checkbox {
+ background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -48px -32px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio {
+ background-position: -32px -48px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -48px -48px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+ background-position: 0px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: 0px -48px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -32px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -32px -48px;
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+ background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+ background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: url("../skin-win8/loading.gif");
+ background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 0px;
+ min-height: 20px;
+}
+span.fancytree-title {
+ color: black;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 20px;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 3px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+ background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+ background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 32px;
+ position: absolute;
+ background-position: 0px -128px;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 64px;
+ background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+ background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+ background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl span.fancytree-connector,
+.fancytree-container.fancytree-rtl span.fancytree-expander,
+.fancytree-container.fancytree-rtl span.fancytree-icon,
+.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img {
+ background-image: url("../skin-win8/icons-rtl.gif");
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-win8/icons-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-win8/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+#fancytree-drop-marker.fancytree-rtl {
+ background-image: url("../skin-win8/icons-rtl.gif");
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #c0c0c0;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+ background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+ background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain span.fancytree-title {
+ border: 1px solid transparent;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title {
+ border-color: #3399ff;
+}
+.fancytree-plain span.fancytree-active span.fancytree-title,
+.fancytree-plain span.fancytree-selected span.fancytree-title {
+ background-color: #f7f7f7;
+ border-color: #dedede;
+}
+.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title {
+ font-style: italic;
+}
+.fancytree-plain span.fancytree-node:hover span.fancytree-title {
+ background-color: #eff9fe;
+ border-color: #70c0e7;
+}
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,
+.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title {
+ background-color: #cbe8f6;
+ border-color: #26a0da;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody tr td {
+ border: 1px solid #EDEDED;
+}
+table.fancytree-ext-table tbody span.fancytree-node,
+table.fancytree-ext-table tbody span.fancytree-node:hover {
+ border: none;
+ background: none;
+}
+table.fancytree-ext-table tbody tr:hover {
+ background-color: #E5F3FB;
+ outline: 1px solid #70C0E7;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+}
+table.fancytree-ext-table tbody tr.fancytree-active:hover,
+table.fancytree-ext-table tbody tr.fancytree-selected:hover {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+ background-color: #F7F7F7;
+ outline: 1px solid #DEDEDE;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+ background-color: #F7F7F7;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+}
+table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {
+ background-color: #CBE8F6;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.less
new file mode 100644
index 0000000..fdd3cf0
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.less
@@ -0,0 +1,158 @@
+/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Borders have NO radius and NO gradients are used!
+
+// both:
+// unselected background: white
+// hover bar (unselected, inactive): #E5F3FB (border: #70C0E7) 'very light blue'
+// active node: #CBE8F6 (border: #26A0DA) 'light blue'
+// active node with hover: wie active node
+
+// Tree view:
+// active node, tree inactive: #F7F7F7 (border: #DEDEDE) 'light gray, selected, but tree not active'
+
+// List view:
+// selected bar: --> active bar
+// focus bar: transparent(white) + border 1px solid #3399FF ()
+
+// table left/right border: #EDEDED 'light gray'
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+
+@fancy-line-height: 20px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 0px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 2px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+
+// @fancy-icon-width: 16px;
+// @fancy-icon-height: 16px;
+// @fancy-line-height: 16px;
+// @fancy-icon-spacing: 3px;
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-win8/";
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%;
+
+/*******************************************************************************
+ * Node titles
+ */
+.fancytree-plain {
+ span.fancytree-title {
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ }
+ &.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title {
+ border-color: #3399ff;
+ }
+ span.fancytree-active span.fancytree-title,
+ span.fancytree-selected span.fancytree-title { // active/selcted nodes inside inactive tree
+ background-color: #f7f7f7;
+ border-color: #dedede;
+ }
+ span.fancytree-node span.fancytree-selected span.fancytree-title {
+ font-style: italic;
+ }
+ span.fancytree-node:hover span.fancytree-title {
+ background-color: #eff9fe; // hover is always colored, even if tree is unfocused
+ border-color: #70c0e7;
+ }
+ &.fancytree-container.fancytree-treefocus {
+ span.fancytree-active span.fancytree-title,
+ span.fancytree-selected span.fancytree-title {
+ background-color: #cbe8f6;
+ border-color: #26a0da;
+ }
+ }
+}
+
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table tbody {
+ tr td {
+ border: 1px solid #EDEDED;
+ }
+ span.fancytree-node,
+ span.fancytree-node:hover { // undo standard tree css
+ border: none;
+ background: none;
+ }
+ // Title gets a white background, when hovered. Undo standard node formatting
+ // span.fancytree-title:hover {
+ // border: none; //1px solid transparent;
+ // background: inherit;
+ // background: transparent;
+ // background: none;
+ // filter: none;
+ // }
+ tr:hover {
+ background-color: #E5F3FB;
+ outline: 1px solid #70C0E7;
+ }
+ // tr:hover td {
+ // outline: 1px solid #D8F0FA;
+ // }
+ // tr.fancytree-focused {
+ // border-color: #3399FF;
+ // outline: 1px dotted black;
+ // }
+ tr.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+ }
+
+ tr.fancytree-active:hover,
+ tr.fancytree-selected:hover {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+ }
+ tr.fancytree-active { // dimmed, if inside inactive tree
+ background-color: #F7F7F7;
+ outline: 1px solid #DEDEDE;
+ }
+ tr.fancytree-selected { // dimmed, if inside inactive tree
+ background-color: #F7F7F7;
+ }
+}
+
+table.fancytree-ext-table.fancytree-treefocus tbody {
+ tr.fancytree-active {
+ background-color: #CBE8F6;
+ outline: 1px solid #26A0DA;
+ }
+ tr.fancytree-selected {
+ background-color: #CBE8F6;
+ }
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.min.css
new file mode 100644
index 0000000..a701af5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "Win8" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-win8/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url("../skin-win8/icons.gif");background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:2px}span.fancytree-custom-icon{width:16px;height:16px;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:2px;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-win8/icons.gif");margin-top:0}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}span.fancytree-checkbox.fancytree-radio{background-position:0 -48px}span.fancytree-checkbox.fancytree-radio:hover{background-position:-16px -48px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio{background-position:-64px -48px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover{background-position:-80px -48px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-selected span.fancytree-checkbox.fancytree-radio{background-position:-32px -48px}.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-48px -48px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover{background-position:0 -48px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-32px -48px}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:url("../skin-win8/loading.gif");background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:0;min-height:20px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:20px;padding:0 3px 0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl span.fancytree-connector,.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,.fancytree-container.fancytree-rtl span.fancytree-expander,.fancytree-container.fancytree-rtl span.fancytree-icon{background-image:url("../skin-win8/icons-rtl.gif")}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-win8/icons-rtl.gif")}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-win8/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}#fancytree-drop-marker.fancytree-rtl{background-image:url("../skin-win8/icons-rtl.gif")}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}.fancytree-plain span.fancytree-title{border:1px solid transparent}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title{border-color:#39f}.fancytree-plain span.fancytree-active span.fancytree-title,.fancytree-plain span.fancytree-selected span.fancytree-title{background-color:#f7f7f7;border-color:#dedede}.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title{font-style:italic}.fancytree-plain span.fancytree-node:hover span.fancytree-title{background-color:#eff9fe;border-color:#70c0e7}.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title{background-color:#cbe8f6;border-color:#26a0da}table.fancytree-ext-table tbody tr td{border:1px solid #ededed}table.fancytree-ext-table tbody span.fancytree-node,table.fancytree-ext-table tbody span.fancytree-node:hover{border:none;background:0 0}table.fancytree-ext-table tbody tr:hover{background-color:#e5f3fb;outline:1px solid #70C0E7}table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title{outline:1px dotted black}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{background-color:#cbe8f6;outline:1px solid #26A0DA}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#f7f7f7;outline:1px solid #DEDEDE}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#f7f7f7}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active{background-color:#cbe8f6;outline:1px solid #26A0DA}table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected{background-color:#cbe8f6} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8/vline-rtl.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-win8/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-win8/vline.gif
new file mode 100644
index 0000000..f9b4232
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-win8/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons-rtl.gif
new file mode 100644
index 0000000..a3f2c8a
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons-rtl__old__blue laxy expanders.gif b/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons-rtl__old__blue laxy expanders.gif
new file mode 100644
index 0000000..d59b0f5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons-rtl__old__blue laxy expanders.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons.gif b/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons.gif
new file mode 100644
index 0000000..0d0635c
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons__old__blue lazy expanders.gif b/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons__old__blue lazy expanders.gif
new file mode 100644
index 0000000..a58eb93
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/icons__old__blue lazy expanders.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/loading.gif b/plugins/55/indexmenu/scripts/fancytree/skin-xp/loading.gif
new file mode 100644
index 0000000..251df05
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/loading.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/skin-common.less b/plugins/55/indexmenu/scripts/fancytree/skin-xp/skin-common.less
new file mode 100644
index 0000000..fc0da50
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/skin-common.less
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+
+// Variables (defaults, may be overwritten by the including .less files)
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+// @fancy-hide-connectors: true; // false: show vertical connector lines
+
+@fancy-level-indent: 16px;
+@fancy-line-height: 16px; // height of a nodes selection bar including borders
+@fancy-node-v-spacing: 1px; // gap between two node borders
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title
+@fancy-icon-ofs-top: 0px; // extra vertical offset for expander, checkbox and icon
+@fancy-title-ofs-top: 0px; // extra vertical offset for title
+@fancy-node-border-width: 1px;
+@fancy-node-border-radius: 0px;
+@fancy-node-outline-width: 1px;
+
+// @fancy-line-ofs-top: (@fancy-line-height - @fancy-icon-height) / 2;
+
+// webpack uses /dist/skin-common.less as root path
+// grunt-less uses /dist/skin-Xxx/ui.fancyree.less as root path
+// So we define our theme LESS files for webpack compatibility, i.e.
+// define the image path n every main LESS file instead of here.
+// Prefix may be set to "", "/", "./", or any other value
+// Note: this variable must be defined by the main LESS files:
+// @fancy-image-prefix: "";
+
+// Use 'url(...)' to link to the throbber image, or
+// use data-uri(...)' to inline the data in css instead:
+/* CHANGE use url, as less does not handel data-uri() correct. DokuWiki can eventually inline it */
+ @fancy-loading-url: url("@{fancy-image-prefix}loading.gif");
+//@fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+
+// Set to `true` to use `data-uri(...)` instead of a `url(...)` link:
+@fancy-inline-sprites: false; // data-uri() is not handle correct by phpless
+
+@fancy-font-size: 10pt;
+@fancy-font-family: tahoma, arial, helvetica;
+@fancy-font-color: black;
+@fancy-font-color-dimm: #c0c0c0;
+@fancy-font-error-color: red;
+
+//------------------------------------------------------------------------------
+// Mixins
+//------------------------------------------------------------------------------
+.setBgPos(@x, @y, @cond:true) when (@cond) {
+ background-position: (@x * -@fancy-icon-width) (@y * -@fancy-icon-height);
+}
+.clearBgImage(@cond:true) when (@cond) {
+ background-image: none;
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and not (@fancy-inline-sprites) {
+ background-image: url("@{fancy-image-prefix}@{url}");
+}
+.setBgImageUrl(@url) when (@fancy-use-sprites) and (@fancy-inline-sprites) {
+ background-image: data-uri("@{fancy-image-prefix}@{url}");
+}
+.useSprite(@x, @y) when (@fancy-use-sprites) {
+ .setBgPos(@x, @y);
+}
+.rounded-corners(@radius) {
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+ -ms-border-radius: @radius;
+ -o-border-radius: @radius;
+ border-radius: @radius;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor) {
+ border-color: @bordercolor;
+ background: @bgcolor;
+ color: @color;
+}
+.spanStyleMixin(@color, @bgcolor, @bordercolor, @startColor, @stopColor) {
+ .spanStyleMixin(@color, @bgcolor, @bordercolor);
+ // @c-start: argb(@startColor);
+ // @c-end: argb(@stopColor);
+ background: -moz-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // FF3.6+
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0%, @startColor),
+ color-stop(100%, @stopColor)
+ ); // Chrome,Safari4+
+ background: -webkit-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Chrome10+,Safari5.1+
+ background: -o-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // Opera 11.10+
+ background: -ms-linear-gradient(
+ top,
+ @startColor 0%,
+ @stopColor 100%
+ ); // IE10+
+ background: linear-gradient(
+ to bottom,
+ @startColor 0%,
+ @stopColor 100%
+ ); // W3C
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@{startColor}', endColorstr='@{stopColor}',GradientType=0 ); // IE6-9
+}
+
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+// Redefine, in case jQuery-UI is not included
+// .ui-helper-hidden,
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ // tri-state checkbox
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: @fancy-font-color-dimm;
+}
+
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+/* CHANGE: renamed spin to spin-fancytree */
+.fancytree-helper-spin {
+ -webkit-animation: spin-fancytree 1000ms infinite linear;
+ animation: spin-fancytree 1000ms infinite linear;
+}
+/* CHANGE: commented because it is wrong prefixed by phpless
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+*/
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+
+ul.fancytree-container {
+ font-family: @fancy-font-family;
+ font-size: @fancy-font-size;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0; // DT issue 201
+ //background-color: white; CHANGE
+ //border: 1px dotted gray; CHANGE
+ // overflow: auto; // ext-dnd5: otherwise this is always the scroll parent
+ // height: 100%; // DT issue 263, 470
+ min-height: 0%; // #192
+ position: relative; // #235
+ ul {
+ padding: 0 0 0 @fancy-level-indent;
+ margin: 0;
+ }
+ ul > li:before {
+ // #538
+ content: none;
+ }
+ li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ .setBgPos(0, 0);
+ background-repeat: repeat-y;
+ background-image: none; // no v-lines
+
+ margin: 0;
+ // padding: 1px 0 0 0; // issue #246
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+
+// Style, when control is disabled
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ // filter: alpha(opacity=50); // Yields a css warning
+ background-color: silver;
+}
+
+ul.fancytree-connectors.fancytree-container {
+ li {
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: phpless does not handle data-uri() correct */
+ //background-image: data-uri("@{fancy-image-prefix}vline.gif");
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 0;
+ }
+}
+
+// Suppress lines for last child node
+ul.fancytree-container li.fancytree-lastsib,
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// Fix jQuery UI 'blind' animation for jQuery UI (#717)
+li.fancytree-animating {
+ position: relative;
+}
+
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+// span.fancytree-radio,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ // display: -moz-inline-box; // @ FF 1+2 removed for issue 221
+ // -moz-box-align: start; /* issue 221 */
+ display: inline-block; // Required to make a span sizeable
+ vertical-align: top;
+ background-repeat: no-repeat;
+ // background-position: left;
+ .setBgImageUrl("icons.gif");
+ .setBgPos(0, 0);
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+// span.fancytree-radio,
+span.fancytree-custom-icon {
+ margin-top: @fancy-icon-ofs-top;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ display: inline-block;
+ margin-left: @fancy-icon-spacing;
+ .setBgPos(0, 0);
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: @fancy-icon-width;
+ height: @fancy-icon-height;
+ margin-left: @fancy-icon-spacing;
+ margin-top: @fancy-icon-ofs-top;
+ vertical-align: top;
+ border-style: none;
+}
+
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-expander {
+ // .useSprite(0, 5);
+ cursor: pointer;
+}
+// span.fancytree-expander:hover {
+// // .useSprite(1, 5);
+// }
+
+// --- End nodes (use connectors instead of expanders)
+
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ // .clearBgImage( @fancy-hide-connectors );
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors {
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ margin-top: 0;
+ }
+ .fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+ .fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+ .fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+ }
+}
+
+// --- Collapsed
+
+.fancytree-exp-c span.fancytree-expander {
+ // Collapsed, not delayed, not last sibling
+ .useSprite(0, 5);
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ .useSprite(1, 5);
+}
+.fancytree-exp-cl span.fancytree-expander {
+ // Collapsed, not delayed, last sibling
+ .useSprite(0, 6);
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ .useSprite(1, 6);
+}
+.fancytree-exp-cd span.fancytree-expander {
+ // Collapsed, delayed, not last sibling
+ .useSprite(4, 5);
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ .useSprite(5, 5);
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ // Collapsed, delayed, last sibling
+ .useSprite(4, 6);
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ .useSprite(5, 6);
+}
+
+// --- Expanded
+
+.fancytree-exp-e span.fancytree-expander, // Expanded, not delayed, not last sibling
+.fancytree-exp-ed span.fancytree-expander {
+ // Expanded, delayed, not last sibling
+ .useSprite(2, 5);
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ .useSprite(3, 5);
+}
+.fancytree-exp-el span.fancytree-expander, // Expanded, not delayed, last sibling
+.fancytree-exp-edl span.fancytree-expander {
+ // Expanded, delayed, last sibling
+ .useSprite(2, 6);
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ .useSprite(3, 6);
+}
+
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander {
+ span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+ }
+ &:hover span.fancytree-expander,
+ &.fancytree-treefocus span.fancytree-expander,
+ .fancytree-treefocus span.fancytree-expander,
+ [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+ }
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Checkbox icon
+// *----------------------------------------------------------------------------*/
+//
+//span.fancytree-checkbox {
+// margin-left: @fancy-icon-spacing;
+// .useSprite(0, 2);
+// &:hover {
+// .useSprite(1, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(0, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(1, 3);
+// }
+//}
+//.fancytree-partsel span.fancytree-checkbox {
+// .useSprite(4, 2);
+// &:hover {
+// .useSprite(5, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(4, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(5, 3);
+// }
+//}
+//// selected after partsel, so it takes precedence:
+//.fancytree-selected span.fancytree-checkbox {
+// .useSprite(2, 2);
+// &:hover {
+// .useSprite(3, 2);
+// }
+// &.fancytree-radio {
+// .useSprite(2, 3);
+// }
+// &.fancytree-radio:hover {
+// .useSprite(3, 3);
+// }
+//}
+//// Unselectable is dimmed, without hover effects
+//.fancytree-unselectable {
+// span.fancytree-checkbox {
+// opacity: 0.4;
+// filter: alpha(opacity=40);
+// }
+// span.fancytree-checkbox:hover {
+// .useSprite(0, 2);
+// }
+// span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(0, 3);
+// }
+// &.fancytree-partsel span.fancytree-checkbox:hover {
+// .useSprite(4, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox:hover {
+// .useSprite(2, 2);
+// }
+// &.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+// .useSprite(2, 3);
+// }
+//}
+//
+//// Auto-hide checkboxes unless selected or hovered
+//.fancytree-container.fancytree-checkbox-auto-hide {
+// span.fancytree-checkbox {
+// visibility: hidden;
+// }
+// .fancytree-node:hover span.fancytree-checkbox,
+// tr:hover td span.fancytree-checkbox,
+// .fancytree-node.fancytree-selected span.fancytree-checkbox,
+// tr.fancytree-selected td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// &.fancytree-treefocus {
+// .fancytree-node.fancytree-active span.fancytree-checkbox,
+// tr.fancytree-active td span.fancytree-checkbox {
+// visibility: unset;
+// }
+// }
+//}
+
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-icon {
+ // Default icon
+ margin-left: @fancy-icon-spacing;
+ .useSprite(0, 0);
+}
+
+/* Documents */
+.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (empty)
+ // .useSprite(0, 0);
+}
+.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(1, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 0);
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ .useSprite(3, 0);
+}
+.fancytree-ico-e span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 0);
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ .useSprite(5, 0);
+}
+
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (empty)
+ .useSprite(0, 1);
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(1, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ // Collapsed folder (not empty)
+ .useSprite(2, 1);
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ .useSprite(3, 1);
+}
+.fancytree-ico-ef span.fancytree-icon {
+ // Expanded folder
+ .useSprite(4, 1);
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ .useSprite(5, 1);
+}
+
+// 'Loading' status overrides all others
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: @fancy-loading-url;
+ .useSprite(0, 0);
+}
+
+/* Status node icons */
+
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ .useSprite(0, 7);
+}
+
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+
+span.fancytree-node {
+ /* See #117 */
+ display: inherit; // #117, resolves to 'display: list-item;' for standard trees
+ width: 100%;
+ margin-top: @fancy-node-v-spacing;
+ min-height: @fancy-line-height;
+}
+span.fancytree-title {
+ color: @fancy-font-color; // inherit doesn't work on IE
+ cursor: pointer;
+ display: inline-block; // Better alignment, when title contains <br>
+ vertical-align: top;
+ min-height: @fancy-line-height;
+ padding: 0 3px 0 3px; // Otherwise italic font will be outside right bounds
+ margin: @fancy-title-ofs-top 0 0 @fancy-icon-spacing;
+ // margin: 0px;
+ // margin-top: @fancy-line-ofs-top;
+ // margin-left: @fancy-icon-spacing;
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+ .rounded-corners(@fancy-node-border-radius);
+ // outline: 0; // @ Firefox, prevent dotted border after click
+ // Set transparent border to prevent jumping when active node gets a border
+ // (we can do this, because this theme doesn't use vertical lines)
+ // border: 1px solid white; // Note: 'transparent' would not work in IE6
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: @fancy-font-error-color;
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * Drag'n'drop support
+// *----------------------------------------------------------------------------*/
+///* ext-dnd5: */
+//span.fancytree-childcounter {
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+//}
+//
+///* ext-dnd: */
+//div.fancytree-drag-helper {
+// span.fancytree-childcounter,
+// span.fancytree-dnd-modifier {
+// display: inline-block;
+// color: #fff;
+// background: #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// min-width: 10px;
+// // min-height: 16px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+// span.fancytree-childcounter {
+// position: absolute;
+// // left: 16px;
+// top: -6px;
+// right: -6px;
+// }
+// span.fancytree-dnd-modifier {
+// background: #5cb85c; // bootstrap green
+// border: none;
+// // min-height: 16px;
+// // font-size: 12px;
+// font-weight: bolder;
+// }
+// &.fancytree-drop-accept {
+// span.fancytree-drag-helper-img {
+// .useSprite(2, 7);
+// }
+// }
+// &.fancytree-drop-reject {
+// span.fancytree-drag-helper-img {
+// .useSprite(1, 7);
+// }
+// }
+//}
+//
+///*** Drop marker icon *********************************************************/
+//#fancytree-drop-marker {
+// width: 2 * @fancy-icon-width; // was 24px, but 32 should be correct
+// position: absolute;
+// .useSprite(0, 8);
+// margin: 0;
+// &.fancytree-drop-after,
+// &.fancytree-drop-before {
+// width: 4 * @fancy-icon-width; // 64px;
+// .useSprite(0, 9);
+// }
+// &.fancytree-drop-copy {
+// .useSprite(4, 8);
+// }
+// &.fancytree-drop-move {
+// .useSprite(2, 8);
+// }
+//}
+//
+///*** Source node while dragging ***********************************************/
+//
+//span.fancytree-drag-source {
+// &.fancytree-drag-remove {
+// // text-decoration: line-through;
+// opacity: 0.15;
+// }
+//}
+//
+///*** Target node while dragging cursor is over it *****************************/
+//
+//span.fancytree-drop-target {
+// &.fancytree-drop-accept {
+// // outline: 1px dotted #5cb85c; // bootstrap sucess
+// }
+//}
+//span.fancytree-drop-reject {
+// // outline: 1px dotted #d9534f; // boostrap warning
+//}
+
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+
+.fancytree-container.fancytree-rtl {
+ .fancytree-title {
+ /*unicode-bidi: bidi-override;*/ /* optional: reverse title letters */
+ }
+ span.fancytree-connector,
+ span.fancytree-expander,
+ span.fancytree-icon,
+ span.fancytree-drag-helper-img {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander,
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ }
+ &.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+ &.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons-rtl.gif");
+ }
+}
+ul.fancytree-container.fancytree-rtl {
+ ul {
+ padding: 0 16px 0 0;
+ }
+ &.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib,
+ // Suppress lines if level is fixed expanded (option minExpandLevel)
+ &.fancytree-no-connector > li {
+ background-image: none;
+ }
+}
+#fancytree-drop-marker.fancytree-rtl {
+ .setBgImageUrl("icons-rtl.gif");
+}
+
+//// CHANGE: not used.
+///*------------------------------------------------------------------------------
+// * 'table' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-table {
+// font-family: @fancy-font-family;
+// font-size: @fancy-font-size;
+// border-collapse: collapse;
+// span.fancytree-node {
+// display: inline-block; // #117
+// box-sizing: border-box; // #562
+// }
+// td.fancytree-status-merged {
+// text-align: center;
+// // font-weight: bold;
+// font-style: italic;
+// // line-height: 100px;
+// color: @fancy-font-color-dimm;
+// }
+// tr.fancytree-statusnode-error td.fancytree-status-merged {
+// color: @fancy-font-error-color;
+// }
+// /* ext-ariagrid */
+// &.fancytree-ext-ariagrid.fancytree-cell-mode {
+// > tbody > tr.fancytree-active > td {
+// background-color: #eee;
+// }
+// > tbody > tr > td.fancytree-active-cell {
+// background-color: #cbe8f6;
+// }
+// &.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+// background-color: #3875d7;
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'columnview' extension
+// *----------------------------------------------------------------------------*/
+//
+//table.fancytree-ext-columnview {
+// // border-collapse: collapse;
+// // width: 100%;
+// tbody tr td {
+// position: relative;
+// border: 1px solid gray;
+// vertical-align: top;
+// overflow: auto;
+// > ul {
+// padding: 0;
+// li {
+// list-style-image: none;
+// list-style-position: outside;
+// list-style-type: none;
+// -moz-background-clip: border;
+// -moz-background-inline-policy: continuous;
+// -moz-background-origin: padding;
+// background-attachment: scroll;
+// background-color: transparent;
+// .setBgPos(0, 0);
+// background-repeat: repeat-y;
+// background-image: none; /* no v-lines */
+//
+// margin: 0;
+// // padding: 1px 0 0 0; // issue #246
+// }
+// }
+// }
+// span.fancytree-node {
+// position: relative; /* allow positioning of embedded spans */
+// display: inline-block; // #117
+// }
+// span.fancytree-node.fancytree-expanded {
+// background-color: #e0e0e0;
+// }
+// span.fancytree-node.fancytree-active {
+// background-color: #cbe8f6;
+// // background-color: royalblue;
+// }
+// .fancytree-has-children span.fancytree-cv-right {
+// position: absolute;
+// right: 3px;
+// .useSprite(0, 5);
+// &:hover {
+// .useSprite(1, 5);
+// }
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'filter' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-filter-dimm {
+// span.fancytree-node span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: bold;
+// }
+//}
+//.fancytree-ext-filter-hide {
+// tr.fancytree-hide,
+// span.fancytree-node.fancytree-hide {
+// display: none;
+// }
+// tr.fancytree-submatch span.fancytree-title,
+// span.fancytree-node.fancytree-submatch span.fancytree-title {
+// color: @fancy-font-color-dimm;
+// font-weight: lighter;
+// }
+// tr.fancytree-match span.fancytree-title,
+// span.fancytree-node.fancytree-match span.fancytree-title {
+// color: black;
+// font-weight: normal;
+// }
+//}
+///* Hide expanders if all child nodes are hidden by filter */
+//.fancytree-ext-filter-hide-expanders {
+// tr.fancytree-match span.fancytree-expander,
+// span.fancytree-node.fancytree-match span.fancytree-expander {
+// visibility: hidden;
+// }
+// tr.fancytree-submatch span.fancytree-expander,
+// span.fancytree-node.fancytree-submatch span.fancytree-expander {
+// visibility: visible;
+// }
+//}
+//
+//.fancytree-ext-childcounter,
+//.fancytree-ext-filter {
+// // span.fancytree-title mark {
+// // font-style: normal;
+// // background-color: #ead61c; // yellow
+// // border-radius: 3px;
+// // }
+// span.fancytree-icon,
+// span.fancytree-custom-icon {
+// position: relative;
+// }
+// span.fancytree-childcounter {
+// color: #fff;
+// background: #777; // #337ab7; // bootstrap blue
+// border: 1px solid gray;
+// position: absolute;
+// top: -6px;
+// right: -6px;
+// min-width: 10px;
+// height: 10px;
+// line-height: 1;
+// vertical-align: baseline;
+// border-radius: 10px;
+// padding: 2px;
+// text-align: center;
+// font-size: 9px;
+// }
+//}
+///*------------------------------------------------------------------------------
+// * 'wide' extension
+// *----------------------------------------------------------------------------*/
+//
+//ul.fancytree-ext-wide {
+// position: relative;
+// min-width: 100%;
+// z-index: 2;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+//
+// span.fancytree-node > span {
+// position: relative;
+// z-index: 2;
+// }
+// span.fancytree-node span.fancytree-title {
+// position: absolute; // Allow left: 0. Note: prevents smooth dropdown animation
+// z-index: 1; // Behind expander and checkbox
+// left: 0px;
+// min-width: 100%;
+// margin-left: 0;
+// margin-right: 0;
+//
+// -webkit-box-sizing: border-box;
+// -moz-box-sizing: border-box;
+// box-sizing: border-box;
+// }
+//}
+//
+///*------------------------------------------------------------------------------
+// * 'fixed' extension
+// *----------------------------------------------------------------------------*/
+//
+//.fancytree-ext-fixed-wrapper {
+// .fancytree-ext-fixed-hidden {
+// display: none;
+// }
+// div.fancytree-ext-fixed-scroll-border-bottom {
+// border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-scroll-border-right {
+// border-right: 3px solid rgba(0, 0, 0, 0.75);
+// }
+// div.fancytree-ext-fixed-wrapper-tl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 3;
+// top: 0px;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-tr {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// top: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-bl {
+// position: absolute;
+// overflow: hidden;
+// z-index: 2;
+// left: 0px;
+// }
+// div.fancytree-ext-fixed-wrapper-br {
+// position: absolute;
+// overflow: scroll;
+// z-index: 1;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.css b/plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.css
new file mode 100644
index 0000000..855c0ff
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.css
@@ -0,0 +1,779 @@
+/*!
+ * Fancytree "XP" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+/*******************************************************************************
+ * Common Styles for Fancytree Skins.
+ *
+ * This section is automatically generated from the `skin-common.less` template.
+ *
+ * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.38.3
+ * @date 2023-02-01T20:52:50Z
+******************************************************************************/
+/*------------------------------------------------------------------------------
+ * Helpers
+ *----------------------------------------------------------------------------*/
+.fancytree-helper-hidden {
+ display: none;
+}
+.fancytree-helper-indeterminate-cb {
+ color: #777;
+}
+.fancytree-helper-disabled {
+ color: #c0c0c0;
+}
+/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
+.fancytree-helper-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*------------------------------------------------------------------------------
+ * Container and UL / LI
+ *----------------------------------------------------------------------------*/
+ul.fancytree-container {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ white-space: nowrap;
+ padding: 3px;
+ margin: 0;
+ background-color: white;
+ border: 1px dotted gray;
+ min-height: 0%;
+ position: relative;
+}
+ul.fancytree-container ul {
+ padding: 0 0 0 16px;
+ margin: 0;
+}
+ul.fancytree-container ul > li:before {
+ content: none;
+}
+ul.fancytree-container li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ margin: 0;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+.ui-fancytree-disabled ul.fancytree-container {
+ opacity: 0.5;
+ background-color: silver;
+}
+ul.fancytree-connectors.fancytree-container li {
+ background-image: url("../skin-xp/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container li.fancytree-lastsib,
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+li.fancytree-animating {
+ position: relative;
+}
+/*------------------------------------------------------------------------------
+ * Common icon definitions
+ *----------------------------------------------------------------------------*/
+span.fancytree-empty,
+span.fancytree-vline,
+span.fancytree-expander,
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-drag-helper-img,
+#fancytree-drop-marker {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ vertical-align: top;
+ background-repeat: no-repeat;
+ background-image: url("../skin-xp/icons.gif");
+ background-position: 0px 0px;
+}
+span.fancytree-icon,
+span.fancytree-checkbox,
+span.fancytree-expander,
+span.fancytree-custom-icon {
+ margin-top: 0px;
+}
+/* Used by icon option: */
+span.fancytree-custom-icon {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Used by 'icon' node option: */
+img.fancytree-icon {
+ width: 16px;
+ height: 16px;
+ margin-left: 3px;
+ margin-top: 0px;
+ vertical-align: top;
+ border-style: none;
+}
+/*------------------------------------------------------------------------------
+ * Expander icon
+ *
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-exp-
+ * 1st character: 'e': expanded, 'c': collapsed, 'n': no children
+ * 2nd character (optional): 'd': lazy (Delayed)
+ * 3rd character (optional): 'l': Last sibling
+ *----------------------------------------------------------------------------*/
+span.fancytree-expander {
+ cursor: pointer;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+ cursor: default;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-xp/icons.gif");
+ margin-top: 0;
+}
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover {
+ background-position: 0px -64px;
+}
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,
+.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover {
+ background-position: -16px -64px;
+}
+.fancytree-exp-c span.fancytree-expander {
+ background-position: 0px -80px;
+}
+.fancytree-exp-c span.fancytree-expander:hover {
+ background-position: -16px -80px;
+}
+.fancytree-exp-cl span.fancytree-expander {
+ background-position: 0px -96px;
+}
+.fancytree-exp-cl span.fancytree-expander:hover {
+ background-position: -16px -96px;
+}
+.fancytree-exp-cd span.fancytree-expander {
+ background-position: -64px -80px;
+}
+.fancytree-exp-cd span.fancytree-expander:hover {
+ background-position: -80px -80px;
+}
+.fancytree-exp-cdl span.fancytree-expander {
+ background-position: -64px -96px;
+}
+.fancytree-exp-cdl span.fancytree-expander:hover {
+ background-position: -80px -96px;
+}
+.fancytree-exp-e span.fancytree-expander,
+.fancytree-exp-ed span.fancytree-expander {
+ background-position: -32px -80px;
+}
+.fancytree-exp-e span.fancytree-expander:hover,
+.fancytree-exp-ed span.fancytree-expander:hover {
+ background-position: -48px -80px;
+}
+.fancytree-exp-el span.fancytree-expander,
+.fancytree-exp-edl span.fancytree-expander {
+ background-position: -32px -96px;
+}
+.fancytree-exp-el span.fancytree-expander:hover,
+.fancytree-exp-edl span.fancytree-expander:hover {
+ background-position: -48px -96px;
+}
+/* Fade out expanders, when container is not hovered or active */
+.fancytree-fade-expander span.fancytree-expander {
+ transition: opacity 1.5s;
+ opacity: 0;
+}
+.fancytree-fade-expander:hover span.fancytree-expander,
+.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,
+.fancytree-fade-expander [class*="fancytree-statusnode-"] span.fancytree-expander {
+ transition: opacity 0.6s;
+ opacity: 1;
+}
+/*------------------------------------------------------------------------------
+ * Checkbox icon
+ *----------------------------------------------------------------------------*/
+span.fancytree-checkbox {
+ margin-left: 3px;
+ background-position: 0px -32px;
+}
+span.fancytree-checkbox:hover {
+ background-position: -16px -32px;
+}
+span.fancytree-checkbox.fancytree-radio {
+ background-position: 0px -48px;
+}
+span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -16px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox {
+ background-position: -64px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -80px -32px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio {
+ background-position: -64px -48px;
+}
+.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -80px -48px;
+}
+.fancytree-selected span.fancytree-checkbox {
+ background-position: -32px -32px;
+}
+.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -48px -32px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio {
+ background-position: -32px -48px;
+}
+.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -48px -48px;
+}
+.fancytree-unselectable span.fancytree-checkbox {
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+.fancytree-unselectable span.fancytree-checkbox:hover {
+ background-position: 0px -32px;
+}
+.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: 0px -48px;
+}
+.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {
+ background-position: -64px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {
+ background-position: -32px -32px;
+}
+.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover {
+ background-position: -32px -48px;
+}
+.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox {
+ visibility: hidden;
+}
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox {
+ visibility: unset;
+}
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,
+.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox {
+ visibility: unset;
+}
+/*------------------------------------------------------------------------------
+ * Node type icon
+ * Note: IE6 doesn't correctly evaluate multiples class names,
+ * so we create combined class names that can be used in the CSS.
+ *
+ * Prefix: fancytree-ico-
+ * 1st character: 'e': expanded, 'c': collapsed
+ * 2nd character (optional): 'f': folder
+ *----------------------------------------------------------------------------*/
+span.fancytree-icon {
+ margin-left: 3px;
+ background-position: 0px 0px;
+}
+/* Documents */
+.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -16px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
+ background-position: -32px 0px;
+}
+.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
+ background-position: -48px 0px;
+}
+.fancytree-ico-e span.fancytree-icon {
+ background-position: -64px 0px;
+}
+.fancytree-ico-e span.fancytree-icon:hover {
+ background-position: -80px 0px;
+}
+/* Folders */
+.fancytree-ico-cf span.fancytree-icon {
+ background-position: 0px -16px;
+}
+.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -16px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
+ background-position: -32px -16px;
+}
+.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
+ background-position: -48px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon {
+ background-position: -64px -16px;
+}
+.fancytree-ico-ef span.fancytree-icon:hover {
+ background-position: -80px -16px;
+}
+.fancytree-loading span.fancytree-expander,
+.fancytree-loading span.fancytree-expander:hover,
+.fancytree-statusnode-loading span.fancytree-icon,
+.fancytree-statusnode-loading span.fancytree-icon:hover,
+span.fancytree-icon.fancytree-icon-loading {
+ background-image: url("../skin-xp/loading.gif");
+ background-position: 0px 0px;
+}
+/* Status node icons */
+.fancytree-statusnode-error span.fancytree-icon,
+.fancytree-statusnode-error span.fancytree-icon:hover {
+ background-position: 0px -112px;
+}
+/*------------------------------------------------------------------------------
+ * Node titles and highlighting
+ *----------------------------------------------------------------------------*/
+span.fancytree-node {
+ /* See #117 */
+ display: inherit;
+ width: 100%;
+ margin-top: 1px;
+ min-height: 16px;
+}
+span.fancytree-title {
+ color: black;
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: top;
+ min-height: 16px;
+ padding: 0 3px 0 3px;
+ margin: 0px 0 0 3px;
+ border: 0 solid transparent;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ -ms-border-radius: 0px;
+ -o-border-radius: 0px;
+ border-radius: 0px;
+}
+span.fancytree-node.fancytree-error span.fancytree-title {
+ color: red;
+}
+/*------------------------------------------------------------------------------
+ * Drag'n'drop support
+ *----------------------------------------------------------------------------*/
+/* ext-dnd5: */
+span.fancytree-childcounter {
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+}
+/* ext-dnd: */
+div.fancytree-drag-helper span.fancytree-childcounter,
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ display: inline-block;
+ color: #fff;
+ background: #337ab7;
+ border: 1px solid gray;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+div.fancytree-drag-helper span.fancytree-childcounter {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+}
+div.fancytree-drag-helper span.fancytree-dnd-modifier {
+ background: #5cb85c;
+ border: none;
+ font-weight: bolder;
+}
+div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {
+ background-position: -32px -112px;
+}
+div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {
+ background-position: -16px -112px;
+}
+/*** Drop marker icon *********************************************************/
+#fancytree-drop-marker {
+ width: 32px;
+ position: absolute;
+ background-position: 0px -128px;
+ margin: 0;
+}
+#fancytree-drop-marker.fancytree-drop-after,
+#fancytree-drop-marker.fancytree-drop-before {
+ width: 64px;
+ background-position: 0px -144px;
+}
+#fancytree-drop-marker.fancytree-drop-copy {
+ background-position: -64px -128px;
+}
+#fancytree-drop-marker.fancytree-drop-move {
+ background-position: -32px -128px;
+}
+/*** Source node while dragging ***********************************************/
+span.fancytree-drag-source.fancytree-drag-remove {
+ opacity: 0.15;
+}
+/*** Target node while dragging cursor is over it *****************************/
+/*------------------------------------------------------------------------------
+ * 'rtl' option
+ *----------------------------------------------------------------------------*/
+.fancytree-container.fancytree-rtl .fancytree-title {
+ /*unicode-bidi: bidi-override;*/
+ /* optional: reverse title letters */
+}
+.fancytree-container.fancytree-rtl span.fancytree-connector,
+.fancytree-container.fancytree-rtl span.fancytree-expander,
+.fancytree-container.fancytree-rtl span.fancytree-icon,
+.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img {
+ background-image: url("../skin-xp/icons-rtl.gif");
+}
+.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: none;
+}
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,
+.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-xp/icons-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl ul {
+ padding: 0 16px 0 0;
+}
+ul.fancytree-container.fancytree-rtl.fancytree-connectors li {
+ background-position: right 0;
+ background-image: url("../skin-xp/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
+ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
+ background-image: none;
+}
+#fancytree-drop-marker.fancytree-rtl {
+ background-image: url("../skin-xp/icons-rtl.gif");
+}
+/*------------------------------------------------------------------------------
+ * 'table' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-table {
+ font-family: tahoma, arial, helvetica;
+ font-size: 10pt;
+ border-collapse: collapse;
+ /* ext-ariagrid */
+}
+table.fancytree-ext-table span.fancytree-node {
+ display: inline-block;
+ box-sizing: border-box;
+}
+table.fancytree-ext-table td.fancytree-status-merged {
+ text-align: center;
+ font-style: italic;
+ color: #c0c0c0;
+}
+table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged {
+ color: red;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr.fancytree-active > td {
+ background-color: #eee;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode > tbody > tr > td.fancytree-active-cell {
+ background-color: #3875d7;
+}
+/*------------------------------------------------------------------------------
+ * 'columnview' extension
+ *----------------------------------------------------------------------------*/
+table.fancytree-ext-columnview tbody tr td {
+ position: relative;
+ border: 1px solid gray;
+ vertical-align: top;
+ overflow: auto;
+}
+table.fancytree-ext-columnview tbody tr td > ul {
+ padding: 0;
+}
+table.fancytree-ext-columnview tbody tr td > ul li {
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ background-attachment: scroll;
+ background-color: transparent;
+ background-position: 0px 0px;
+ background-repeat: repeat-y;
+ background-image: none;
+ /* no v-lines */
+ margin: 0;
+}
+table.fancytree-ext-columnview span.fancytree-node {
+ position: relative;
+ /* allow positioning of embedded spans */
+ display: inline-block;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
+ background-color: #e0e0e0;
+}
+table.fancytree-ext-columnview span.fancytree-node.fancytree-active {
+ background-color: #cbe8f6;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
+ position: absolute;
+ right: 3px;
+ background-position: 0px -80px;
+}
+table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
+ background-position: -16px -80px;
+}
+/*------------------------------------------------------------------------------
+ * 'filter' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: bold;
+}
+.fancytree-ext-filter-hide tr.fancytree-hide,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
+ display: none;
+}
+.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
+ color: #c0c0c0;
+ font-weight: lighter;
+}
+.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
+.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
+ color: black;
+ font-weight: normal;
+}
+/* Hide expanders if all child nodes are hidden by filter */
+.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {
+ visibility: hidden;
+}
+.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,
+.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {
+ visibility: visible;
+}
+.fancytree-ext-childcounter span.fancytree-icon,
+.fancytree-ext-filter span.fancytree-icon,
+.fancytree-ext-childcounter span.fancytree-custom-icon,
+.fancytree-ext-filter span.fancytree-custom-icon {
+ position: relative;
+}
+.fancytree-ext-childcounter span.fancytree-childcounter,
+.fancytree-ext-filter span.fancytree-childcounter {
+ color: #fff;
+ background: #777;
+ border: 1px solid gray;
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ min-width: 10px;
+ height: 10px;
+ line-height: 1;
+ vertical-align: baseline;
+ border-radius: 10px;
+ padding: 2px;
+ text-align: center;
+ font-size: 9px;
+}
+/*------------------------------------------------------------------------------
+ * 'wide' extension
+ *----------------------------------------------------------------------------*/
+ul.fancytree-ext-wide {
+ position: relative;
+ min-width: 100%;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+ul.fancytree-ext-wide span.fancytree-node > span {
+ position: relative;
+ z-index: 2;
+}
+ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ min-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+/*------------------------------------------------------------------------------
+ * 'fixed' extension
+ *----------------------------------------------------------------------------*/
+.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden {
+ display: none;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom {
+ border-bottom: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right {
+ border-right: 3px solid rgba(0, 0, 0, 0.75);
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 3;
+ top: 0px;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ top: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl {
+ position: absolute;
+ overflow: hidden;
+ z-index: 2;
+ left: 0px;
+}
+.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br {
+ position: absolute;
+ overflow: scroll;
+ z-index: 1;
+}
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+/*******************************************************************************
+ * Tree container
+ */
+ul.fancytree-container li {
+ background-image: url("../skin-xp/vline.gif");
+ background-position: 0 0;
+}
+ul.fancytree-container.fancytree-rtl li {
+ background-position: right 0;
+ background-image: url("../skin-xp/vline-rtl.gif");
+}
+ul.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander {
+ background-image: url("../skin-xp/icons-rtl.gif");
+ background-position: 0px -64px;
+}
+ul.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-xp/icons-rtl.gif");
+ background-position: -16px -64px;
+}
+ul.fancytree-container li.fancytree-lastsib {
+ background-image: none;
+}
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ background-image: url("../skin-xp/icons.gif");
+}
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-n span.fancytree-expander:hover {
+ background-position: 0px -64px;
+}
+.fancytree-exp-nl span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander:hover {
+ background-position: -16px -64px;
+}
+/*******************************************************************************
+ * Node titles
+ */
+span.fancytree-title {
+ border: 0 solid transparent;
+}
+span.fancytree-title:hover {
+ background-color: #F2F7FD;
+ border-color: #B8D6FB;
+}
+span.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+ background-color: #EFEBDE;
+}
+.fancytree-folder span.fancytree-title {
+ font-weight: bold;
+}
+.fancytree-selected span.fancytree-title {
+ color: green;
+ font-style: italic;
+}
+.fancytree-active span.fancytree-title {
+ background-color: #3169C6 !important;
+ color: white !important;
+}
+/*******************************************************************************
+ * 'table' extension
+ */
+table.fancytree-ext-table {
+ border-collapse: collapse;
+}
+table.fancytree-ext-table tbody tr.fancytree-focused {
+ background-color: #99DEFD;
+}
+table.fancytree-ext-table tbody tr.fancytree-active {
+ background-color: royalblue;
+}
+table.fancytree-ext-table tbody tr.fancytree-selected {
+ background-color: #99FDDE;
+}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.less b/plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.less
new file mode 100644
index 0000000..9e5bb30
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.less
@@ -0,0 +1,133 @@
+/*!
+ * Fancytree "XP" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */
+
+// Import common styles
+@import "skin-common.less";
+
+
+/*******************************************************************************
+ * Styles specific to this skin.
+ *
+ * This section is automatically generated from the `ui-fancytree.less` template.
+ ******************************************************************************/
+
+// Override the variable after the import.
+// NOTE: Variables are always resolved as the last definition, even if it is
+// after where it is used.
+@fancy-use-sprites: true; // false: suppress all background images (i.e. icons)
+
+@fancy-icon-width: 16px;
+@fancy-icon-height: 16px;
+@fancy-icon-spacing: 3px;
+@fancy-node-border-width: 0;
+@fancy-node-v-spacing: 0px; // gap between two node borders
+
+// We need to define this variable here (not in skin-common.less) to make it
+// work with grunt and webpack:
+@fancy-image-prefix: "./skin-xp/";
+
+// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+// @fancy-loading-url: data-uri("@{fancy-image-prefix}loading.gif");
+// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS
+// instead of linking to that file:
+// @fancy-inline-sprites: true;
+
+//default 10pt, which is used in a relative manner resulting in 13.3 in dokuwiki-template.
+@fancy-font-size: 93%;
+
+/*******************************************************************************
+ * Tree container
+ */
+ul.fancytree-container {
+ li {
+ // background-image: url("vline.gif");
+ // Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':
+ /* CHANGE: replace data-uri() with url() */
+ background-image: url("@{fancy-image-prefix}vline.gif");
+ background-position: 0 1px;
+ }
+ &.fancytree-rtl {
+ li {
+ background-position: right 1px;
+ background-image: url("@{fancy-image-prefix}vline-rtl.gif");
+ }
+ .fancytree-exp-n span.fancytree-expander {
+ background-image: url("@{fancy-image-prefix}icons-rtl.gif");
+ .useSprite(0, 4);
+ }
+ .fancytree-exp-nl span.fancytree-expander {
+ background-image: url("@{fancy-image-prefix}icons-rtl.gif");
+ .useSprite(1, 4);
+ }
+ }
+ // Suppress lines for last child node
+ li.fancytree-lastsib {
+ background-image: none;
+ }
+}
+// Suppress lines if level is fixed expanded (option minExpandLevel)
+ul.fancytree-no-connector > li {
+ background-image: none;
+}
+
+// XP theme always displays connectors (not only when .fancytree-connectors is set)
+.fancytree-exp-n span.fancytree-expander,
+.fancytree-exp-nl span.fancytree-expander {
+ .setBgImageUrl("icons.gif");
+ // margin-top: 0;
+}
+.fancytree-exp-n span.fancytree-expander, // End-node, not last sibling
+.fancytree-exp-n span.fancytree-expander:hover {
+ .useSprite(0, 4);
+}
+.fancytree-exp-nl span.fancytree-expander, // End-node, last sibling
+.fancytree-exp-nl span.fancytree-expander:hover {
+ .useSprite(1, 4);
+}
+
+/*******************************************************************************
+ * Node titles
+ */
+
+span.fancytree-title {
+ border: @fancy-node-border-width solid transparent; // avoid jumping, when a border is added on hover
+}
+span.fancytree-title:hover {
+ background-color: #F2F7FD; // light blue
+ border-color: #B8D6FB; // darker light blue
+}
+span.fancytree-focused span.fancytree-title {
+ outline: 1px dotted black;
+ background-color: #EFEBDE; // gray
+}
+.fancytree-folder span.fancytree-title {
+ font-weight: bold;
+}
+.fancytree-selected span.fancytree-title {
+ color: green;
+ font-style: italic;
+}
+.fancytree-active span.fancytree-title {
+ background-color: #3169C6 !important;
+ color: white !important; // @ IE6
+}
+
+///*******************************************************************************
+// * 'table' extension
+// */
+//table.fancytree-ext-table {
+// border-collapse: collapse;
+// tbody tr.fancytree-focused {
+// background-color: #99DEFD;
+// }
+// tbody tr.fancytree-active {
+// background-color: royalblue;
+// }
+// tbody tr.fancytree-selected {
+// background-color: #99FDDE;
+// }
+//}
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.min.css b/plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.min.css
new file mode 100644
index 0000000..7d70f5e
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/ui.fancytree.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Fancytree "XP" skin.
+ *
+ * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
+ * the LESS templates.
+ */.fancytree-helper-hidden{display:none}.fancytree-helper-indeterminate-cb{color:#777}.fancytree-helper-disabled{color:silver}.fancytree-helper-spin{-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container ul>li:before{content:none}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}ul.fancytree-connectors.fancytree-container li{background-image:url("../skin-xp/vline.gif");background-position:0 0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}li.fancytree-animating{position:relative}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url("../skin-xp/icons.gif");background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon{margin-top:0}span.fancytree-custom-icon{width:16px;height:16px;display:inline-block;margin-left:3px;background-position:0 0}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:0;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-xp/icons.gif");margin-top:0}.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}.fancytree-fade-expander span.fancytree-expander{transition:opacity 1.5s;opacity:0}.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander [class*=fancytree-statusnode-] span.fancytree-expander,.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,.fancytree-fade-expander:hover span.fancytree-expander{transition:opacity .6s;opacity:1}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}span.fancytree-checkbox.fancytree-radio{background-position:0 -48px}span.fancytree-checkbox.fancytree-radio:hover{background-position:-16px -48px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio{background-position:-64px -48px}.fancytree-partsel span.fancytree-checkbox.fancytree-radio:hover{background-position:-80px -48px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-selected span.fancytree-checkbox.fancytree-radio{background-position:-32px -48px}.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-48px -48px}.fancytree-unselectable span.fancytree-checkbox{opacity:.4}.fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -32px}.fancytree-unselectable span.fancytree-checkbox.fancytree-radio:hover{background-position:0 -48px}.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover{background-position:-64px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover{background-position:-32px -32px}.fancytree-unselectable.fancytree-selected span.fancytree-checkbox.fancytree-radio:hover{background-position:-32px -48px}.fancytree-container.fancytree-checkbox-auto-hide span.fancytree-checkbox{visibility:hidden}.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node.fancytree-selected span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide .fancytree-node:hover span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr.fancytree-selected td span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide tr:hover td span.fancytree-checkbox{visibility:unset}.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus .fancytree-node.fancytree-active span.fancytree-checkbox,.fancytree-container.fancytree-checkbox-auto-hide.fancytree-treefocus tr.fancytree-active td span.fancytree-checkbox{visibility:unset}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-loading span.fancytree-icon,.fancytree-statusnode-loading span.fancytree-icon:hover,span.fancytree-icon.fancytree-icon-loading{background-image:url("../skin-xp/loading.gif");background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:16px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:16px;padding:0 3px 0 3px;margin:0 0 0 3px;border:0 solid transparent;-webkit-border-radius:0px;-moz-border-radius:0;-ms-border-radius:0px;-o-border-radius:0;border-radius:0}span.fancytree-node.fancytree-error span.fancytree-title{color:red}span.fancytree-childcounter{color:#fff;background:#337ab7;border:1px solid gray;border-radius:10px;padding:2px;text-align:center}div.fancytree-drag-helper span.fancytree-childcounter,div.fancytree-drag-helper span.fancytree-dnd-modifier{display:inline-block;color:#fff;background:#337ab7;border:1px solid gray;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}div.fancytree-drag-helper span.fancytree-childcounter{position:absolute;top:-6px;right:-6px}div.fancytree-drag-helper span.fancytree-dnd-modifier{background:#5cb85c;border:none;font-weight:bolder}div.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source.fancytree-drag-remove{opacity:.15}.fancytree-container.fancytree-rtl span.fancytree-connector,.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,.fancytree-container.fancytree-rtl span.fancytree-expander,.fancytree-container.fancytree-rtl span.fancytree-icon{background-image:url("../skin-xp/icons-rtl.gif")}.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:none}.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-xp/icons-rtl.gif")}ul.fancytree-container.fancytree-rtl ul{padding:0 16px 0 0}ul.fancytree-container.fancytree-rtl.fancytree-connectors li{background-position:right 0;background-image:url("../skin-xp/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,ul.fancytree-container.fancytree-rtl.fancytree-no-connector>li{background-image:none}#fancytree-drop-marker.fancytree-rtl{background-image:url("../skin-xp/icons-rtl.gif")}table.fancytree-ext-table{font-family:tahoma,arial,helvetica;font-size:10pt;border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block;box-sizing:border-box}table.fancytree-ext-table td.fancytree-status-merged{text-align:center;font-style:italic;color:silver}table.fancytree-ext-table tr.fancytree-statusnode-error td.fancytree-status-merged{color:red}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr.fancytree-active>td{background-color:#eee}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode>tbody>tr>td.fancytree-active-cell{background-color:#cbe8f6}table.fancytree-ext-table.fancytree-ext-ariagrid.fancytree-cell-mode.fancytree-cell-nav-mode>tbody>tr>td.fancytree-active-cell{background-color:#3875d7}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#e0e0e0}table.fancytree-ext-columnview span.fancytree-node.fancytree-active{background-color:#cbe8f6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander{visibility:hidden}.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander,.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander{visibility:visible}.fancytree-ext-childcounter span.fancytree-custom-icon,.fancytree-ext-childcounter span.fancytree-icon,.fancytree-ext-filter span.fancytree-custom-icon,.fancytree-ext-filter span.fancytree-icon{position:relative}.fancytree-ext-childcounter span.fancytree-childcounter,.fancytree-ext-filter span.fancytree-childcounter{color:#fff;background:#777;border:1px solid gray;position:absolute;top:-6px;right:-6px;min-width:10px;height:10px;line-height:1;vertical-align:baseline;border-radius:10px;padding:2px;text-align:center;font-size:9px}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;min-width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fancytree-ext-fixed-wrapper .fancytree-ext-fixed-hidden{display:none}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-bottom{border-bottom:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-scroll-border-right{border-right:3px solid rgba(0,0,0,.75)}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tl{position:absolute;overflow:hidden;z-index:3;top:0;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-tr{position:absolute;overflow:hidden;z-index:2;top:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-bl{position:absolute;overflow:hidden;z-index:2;left:0}.fancytree-ext-fixed-wrapper div.fancytree-ext-fixed-wrapper-br{position:absolute;overflow:scroll;z-index:1}ul.fancytree-container li{background-image:url("../skin-xp/vline.gif");background-position:0 0}ul.fancytree-container.fancytree-rtl li{background-position:right 0;background-image:url("../skin-xp/vline-rtl.gif")}ul.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander{background-image:url("../skin-xp/icons-rtl.gif");background-position:0 -64px}ul.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-xp/icons-rtl.gif");background-position:-16px -64px}ul.fancytree-container li.fancytree-lastsib{background-image:none}ul.fancytree-no-connector>li{background-image:none}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:url("../skin-xp/icons.gif")}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}span.fancytree-title{border:0 solid transparent}span.fancytree-title:hover{background-color:#f2f7fd;border-color:#b8d6fb}span.fancytree-focused span.fancytree-title{outline:1px dotted black;background-color:#efebde}.fancytree-folder span.fancytree-title{font-weight:700}.fancytree-selected span.fancytree-title{color:green;font-style:italic}.fancytree-active span.fancytree-title{background-color:#3169c6!important;color:#fff!important}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table tbody tr.fancytree-focused{background-color:#99defd}table.fancytree-ext-table tbody tr.fancytree-active{background-color:#4169e1}table.fancytree-ext-table tbody tr.fancytree-selected{background-color:#99fdde} \ No newline at end of file
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/vline-rtl.gif b/plugins/55/indexmenu/scripts/fancytree/skin-xp/vline-rtl.gif
new file mode 100644
index 0000000..0400cb3
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/vline-rtl.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/fancytree/skin-xp/vline.gif b/plugins/55/indexmenu/scripts/fancytree/skin-xp/vline.gif
new file mode 100644
index 0000000..1b00ae5
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/fancytree/skin-xp/vline.gif
Binary files differ
diff --git a/plugins/55/indexmenu/scripts/indexmenu.js b/plugins/55/indexmenu/scripts/indexmenu.js
new file mode 100644
index 0000000..d9b8d61
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/indexmenu.js
@@ -0,0 +1,1008 @@
+/*--------------------------------------------------------|
+ | dTree 2.05 | www.destroydrop.com/javascript/tree/ |
+ |--------------------------------------------------------|
+ | Copyright (c) 2002-2003 Geir Landro |
+ | |
+ | This script can be used freely as long as all |
+ | copyright messages are intact. |
+ | |
+ | Updated: 17.04.2003 |
+ |--------------------------------------------------------|
+ | Modified for Dokuwiki by |
+ | Samuele Tognini <samuele@samuele.netsons.org> |
+ | under GPL 2 license |
+ | (http://www.gnu.org/licenses/gpl.html) |
+ | Updated: 29.08.2009 |
+ |--------------------------------------------------------|
+ | Modified for Dokuwiki by |
+ | Rene Hadler <rene.hadler@iteas.at> |
+ | under GPL 2 license |
+ | (http://www.gnu.org/licenses/gpl.html) |
+ | Updated: 07.08.2012 |
+ |--------------------------------------------------------|
+ | jQuery update - 27 02 2012 |
+ | Gerrit Uitslag <klapinklapin@gmail.com |
+ |--------------------------------------------------------|
+ | indexmenu | https://www.dokuwiki.org/plugin:indexmenu |
+ |-------------------------------------------------------*/
+/* global DOKU_COOKIE_PARAM */
+/* global DOKU_BASE */
+
+/*
+ * ids used in the dTree:
+ * - div#cdtree_<id indexmenu> div top level
+ * - div#dtree_<id indexmenu> div contains all nodes
+ * - div#toc_<id indexmenu> ??
+ * - div.dtreeNode
+ * - img#i<id indexmenu><nodenr?> icon
+ * - a#s<id indexmenu><nodenr?> url to page/namespace with title
+ * - div#t<id indexmenu><nodenr?> button for opening ToC, included if hovered
+ * - div.d<id indexmenu><nodenr?>
+ * repeats: - div.dtreeNode (with img#i, a#s and div#t)
+ * repeats: - div.d<id indexmenu><nodenr?>
+ * - z<id indexmenu> scroll rightward arrows
+ * - left_<id indexmenu> scroll leftward arrows
+ *
+ * at the end of body:
+ * - picker_<id indexmenu> popup with ToC
+ * - r<id indexmenu> rightmouse button menu
+ */
+
+/**
+ * dTreeNode object
+ *
+ * @param {string} dokuid page id of node
+ * @param {number} id node id
+ * @param {number} pid parent node id
+ * @param {string} name Page Title
+ * @param {number|string} hns page id of headpage of namespace
+ * @param {number} isdir is directory?
+ * @param {number} ajax load subnodes by ajax
+ * @constructor
+ */
+function dTreeNode(dokuid, id, pid, name, hns, isdir, ajax) {
+ /** @type {string} */
+ this.dokuid = dokuid; // page id of node
+ /** @type {number} */
+ this.id = id; // id number of node
+ /** @type {number} */
+ this.pid = pid; // id number of parent node
+ /** @type {string} */
+ this.name = name; // ns/page title
+ /** @type {number|string} */
+ this.hns = hns; // headpage of namespace or zero
+ /** @type {boolean} */
+ this.isdir = Boolean(isdir); // is directory
+ /** @type {boolean} */
+ this.ajax = Boolean(ajax); // load its nodes by ajax
+ /** @type {boolean} */
+ this._io = false; // is node open
+ /** @type {boolean} */
+ this._is = false; // is selected
+ /** @type {boolean} */
+ this._ls = false; // is last sibling
+ /** @type {boolean} */
+ this._hc = Boolean(ajax); // has children
+ /** @type {number} */
+ this._ai = 0; // id number of first child....
+ /** @type {dTreeNode} */
+ this._p = undefined; // parent dTreeNode
+ /** @type {number} */
+ this._lvl = 0; // level
+ /** @type {boolean} */
+ this._ok = false; // all children are loaded
+ /** @type {boolean} */
+ this._cp = false; // current page
+ /** @type {string} */
+ this.icon = ''; // icon of closed node
+ /** @type {string} */
+ this.iconOpen = ''; // icon of opened node
+}
+
+/**
+ * Tree object
+ *
+ * @param {string} treeName id of the indexmenu, has form 'indexmenu_<identifier>'
+ * @param {string} theme name of theme dir
+ * @constructor
+ */
+function dTree(treeName, theme) {
+ let imgExt = IndexmenuUtils.determineExtension(theme);
+ this.config = {
+ urlbase: DOKU_BASE + 'doku.php?id=', // base of dokuwiki (set in page)
+ plugbase: DOKU_BASE + 'lib/plugins/indexmenu', // base of plugin folder
+ useCookies: true, // use cookies (set in page) e.g. disabled for context option
+ scroll: true, // enable scrolling of tree in too small columns (set in page)
+ toc: true, // enable ToC popups in tree (set in page)
+ maxjs: 1, // number set by maxjs option (set in page)
+ jsajax: '', // &max=#&sort=(t|d)&msort=(indexmenu_n|<metakey>)&rsort=1&nsort=1&hsort=1&nopg=1&skipns=+=/.../&skipfile=+=/.../(set in page)
+ sepchar: ':', // value ':', ';' or '/' (set in page)
+ theme: theme // dir name of theme folder
+ };
+ let imagePath = this.config.plugbase + '/images/' + theme + '/';
+ this.icon = {
+ root: imagePath + 'base.' + imgExt,
+ folder: imagePath + 'folder.' + imgExt,
+ folderH: imagePath + 'folderh.' + imgExt,
+ folderOpen: imagePath + 'folderopen.' + imgExt,
+ folderHOpen: imagePath + 'folderhopen.' + imgExt,
+ node: imagePath + 'page.' + imgExt,
+ empty: imagePath + 'empty.' + imgExt,
+ line: imagePath + 'line.' + imgExt,
+ join: imagePath + 'join.' + imgExt,
+ joinBottom: imagePath + 'joinbottom.' + imgExt,
+ plus: imagePath + 'plus.' + imgExt,
+ plusBottom: imagePath + 'plusbottom.' + imgExt,
+ minus: imagePath + 'minus.' + imgExt,
+ minusBottom: imagePath + 'minusbottom.' + imgExt,
+ nlPlus: imagePath + 'nolines_plus.' + imgExt,
+ nlMinus: imagePath + 'nolines_minus.' + imgExt
+ };
+ /** @type {string} */
+ this.treeName = treeName; // (unique) name of this indexmenu
+ /** @type {dTreeNode[]} */
+ this.aNodes = []; // array of nodes
+ /** @type {number[]} */
+ this.aIndent = []; // array stores the indents of the tree (contains values 0 or 1)
+ /** @type {dTreeNode} */
+ this.root = new dTreeNode(false, -1);
+ /** @type {number} */
+ this.selectedNode = undefined; // node id
+ /** @type {boolean} */
+ this.selectedFound = false; // set to true when found
+ /** @type {boolean} */
+ this.completed = false; // succesfull written js tree to the page
+ /** @type {number} */
+ this.scrllTmr = 0; // store timer id for horizontal scrolling the page
+ /** @type {string} */
+ this.pageid = JSINFO.id || ''; // current page
+
+ this.fajax = false; // if retrieve next level of opened nodes
+}
+/**
+ * CSS classes:
+ *
+ * a.nodeFdUrl Namespace with url link (headpage)
+ * a.node Namespace without url link
+ * a.nodeUrl Page
+ * a.nodeSel Last visited page
+ * a.navSel Current page
+ */
+
+
+/**
+ * Adds a new node to the node array
+ *
+ * @param {string} dokuid page id of node
+ * @param {number} id node id
+ * @param {number} pid parent node id
+ * @param {string} name Page Title
+ * @param {number|string} hns page id of headpage of namespace
+ * @param {number} isdir is directory?
+ * @param {number} ajax load subnodes by ajax
+ */
+dTree.prototype.add = function (dokuid, id, pid, name, hns, isdir, ajax) {
+ this.aNodes[this.aNodes.length] = new dTreeNode(dokuid, id, pid, name, hns, isdir, ajax);
+};
+
+/**
+ * Open all nodes, if no node status was stored in cookie
+ */
+dTree.prototype.openAll = function () {
+ if (!this.getCookie('co' + this.treeName)) {
+ this.oAll(true);
+ }
+};
+
+/**
+ * Outputs the tree to the page. Called by document.write after adding the nodes to the tree.
+ *
+ * @returns {string} html of whole tree
+ */
+dTree.prototype.toString = function () {
+ let str = '';
+ this.pageid = this.pageid.replace(/:/g,this.config.sepchar);
+ if (this.config.scroll) {
+ str += '<div id="cdtree_' + this.treeName + '" class="dtree" style="position:relative;overflow:hidden;width:100%;">';
+ }
+ str += '<div id="dtree_' + this.treeName + '" class="dtree ' + this.config.theme + '" style="overflow:';
+ if (this.config.scroll) {
+ str += 'visible;position:relative;width:100%"';
+ } else {
+ str += 'hidden;"';
+ }
+ str += '>';
+ if (jQuery('#dtree_' + this.treeName)[0]) {
+ str += '<div class="error">Indexmenu id conflict</div>';
+ }
+ if (this.config.toc) {
+ str += '<div id="t' + this.treeName + '" class="indexmenu_tocbullet ' + this.config.theme + '" style="display:none;" title="Table of contents"></div>';
+ str += '<div id="toc_' + this.treeName + '" style="display:none;"></div>';
+ }
+ if (this.config.useCookies) {
+ this.selectedNode = this.getSelected();
+ }
+ str += this.addNode(this.root) + '</div>';
+ if (this.config.scroll) {
+ str += '<div id="z' + this.treeName + '" class="indexmenu_rarrow"></div>';
+ str += '<div id="left_' + this.treeName + '" class="indexmenu_larrow" style="display:none;" title="Click to scroll back" onmousedown="' + this.treeName + '.scroll(\'r\',1)" onmouseup="' + this.treeName + '.stopscroll()"></div>';
+ str += '</div>';
+ }
+ this.completed = true;
+ //hide the fallback nojs indexmenu
+ jQuery('#nojs_' + this.treeName).css("display", "none"); //using .hide(); let's crash opera
+ return str;
+};
+
+/**
+ * Creates the tree structure
+ *
+ * @param {dTreeNode} pNode
+ * @returns {string} html of node (inclusive children)
+ */
+dTree.prototype.addNode = function (pNode) {
+ let str = '', cn, n = pNode._ai, l = pNode._lvl + 1;
+ for (n; n < this.aNodes.length; n++) {
+ if (this.aNodes[n].pid === pNode.id) {
+ cn = this.aNodes[n];
+ cn._p = pNode;
+ cn._ai = n;
+ cn._lvl = l;
+ this.setCS(cn);
+ if (cn._hc && !cn._io && this.config.useCookies) {
+ cn._io = this.isOpen(cn.id);
+ }
+ if (this.pageid === (!cn.hns && cn.dokuid || cn.hns)) {
+ cn._cp = true;
+ } else if (cn.id === this.selectedNode && !this.selectedFound) {
+ cn._is = true;
+ this.selectedNode = n;
+ this.selectedFound = true;
+ }
+ if (!cn._hc && cn.isdir && !cn.ajax && !cn.hns) {
+ if (cn._ls) {
+ str += this.noderr(cn, n);
+ }
+ } else {
+ str += this.node(cn, n);
+ }
+ if (cn._ls) {
+ break;
+ }
+ }
+ }
+ return str;
+};
+
+/**
+ * Create empty node
+ *
+ * @param {dTreeNode} node
+ * @param {int} nodeId
+ * @returns {string} html of empty node
+ */
+dTree.prototype.noderr = function (node, nodeId) {
+ let str = '<div class="dTreeNode">' + this.indent(node, nodeId);
+ str += '<div class="emptynode" title="Empty"></div></div>';
+ return str;
+};
+
+/**
+ * Creates the node icon, url and text
+ *
+ * @param {dTreeNode} node
+ * @param {int} nodeId
+ * @returns {string} html of node (inclusive children)
+ */
+dTree.prototype.node = function (node, nodeId) {
+ let h = 1, jsfnc, str;
+ jsfnc = 'onmouseover="' + this.treeName + '.show_feat(\'' + nodeId + '\');" onmousedown="return IndexmenuContextmenu.checkcontextm(\'' + nodeId + '\',' + this.treeName + ',event);" oncontextmenu="return IndexmenuContextmenu.stopevt(event)"';
+ if (node._lvl > this.config.maxjs) {
+ h = 0;
+ } else {
+ node._ok = true;
+ }
+ str = '<div class="dTreeNode">' + this.indent(node, nodeId);
+ node.icon = (this.root.id === node.pid) ? this.icon.root : ((node.hns) ? this.icon.folderH : ((node._hc) ? this.icon.folder : this.icon.node));
+ node.iconOpen = (node._hc) ? ((node.hns) ? this.icon.folderHOpen : this.icon.folderOpen) : this.icon.node;
+ if (this.root.id === node.pid) {
+ node.icon = this.icon.root;
+ node.iconOpen = this.icon.root;
+ }
+ str += '<img id="i' + this.treeName + nodeId + '" src="' + ((node._io) ? node.iconOpen : node.icon) + '" alt="" />';
+ if (!node._hc || node.hns) {
+ str += '<a id="s' + this.treeName + nodeId + '" class="' + ((node._cp) ? 'navSel' : ((node._is) ? 'nodeSel' : (node._hc) ? 'nodeFdUrl' : 'nodeUrl'));
+ str += '" href="' + this.config.urlbase;
+ (node.hns) ? str += node.hns : str += node.dokuid;
+ str += '"' + ' title="' + node.name + '"' + jsfnc;
+ str += ' onclick="javascript: ' + this.treeName + '.s(' + nodeId + ');"';
+ str += '>' + node.name + '</a>';
+ }
+ else if (node.pid !== this.root.id) {
+ str += '<a id="s' + this.treeName + nodeId + '" href="javascript: ' + this.treeName + '.o(' + nodeId + '); " class="node"' + jsfnc + '>' + node.name + '</a>';
+ } else {
+ str += node.name;
+ }
+ str += '</div>';
+ if (node._hc) {
+ str += '<div id="d' + this.treeName + nodeId + '" class="clip" style="display:' + ((this.root.id === node.pid || node._io) ? 'block' : 'none') + ';">';
+ if (h) {
+ str += this.addNode(node);
+ }
+ str += '</div>';
+ }
+ this.aIndent.pop();
+ return str;
+};
+
+/**
+ * Adds the empty and line icons which indent the node
+ *
+ * @param {dTreeNode} node
+ * @param {int} nodeId
+ * @returns {string} html of indent icons
+ */
+dTree.prototype.indent = function (node, nodeId) {
+ let n, str = '';
+ if (this.root.id !== node.pid) {
+ for (n = 0; n < this.aIndent.length; n++) {
+ str += '<img src="' + ( (this.aIndent[n] === 1) ? this.icon.line : this.icon.empty ) + '" alt="" />';
+ }
+ if (node._ls) {
+ this.aIndent.push(0);
+ } else {
+ this.aIndent.push(1);
+ }
+ if (node._hc) {
+ str += '<a href="javascript: ' + this.treeName + '.o(' + nodeId + ');">' +
+ '<img id="j' + this.treeName + nodeId + '" src="' +
+ ( (node._io) ? ((node._ls) ? this.icon.minusBottom : this.icon.minus) : ((node._ls) ? this.icon.plusBottom : this.icon.plus ) ) +
+ '" alt="" /></a>';
+ } else {
+ str += '<img src="' + ((node._ls) ? this.icon.joinBottom : this.icon.join) + '" alt="" />';
+ }
+ }
+ return str;
+};
+
+/**
+ * Checks if a node has any children and if it is the last sibling
+ *
+ * @param {dTreeNode} node
+ */
+dTree.prototype.setCS = function (node) {
+ let lastId, n;
+ for (n = 0; n < this.aNodes.length; n++) {
+ if (this.aNodes[n].pid === node.id) {
+ node._hc = true;
+ }
+ if (this.aNodes[n].pid === node.pid) {
+ lastId = this.aNodes[n].id;
+ }
+ }
+ if (lastId === node.id) {
+ node._ls = true;
+ }
+};
+
+/**
+ * Returns the selected node as stored in cookie
+ *
+ * @returns {int} node id
+ */
+dTree.prototype.getSelected = function () {
+ let sn = this.getCookie('cs' + this.treeName);
+ return (sn) ? parseInt(sn, 10) : null;
+};
+
+/**
+ * Highlights the selected node
+ *
+ * @param {int} id node id
+ */
+dTree.prototype.s = function (id) {
+ let eOld, eNew, cn = this.aNodes[id];
+ if (this.selectedNode !== id) {
+ eNew = jQuery("#s" + this.treeName + id)[0];
+ if (!eNew) {
+ return;
+ }
+ if (this.selectedNode || this.selectedNode === 0) {
+ eOld = jQuery("#s" + this.treeName + this.selectedNode)[0];
+ eOld.className = "node";
+ }
+ eNew.className = "nodeSel";
+ this.selectedNode = id;
+ if (this.config.useCookies) {
+ this.setCookie('cs' + this.treeName, cn.id);
+ }
+ }
+};
+
+/**
+ * Toggle Open or close
+ *
+ * @param {int} id node id
+ */
+dTree.prototype.o = function (id) {
+ let cn = this.aNodes[id];
+ this.nodeStatus(!cn._io, id, cn._ls);
+ cn._io = !cn._io;
+ if (this.config.useCookies) {
+ this.updateCookie();
+ }
+ // scroll
+ this.divdisplay('z', false);
+ this.resizescroll("block");
+};
+
+/**
+ * Open or close all nodes
+ *
+ * @param {boolean} status if true open
+ */
+dTree.prototype.oAll = function (status) {
+ for (let n = 0; n < this.aNodes.length; n++) {
+ if (this.aNodes[n]._hc && this.aNodes[n].pid !== this.root.id) {
+ this.nodeStatus(status, n, this.aNodes[n]._ls);
+ this.aNodes[n]._io = status;
+ }
+ }
+ if (this.config.useCookies) {
+ this.updateCookie();
+ }
+};
+
+/**
+ * Opens the tree to a specific node
+ *
+ * @param {number} nId node id
+ * @param {boolean} bSelect
+ * @param {boolean} bFirst
+ */
+dTree.prototype.openTo = function (nId, bSelect, bFirst) {
+ let n, cn;
+ if (!bFirst) {
+ for (n = 0; n < this.aNodes.length; n++) {
+ if (this.aNodes[n].id === nId) {
+ nId = n;
+ break;
+ }
+ }
+ }
+ this.fill(this.aNodes[nId].pid);
+ cn = this.aNodes[nId];
+ if (cn.pid === this.root.id || !cn._p) {
+ return;
+ }
+ cn._io = 1;
+ if (this.completed && cn._hc) {
+ this.nodeStatus(true, cn._ai, cn._ls);
+ }
+ if (cn._is) {
+ (this.completed) ? this.s(cn._ai) : this._sn = cn._ai;
+ }
+ this.openTo(cn._p._ai, false, true);
+};
+
+/**
+ * Open the given nodes, if no node status is already stored
+ *
+ * @param {Array|string} nodes array of nodes to open or empty string to open all nodes
+ */
+dTree.prototype.getOpenTo = function (nodes) {
+ if (nodes === '') {
+ this.openAll();
+ } else if (!this.config.useCookies || !this.getCookie('co' + this.treeName)) {
+ for (let n = 0; n < nodes.length; n++) {
+ this.openTo(nodes[n], false, true);
+ }
+ }
+};
+
+/**
+ * Change the status of a node(open or closed)
+ *
+ * @param {boolean} status true if open
+ * @param {int} id node id
+ * @param {boolean} bottom true if bottom node
+ */
+dTree.prototype.nodeStatus = function (status, id, bottom) {
+ if (status && !this.fill(id)) {
+ return;
+ }
+ let eJoin, eIcon;
+ eJoin = jQuery('#j' + this.treeName + id)[0];
+ eIcon = jQuery('#i' + this.treeName + id)[0];
+ eIcon.src = (status) ? this.aNodes[id].iconOpen : this.aNodes[id].icon;
+ eJoin.src = ((status) ? ((bottom) ? this.icon.minusBottom : this.icon.minus) : ((bottom) ? this.icon.plusBottom : this.icon.plus));
+ jQuery('#d' + this.treeName + id)[0].style.display = (status) ? 'block' : 'none';
+};
+
+/**
+ * [Cookie] Clears a cookie
+ */
+dTree.prototype.clearCookie = function () {
+ let now, yday;
+ now = new Date();
+ yday = new Date(now.getTime() - 1000 * 60 * 60 * 24);
+ this.setCookie('co' + this.treeName, 'cookieValue', yday);
+ this.setCookie('cs' + this.treeName, 'cookieValue', yday);
+};
+
+/**
+ * [Cookie] Sets value in a cookie
+ *
+ * @param {string} cookieName
+ * @param {string} cookieValue
+ * @param {boolean|Date} expires
+ */
+dTree.prototype.setCookie = function (cookieName, cookieValue, expires = false) {
+ document.cookie =
+ encodeURIComponent(cookieName) + '=' + encodeURIComponent(cookieValue) +
+ (expires ? '; expires=' + expires.toUTCString() : '') +
+ '; path=' + DOKU_COOKIE_PARAM.path +
+ '; secure=' + DOKU_COOKIE_PARAM.secure;
+};
+
+/**
+ * [Cookie] Gets a value from a cookie
+ *
+ * @param cookieName
+ * @returns {string}
+ */
+dTree.prototype.getCookie = function (cookieName) {
+ let cookieValue = '', pN, posValue, endPos;
+ pN = document.cookie.indexOf(encodeURIComponent(cookieName) + '=');
+ if (pN !== -1) {
+ posValue = pN + (encodeURIComponent(cookieName) + '=').length;
+ endPos = document.cookie.indexOf(';', posValue);
+ if (endPos !== -1) {
+ cookieValue = decodeURIComponent(document.cookie.substring(posValue, endPos));
+ }
+ else {
+ cookieValue = decodeURIComponent(document.cookie.substring(posValue));
+ }
+ }
+ return (cookieValue);
+};
+
+/**
+ * [Cookie] Stores ids of open nodes as a string in cookie
+ */
+dTree.prototype.updateCookie = function () {
+ let str = '', n;
+ for (n = 0; n < this.aNodes.length; n++) {
+ if (this.aNodes[n]._io && this.aNodes[n].pid !== this.root.id) {
+ if (str) {
+ str += '.';
+ }
+ str += this.aNodes[n].id;
+ }
+ }
+ this.setCookie('co' + this.treeName, str);
+};
+
+/**
+ * [Cookie] Checks if a node id is in the cookie
+ *
+ * @param {int} id node id
+ * @return {Boolean} if open true
+ */
+dTree.prototype.isOpen = function (id) {
+ let n, aOpen = this.getCookie('co' + this.treeName).split('.');
+ for (n = 0; n < aOpen.length; n++) {
+ if (parseInt(aOpen[n],10) === id) {
+ return true;
+ }
+ }
+ return false;
+};
+
+/**
+ * Open the node of the current namespace
+ *
+ * @param {int} max
+ */
+dTree.prototype.openCurNS = function (max) {
+ let r, cn, match, t, i, n, cnsa, cna;
+ let cns = this.pageid;
+ r = new RegExp("\\b" + this.config.sepchar + "\\b", "g");
+ match = cns.match(r) || -1;
+ if (max > 0 && match.length >= max) {
+ t = cns.split(this.config.sepchar);
+ n = (this.aNodes[0].dokuid === '') ? 0 : this.aNodes[0].dokuid.split(this.config.sepchar).length;
+ t.splice(max + n, t.length);
+ cnsa = t.join(this.config.sepchar);
+ }
+ for (i = 0; i < this.aNodes.length; i++) {
+ cn = this.aNodes[i];
+ if (cns === cn.dokuid || cns === cn.hns) {
+ this.openTo(cn.id, false, true);
+ this.fajax = false;
+ if (cn.pid >= 0) {
+ jQuery(this.scroll("l", 4, cn.pid, 1));
+ }
+ break;
+ }
+ if (cnsa === cn.dokuid || cnsa === cn.hns) {
+ cna = cn;
+ this.fajax = true;
+ }
+ }
+ if (cna) {
+ this.openTo(cna.id, false, true);
+ }
+};
+
+/**
+ * Load children when not available
+ *
+ * @param {int} id node id
+ * @returns {boolean}
+ */
+dTree.prototype.fill = function (id) {
+ if (id === -1 || this.aNodes[id]._ok) {
+ return true;
+ }
+ let n = id, $eLoad, a, rd, ln, eDiv;
+ if (this.aNodes[n].ajax) {
+ //temporary load indicator
+ $eLoad = jQuery('#l' + this.treeName);
+ if (!$eLoad.length) {
+ $eLoad = IndexmenuUtils.createPicker('l' + this.treeName, 'picker');
+ }
+ jQuery('#s' + this.treeName + n).parent().append($eLoad);
+ $eLoad
+ .html('Loading ...')
+ .css({width: 'auto'})
+ .show();
+
+ //retrieves children
+ this.getAjax(n);
+ return true;
+ }
+ rd = [];
+ while (!this.aNodes[n]._ok) {
+ rd[rd.length] = n;
+ n = this.aNodes[n].pid;
+ }
+ for (ln = rd.length - 1; ln >= 0; ln--) {
+ id = rd[ln];
+ a = this.aNodes[id];
+ eDiv = jQuery('#d' + this.treeName + id)[0];
+ if (!eDiv) {
+ return false;
+ }
+ this.aIndent = [];
+ n = a;
+ while (n.pid >= 0) {
+ if (n._ls) {
+ this.aIndent.unshift(0);
+ } else {
+ this.aIndent.unshift(1);
+ }
+ n = n._p;
+ }
+ eDiv.innerHTML = this.addNode(a);
+ a._ok = true;
+ }
+ return true;
+};
+
+/**
+ * Open the nodes stored in cookie
+ */
+dTree.prototype.openCookies = function () {
+ let n, cn, aOpen = this.getCookie('co' + this.treeName).split('.');
+ for (n = 0; n < aOpen.length; n++) {
+ if (aOpen[n] === "") {
+ break;
+ }
+ cn = this.aNodes[aOpen[n]];
+ if (!cn._ok) {
+ this.nodeStatus(true, aOpen[n], cn._ls);
+ cn._io = true;
+ }
+ }
+};
+
+/**
+ * Scrolls the index
+ *
+ * @param {string} where to move to
+ * @param {int} s start
+ * @param {int} n parent node id
+ * @param {int} i
+ */
+dTree.prototype.scroll = function (where, s, n, i) {
+ if (!this.config.scroll) {
+ return false;
+ }
+ let w, dtree, dtreel, nodeId;
+ dtree = jQuery('#dtree_' + this.treeName)[0];
+ dtreel = parseInt(dtree.offsetLeft);
+ if (where === "r") {
+ jQuery('#left_' + this.treeName)[0].style.border = "thin inset";
+ this.scrollRight(dtreel, s);
+ } else {
+ nodeId = jQuery('#s' + this.treeName + n)[0];
+ if (nodeId == null) {
+ return false;
+ }
+ w = parseInt(dtree.parentNode.offsetWidth - nodeId.offsetWidth - nodeId.offsetLeft);
+ if (this.config.toc) {
+ w = w - 11;
+ }
+ if (dtreel <= w) {
+ return;
+ }
+ this.resizescroll("none");
+ this.stopscroll();
+ this.scrollLeft(dtreel, s, w - 3, i);
+ }
+};
+
+/**
+ * Scroll index to the left
+ *
+ * @param {int} lft current position
+ * @param {int} s start
+ * @param {int} w width
+ * @param {int} i
+ */
+dTree.prototype.scrollLeft = function (lft, s, w, i) {
+ if (lft < w - i - 10) {
+ this.divdisplay('z', false);
+ this.scrllTmr = 0;
+ return;
+ }
+ var self = this;
+ jQuery('#dtree_' + self.treeName)[0].style.left = lft + "px";
+ this.scrllTmr = setTimeout(function () {
+ self.scrollLeft(lft - s, s + i, w, i);
+ }, 20);
+};
+
+/**
+ * Scroll Index back to the right
+ *
+ * @param {int} lft current position
+ * @param {int} s start
+ */
+dTree.prototype.scrollRight = function (lft, s) {
+ if (lft >= s) {
+ this.divdisplay('left_', false);
+ this.stopscroll();
+ return;
+ }
+ var self = this;
+ jQuery('#dtree_' + self.treeName)[0].style.left = lft + "px";
+ if (lft > -15) {
+ s = 1;
+ }
+ this.scrllTmr = setTimeout(function () {
+ self.scrollRight(lft + s, s + 1);
+ }, 20);
+};
+
+/**
+ * Stop scroll movement
+ */
+dTree.prototype.stopscroll = function () {
+ jQuery('#left_' + this.treeName)[0].style.border = "none";
+ clearTimeout(this.scrllTmr);
+ this.scrllTmr = 0;
+};
+
+/**
+ * Show features and add event handlers for ToC and scroll
+ *
+ * @param {int} n node id
+ */
+dTree.prototype.show_feat = function (n) {
+ var w, div, id, dtree, dtreel, self, node = jQuery('#s' + this.treeName + n)[0];
+ self = this;
+ if (this.config.toc && node.className !== "node") {
+ div = jQuery('#t' + this.treeName)[0];
+ id = (this.aNodes[n].hns) ? this.aNodes[n].hns : this.aNodes[n].dokuid;
+ div.onmousedown = function () {
+ IndexmenuContextmenu.createTocMenu('call=indexmenu&req=toc&id=' + decodeURIComponent(id), 'picker_' + self.treeName, 't' + self.treeName);
+ };
+ node.parentNode.appendChild(div);
+ if (div.style.display === "none") {
+ div.style.display = "inline";
+ }
+ }
+ if (this.config.scroll) {
+ div = jQuery('#z' + this.treeName)[0];
+ div.onmouseover = function () {
+ div.style.border = "none";
+ self.scroll("l", 1, n, 0);
+ };
+ div.onmousedown = function () {
+ div.style.border = "thin inset";
+ self.scroll("l", 4, n, 1);
+ };
+ div.onmouseout = function () {
+ div.style.border = "none";
+ self.stopscroll();
+ };
+ div.onmouseup = div.onmouseover;
+ dtree = jQuery('#dtree_' + this.treeName)[0];
+ dtreel = parseInt(dtree.offsetLeft);
+ w = parseInt(dtree.parentNode.offsetWidth - node.offsetWidth - node.offsetLeft + 1);
+ if (dtreel > w) {
+ div.style.display = "none";
+ div.style.top = node.offsetTop + "px";
+ div.style.left = parseInt(node.offsetLeft + node.offsetWidth + w - 12) + "px";
+ div.style.display = "block";
+ }
+ }
+};
+
+/**
+ * Show and resize the scroll-back button relatively to size of tree
+ *
+ * @param {string} status 'block' or 'none'
+ */
+dTree.prototype.resizescroll = function (status) {
+ let dtree, w, h, left = jQuery('#left_' + this.treeName)[0];
+ if (!left) {
+ return;
+ }
+ if (left.style.display === status) {
+ dtree = jQuery('#dtree_' + this.treeName)[0];
+ w = Math.trunc(dtree.offsetHeight / 3);
+ h = Math.trunc(w / 50) * 50;
+ if (h < 50) {
+ h = 50;
+ }
+ left.style.height = h + "px";
+ left.style.top = w + "px";
+ if (status === "none") {
+ left.style.display = "block";
+ }
+ }
+};
+
+/**
+ * Toggle Open or close
+ *
+ * @param {int} n node id
+ */
+dTree.prototype.getAjax = function (n) {
+ var node, selft = this;
+ let req, curns;
+ node = selft.aNodes[n];
+
+ req = 'req=index&idx=' + node.dokuid + decodeURIComponent(this.config.jsajax);
+
+ curns = this.pageid.substring(0, this.pageid.lastIndexOf(this.config.sepchar));
+ if (this.fajax) {
+ req += '&nss=' + curns + '&max=1';
+ }
+
+ var onCompletion = function (data) {
+ var i, ajxnodes, ajxnode, plus;
+ plus = selft.aNodes.length - 1;
+ eval(data);
+ if (!ajxnodes instanceof Array || ajxnodes.length < 1) {
+ ajxnodes = [
+ ['', 1, 0, '', 0, 1, 0]
+ ];
+ }
+ node.ajax = false;
+ for (i = 0; i < ajxnodes.length; i++) {
+ ajxnode = ajxnodes[i];
+ ajxnode[2] = (ajxnode[2] == 0) ? node.id : ajxnode[2] + plus;
+ ajxnode[1] += plus;
+ selft.add(ajxnode[0], ajxnode[1], ajxnode[2], ajxnode[3], ajxnode[4], ajxnode[5], ajxnode[6]);
+ }
+ if (selft.fajax) {
+ selft.fajax = false;
+ selft.openCurNS(0);
+ } else {
+ selft.openTo(node.id, false, true);
+ }
+ jQuery('#l' + selft.treeName).hide();
+ };
+
+ jQuery.post(
+ DOKU_BASE + 'lib/exe/ajax.php',
+ 'call=indexmenu&'+req,
+ onCompletion,
+ 'html'
+ );
+};
+
+/**
+ * Load custom css for theme
+ */
+dTree.prototype.loadCss = function () {
+ let oLink = document.createElement("link");
+ oLink.href = this.config.plugbase + '/images/' + this.config.theme + '/style.css';
+ oLink.rel = "stylesheet";
+ oLink.type = "text/css";
+ document.getElementsByTagName('head')[0].appendChild(oLink);
+};
+
+/**
+ * Show the contextmenu
+ *
+ * @param {int} n node id
+ * @param {Event} e event
+ * @returns {boolean}
+ */
+dTree.prototype.contextmenu = function (n, e) {
+ let type, node, cdtree, $rmenu;
+ cdtree = jQuery("#cdtree_" + this.treeName)[0];
+ $rmenu = jQuery('#r' + this.treeName)[0];
+ if (!$rmenu) {
+ return true;
+ }
+ IndexmenuContextmenu.mouseposition($rmenu, e);
+ let cmenu = window.indexmenu_contextmenu;
+ node = this.aNodes[n];
+ $rmenu.innerHTML = '<div class="indexmenu_rmenuhead" title="' + node.name + '">' + node.name + "</div>";
+ $rmenu.appendChild(document.createElement('ul'));
+ type = (node.isdir || node._hc) ? 'ns' : 'pg';
+ IndexmenuContextmenu.arrconcat(cmenu['all'][type], this, n);
+ if (node.hns) {
+ IndexmenuContextmenu.arrconcat(cmenu[type], this, n);
+ type = 'pg';
+ IndexmenuContextmenu.arrconcat(cmenu['all'][type], this, n);
+ }
+ IndexmenuContextmenu.arrconcat(cmenu[type], this, n);
+ $rmenu.style.display = 'inline';
+ return false;
+};
+
+/**
+ * Show/hide object with given id of current indexmenu
+ *
+ * @param {string} objName name of object, which is combined with the unique id of the indexmenu
+ * @param {boolean} visible true: visible, false: hide.
+ */
+dTree.prototype.divdisplay = function (objName, visible) {
+ let o = jQuery('#' + objName + this.treeName)[0];
+ if (!o) {
+ return;
+ }
+ (visible) ? o.style.display = 'inline' : o.style.display = 'none';
+};
+
+/**
+ * Initialise the dTree index
+ *
+ * @param {int} hasstyle has an additional css style sheet
+ * @param {int} nocookies use no cookies
+ * @param {string} opennodes string of initial opened nodes
+ * @param {int} nav is navbar option set
+ * @param {int} max max level of available nodes (deeper levels are included with js)
+ * @param {int} nomenu show no menu
+ */
+dTree.prototype.init = function (hasstyle, nocookies, opennodes, nav, max, nomenu) {
+ if (hasstyle) {
+ this.loadCss();
+ }
+ if (!nocookies) {
+ this.openCookies();
+ }
+ //open given nodes
+ if (opennodes) {
+ this.getOpenTo(opennodes.split(" "));
+ }
+ if (nav) {
+ this.openCurNS(max);
+ }
+ //create contextmenu
+ if (!nomenu) {
+ var self = this;
+ IndexmenuUtils.createPicker('r' + this.treeName, 'indexmenu_rmenu ' + this.config.theme);
+ jQuery('#r' + this.treeName)[0].oncontextmenu = IndexmenuContextmenu.stopevt;
+ jQuery(document).on("click",function() {
+ self.divdisplay('r', false);
+ });
+ }
+};
diff --git a/plugins/55/indexmenu/scripts/nojsindex.js b/plugins/55/indexmenu/scripts/nojsindex.js
new file mode 100644
index 0000000..970f353
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/nojsindex.js
@@ -0,0 +1,27 @@
+/**
+ * Javascript for index view
+ *
+ * @author Gerrit Uitslag <klapinklapin@gmail.com>
+ */
+
+jQuery(function () {
+
+ jQuery('.indexmenu_nojs').each(function () {
+ let $tree = jQuery(this);
+ let jsajax = $tree.data('jsajax');
+
+ $tree.dw_tree({
+ toggle_selector: 'a.indexmenu_idx',
+ load_data: function (show_sublist, $clicky) {
+
+ jQuery.post(
+ DOKU_BASE + 'lib/exe/ajax.php',
+ 'call=indexmenu&req=index&nojs=1&' + $clicky[0].search.substring(1) + '&max=1' + decodeURIComponent(jsajax),
+ show_sublist,
+ 'html'
+ );
+ }
+ });
+ });
+
+});
diff --git a/plugins/55/indexmenu/scripts/toolbarindexwizard.js b/plugins/55/indexmenu/scripts/toolbarindexwizard.js
new file mode 100644
index 0000000..3a81b4b
--- /dev/null
+++ b/plugins/55/indexmenu/scripts/toolbarindexwizard.js
@@ -0,0 +1,349 @@
+/**
+ * The Indexmenu Wizard
+ *
+ * @author Gerrit Uitslag
+ * based on Linkwiz by
+ * @author Andreas Gohr <gohr@cosmocode.de>
+ * @author Pierre Spring <pierre.spring@caillou.ch>
+ * and the concepts of the old indexmenu wizard
+ */
+const indexmenu_wiz = {
+ $wiz: null,
+ timer: null,
+ textArea: null,
+
+ defaulttheme: 'default',
+ fields: {
+ div1: {
+ elems: {
+ jstoggle: {label: 'js'}
+ }
+ },
+ div2: {
+ tlbclass: 'jsitem theme',
+ elems: {
+ el1: {headerid: 'theme'}
+ }
+ },
+ div3: {
+ elems: {
+ el2: {headerid: 'navigation'},
+ navbar: {},
+ context: {},
+ nocookie: {tlbclass: 'jsitem'},
+ noscroll: {tlbclass: 'jsitem'},
+ notoc: {tlbclass: 'jsitem'}
+ }
+ },
+ div4: {
+ elems: {
+ el3: {headerid: 'sort'},
+ tsort: {},
+ dsort: {},
+ msort: {},
+ hsort: {},
+ rsort: {},
+ nsort: {}
+ }
+ },
+ div5: {
+ elems: {
+ el4: {headerid: 'filter'},
+ nons: {},
+ nopg: {}
+ }
+ },
+ div6: {
+ tlbclass: 'jsitem',
+ elems: {
+ el5: {headerid: 'performance'},
+ max: {tlbclass: 'jsitem', numberinput: ['maxn', 'maxm']},
+ maxjs: {tlbclass: 'jsitem', numberinput: ['maxjsn']},
+ id: {tlbclass: 'jsitem', numberinput: ['idn']}
+ }
+ }
+ },
+
+ /**
+ * Initialize the indexmenu_wiz by creating the needed HTML
+ * and attaching the eventhandlers
+ */
+ init: function ($editor) {
+ // position relative to the text area
+ const pos = $editor.position();
+
+ // create HTML Structure
+ indexmenu_wiz.$wiz = jQuery(document.createElement('div'))
+ .dialog({
+ autoOpen: false,
+ draggable: true,
+ title: LANG.plugins.indexmenu.indexmenuwizard,
+ resizable: false
+ })
+ .html(
+ '<fieldset class="indexmenu_index"><legend>' + LANG.plugins.indexmenu.index + '</legend>' +
+ '<div><label>' + LANG.plugins.indexmenu.namespace + '<input id="namespace" type="text"></label></div>' +
+ '<div><label class="number">' + LANG.plugins.indexmenu.nsdepth + ' #<input id="nsdepth" type="text" value=1></label></div>' +
+ '</fieldset>' +
+
+ '<fieldset class="indexmenu_options"><legend>' + LANG.plugins.indexmenu.options + '</legend>' +
+ '</fieldset>' +
+ '<input type="submit" value="' + LANG.plugins.indexmenu.insert + '" class="button" id="indexmenu__insert">' +
+
+ '<fieldset class="indexmenu_metanumber">' +
+ '<label class="number">' + LANG.plugins.indexmenu.metanum + '<input type="text" id="metanumber"></label>' +
+ '<input type="submit" value="' + LANG.plugins.indexmenu.insertmetanum + '" class="button" id="indexmenu__insertmetanum">' +
+ '</fieldset>'
+ )
+ .parent()
+ .attr('id', 'indexmenu__wiz')
+ .css({
+ 'position': 'absolute',
+ 'top': (pos.top + 20) + 'px',
+ 'left': (pos.left + 80) + 'px'
+ })
+ .hide()
+ .appendTo('.dokuwiki:first');
+
+ indexmenu_wiz.textArea = $editor[0];
+ let $opt_fieldset = jQuery('#indexmenu__wiz fieldset.indexmenu_options');
+
+ jQuery.each(indexmenu_wiz.fields, function (i, section) {
+ let div = jQuery('<div>').addClass(section.tlbclass);
+
+ jQuery.each(section.elems, function (elid, props) {
+ if (props.headerid) {
+ div.append('<strong>' + LANG.plugins.indexmenu[props.headerid] + '</strong><br />');
+ } else {
+ let label = props.label || elid;
+ //checkbox
+ jQuery("<label>")
+ .addClass(props.tlbclass).addClass(props.numberinput ? ' hasnumber' : '')
+ .html('<input id="' + elid + '" type="checkbox">' + label)
+ .attr({title: LANG.plugins.indexmenu[elid]})
+ .appendTo(div);
+
+ //number inputs
+ if (props.numberinput) {
+ jQuery.each(props.numberinput, function (j, numid) {
+ jQuery("<label>")
+ .attr({title: LANG.plugins.indexmenu[elid]})
+ .addClass("number " + props.tlbclass)
+ .html('#<input type="text" id="' + numid + '">')
+ .appendTo(div);
+ });
+ }
+ }
+ });
+ $opt_fieldset.append(div);
+ });
+
+ indexmenu_wiz.includeThemes();
+
+ if (JSINFO && JSINFO.namespace) {
+ jQuery('#namespace').val(':' + JSINFO.namespace);
+ }
+
+ // attach event handlers
+
+ //toggle js fields
+ jQuery('#jstoggle')
+ .on('change', function () {
+ jQuery('#indexmenu__wiz .jsitem').toggle(this.checked);
+ }).trigger('change')
+ .parent().css({display: 'inline-block', width: '40px'}); //enlarge clickable area of label
+
+ //interactive number fields
+ jQuery('label.number input').on('keydown keyup', function () {
+ //allow only numbers
+ indexmenu_wiz.filterNumberinput(this);
+ //checked the option if a number in input
+ indexmenu_wiz.autoCheckboxForNumbers(this);
+ });
+
+ jQuery('#indexmenu__insert').on('click', indexmenu_wiz.insertIndexmenu);
+ jQuery('#indexmenu__insertmetanum').on('click', indexmenu_wiz.insertMetaNumber);
+
+ jQuery('#indexmenu__wiz').find('.ui-dialog-titlebar-close').on('click', indexmenu_wiz.hide);
+ },
+
+ /**
+ * Request and include themes in wizard
+ */
+ includeThemes: function () {
+
+ let addButtons = function (data) {
+ jQuery('<div>')
+ .attr('id', 'themebar')
+ .addClass('toolbar')
+ .appendTo('div.theme');
+
+ jQuery.each(data.themes, function (i, theme) {
+ let themeName = theme.split('.');
+
+ let icoUrl = DOKU_BASE + data.themebase + '/' + theme + '/base.' + IndexmenuUtils.determineExtension(theme);
+ let $ico = jQuery('<div>')
+ .css({background: 'url(' + icoUrl + ') no-repeat center'});
+ jQuery('<button>')
+ .addClass('themebutton toolbutton')
+ .attr('id', theme)
+ .attr('title', themeName[0])
+ .append($ico)
+ .on('click', indexmenu_wiz.selectTheme)
+ .appendTo('div#themebar');
+ });
+
+ //select default theme
+ jQuery('#themebar button#' + indexmenu_wiz.defaulttheme).trigger('click');
+ };
+
+ jQuery.post(
+ DOKU_BASE + 'lib/exe/ajax.php',
+ {call: 'indexmenu', req: 'local'},
+ addButtons,
+ 'json'
+ );
+ },
+
+ /**
+ * set class 'selected' to clicked theme, remove from other
+ */
+ selectTheme: function () {
+ jQuery('.themebutton').toggleClass('selected', false);
+ jQuery(this).toggleClass('selected', true);
+ },
+
+ /**
+ * Allow only number, by direct removing other characters from input
+ */
+ filterNumberinput: function (elem) {
+ if (elem.value.match(/\D/)) {
+ elem.value = this.value.replace(/\D/g, '');
+ }
+ },
+
+ /**
+ * When a number larger than zero is inputted, check the checkbox
+ */
+ autoCheckboxForNumbers: function (elem) {
+ let checkboxid = elem.id.substring(0, elem.id.length - 1);
+ let value = elem.value;
+ //exception for second number field of max: only uncheck when first field is also empty
+ if (elem.id === 'maxm' && !(elem.value > 0)) {
+ value = parseInt(jQuery('input#maxn').val());
+ }
+ jQuery('input#' + checkboxid).prop('checked', value > 0);
+ },
+
+ /**
+ * Insert the indexmenu with options to the textarea,
+ * replacing the current selection or at the cursor position.
+ */
+ insertIndexmenu: function () {
+ let options = '';
+ jQuery('fieldset.indexmenu_options input').each(function (i, input) {
+ let $label = jQuery(this).parent();
+
+ if (input.checked && (!$label.hasClass('jsitem') || jQuery('input#jstoggle').is(':checked'))) {
+ if (input.id === 'jstoggle') {
+ //add js options
+ options += ' js';
+ //add theme
+ let themename = jQuery('#themebar button.selected').attr('id');
+ if (indexmenu_wiz.defaulttheme !== themename) { //skip default theme
+ options += '#' + themename;
+ }
+ } else {
+ //add option
+ options += ' ' + input.id;
+ //add numbers
+ if ($label.hasClass('hasnumber')) {
+ jQuery.each(indexmenu_wiz.fields.div6.elems[input.id].numberinput, function (j, numid) {
+ let num = parseInt(jQuery('input#' + numid).val());
+ options += num ? '#' + num : '';
+ });
+ }
+ }
+ }
+
+ });
+ options = options ? '|' + options.trim() : '';
+
+ let sel, ns, depth, syntax, eo;
+
+ // XXX: Compatibility Fix for 2014-05-05 "Ponder Stibbons", splitbrain/dokuwiki#505
+ if (DWgetSelection) {
+ sel = DWgetSelection(indexmenu_wiz.textArea);
+ } else {
+ sel = getSelection(indexmenu_wiz.textArea);
+ }
+
+
+ ns = jQuery('#namespace').val();
+ depth = parseInt(jQuery('#nsdepth').val());
+ depth = depth ? '#' + depth : '';
+
+ syntax = '{{indexmenu>' + ns + depth + options + '}}';
+ eo = depth.length + options.length + 2;
+
+ pasteText(sel, syntax, {startofs: 12, endofs: eo});
+ indexmenu_wiz.hide();
+ },
+
+ /**
+ * Insert meta number for sorting in textarea
+ * Takes number from input, otherwise tries the selection in textarea
+ */
+ insertMetaNumber: function () {
+ let sel, selnum, syntax, number;
+
+ // XXX: Compatibility Fix for 2014-05-05 "Ponder Stibbons", splitbrain/dokuwiki#505
+ if (DWgetSelection) {
+ sel = DWgetSelection(indexmenu_wiz.textArea);
+ } else {
+ sel = getSelection(indexmenu_wiz.textArea);
+ }
+
+ selnum = parseInt(sel.getText());
+ number = parseInt(jQuery('input#metanumber').val());
+ number = number || selnum || 1;
+ syntax = '{{indexmenu_n>' + number + '}}';
+
+ pasteText(sel, syntax, {startofs: 14, endofs: 2});
+ indexmenu_wiz.hide();
+ },
+
+ /**
+ * Show the indexmenu wizard
+ */
+ show: function () {
+ // XXX: Compatibility Fix for 2014-05-05 "Ponder Stibbons", splitbrain/dokuwiki#505
+ if (DWgetSelection) {
+ indexmenu_wiz.selection = DWgetSelection(indexmenu_wiz.textArea);
+ } else {
+ indexmenu_wiz.selection = getSelection(indexmenu_wiz.textArea);
+ }
+
+ indexmenu_wiz.$wiz.show();
+ jQuery('#namespace').trigger('focus');
+ },
+
+ /**
+ * Hide the indexmenu wizard
+ */
+ hide: function () {
+ indexmenu_wiz.$wiz.hide();
+ indexmenu_wiz.textArea.focus(); //pure js
+ },
+
+ /**
+ * Toggle the indexmenu wizard
+ */
+ toggle: function () {
+ if (indexmenu_wiz.$wiz.css('display') === 'none') {
+ indexmenu_wiz.show();
+ } else {
+ indexmenu_wiz.hide();
+ }
+ }
+};