1/*! 2 * jquery.fancytree.columnview.js 3 * 4 * Render tree like a Mac Finder's column view. 5 * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) 6 * 7 * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de) 8 * 9 * Released under the MIT license 10 * https://github.com/mar10/fancytree/wiki/LicenseInfo 11 * 12 * @version 2.38.3 13 * @date 2023-02-01T20:52:50Z 14 */ 15 16(function (factory) { 17 if (typeof define === "function" && define.amd) { 18 // AMD. Register as an anonymous module. 19 define(["jquery", "./jquery.fancytree"], factory); 20 } else if (typeof module === "object" && module.exports) { 21 // Node/CommonJS 22 require("./jquery.fancytree"); 23 module.exports = factory(require("jquery")); 24 } else { 25 // Browser globals 26 factory(jQuery); 27 } 28})(function ($) { 29 "use strict"; 30 31 /******************************************************************************* 32 * Private functions and variables 33 */ 34 var _assert = $.ui.fancytree.assert, 35 FT = $.ui.fancytree; 36 37 /******************************************************************************* 38 * Private functions and variables 39 */ 40 $.ui.fancytree.registerExtension({ 41 name: "columnview", 42 version: "2.38.3", 43 // Default options for this extension. 44 options: {}, 45 // Overide virtual methods for this extension. 46 // `this` : is this extension object 47 // `this._base` : the Fancytree instance 48 // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree) 49 treeInit: function (ctx) { 50 var $tdFirst, 51 $ul, 52 tree = ctx.tree, 53 $table = tree.widget.element; 54 55 tree.tr = $("tbody tr", $table)[0]; 56 tree.$tdList = $(">td", tree.tr); 57 tree.columnCount = tree.$tdList.length; 58 // Perform default behavior 59 this._superApply(arguments); 60 // Standard Fancytree created a root <ul>. Now move this into first table cell 61 $ul = $(tree.rootNode.ul); 62 $tdFirst = tree.$tdList.eq(0); 63 64 _assert( 65 $.inArray("table", this.options.extensions) < 0, 66 "columnview extensions must not use ext-table" 67 ); 68 _assert( 69 tree.columnCount >= 2, 70 "columnview target must be a table with at least two columns" 71 ); 72 73 $ul.removeClass("fancytree-container").removeAttr("tabindex"); 74 tree.$container = $table; 75 $table 76 .addClass("fancytree-container fancytree-ext-columnview") 77 .attr("tabindex", "0"); 78 79 $tdFirst.empty(); 80 $ul.detach().appendTo($tdFirst); 81 82 // Force some required options 83 tree.widget.options.autoCollapse = true; 84 // tree.widget.options.autoActivate = true; 85 tree.widget.options.toggleEffect = false; 86 tree.widget.options.clickFolderMode = 1; 87 88 $table 89 // Make sure that only active path is expanded when a node is activated: 90 .on("fancytreeactivate", function (event, data) { 91 var node = data.node, 92 tree = data.tree, 93 level = node.getLevel(); 94 95 tree._callHook("nodeCollapseSiblings", node); 96 // Clear right neighbours 97 if (!node.expanded) { 98 tree.$tdList.eq(level).nextAll().empty(); 99 } 100 // Expand nodes on activate, so we populate the right neighbor cell 101 if (!node.expanded && (node.children || node.lazy)) { 102 node.setExpanded(); 103 } 104 }) 105 // Adjust keyboard behaviour: 106 .on("fancytreekeydown", function (event, data) { 107 var next = null, 108 handled = true, 109 node = data.node || data.tree.getFirstChild(); 110 111 if (node.getLevel() >= tree.columnCount) { 112 return; 113 } 114 switch (FT.eventToString(event)) { 115 case "down": 116 next = node.getNextSibling(); 117 break; 118 case "left": 119 if (!node.isTopLevel()) { 120 next = node.getParent(); 121 } 122 break; 123 case "right": 124 next = node.getFirstChild(); 125 if (!next) { 126 // default processing: expand or ignore 127 return; 128 } 129 // Prefer an expanded child if any 130 next.visitSiblings(function (n) { 131 if (n.expanded) { 132 next = n; 133 return false; 134 } 135 }, true); 136 break; 137 case "up": 138 next = node.getPrevSibling(); 139 break; 140 default: 141 handled = false; 142 } 143 if (next) { 144 next.setActive(); 145 } 146 return !handled; 147 }); 148 }, 149 nodeSetExpanded: function (ctx, flag, callOpts) { 150 var $wait, 151 node = ctx.node, 152 tree = ctx.tree, 153 level = node.getLevel(); 154 155 if (flag !== false && !node.expanded && node.isUndefined()) { 156 $wait = $( 157 "<span class='fancytree-icon fancytree-icon-loading'>" 158 ); 159 tree.$tdList.eq(level).empty().append($wait); 160 } 161 return this._superApply(arguments); 162 }, 163 nodeRemoveChildren: function (ctx) { 164 // #899: node's children removed: remove child marker... 165 $(ctx.node.span).find("span.fancytree-cv-right").remove(); 166 // ...and clear right columns 167 ctx.tree.$tdList.eq(ctx.node.getLevel()).nextAll().empty(); 168 return this._superApply(arguments); 169 }, 170 nodeRender: function (ctx, force, deep, collapsed, _recursive) { 171 // Render standard nested <ul> - <li> hierarchy 172 this._super(ctx, force, deep, collapsed, _recursive); 173 // Remove expander and add a trailing triangle instead 174 var level, 175 $tdChild, 176 $ul, 177 tree = ctx.tree, 178 node = ctx.node, 179 $span = $(node.span); 180 181 $span.find("span.fancytree-expander").remove(); 182 if ( 183 node.hasChildren() !== false && 184 !$span.find("span.fancytree-cv-right").length 185 ) { 186 $span.append( 187 $("<span class='fancytree-icon fancytree-cv-right'>") 188 ); 189 } 190 // Move <ul> with children into the appropriate <td> 191 if (node.ul && node.expanded) { 192 node.ul.style.display = ""; // might be hidden if RIGHT was pressed 193 level = node.getLevel(); 194 if (level < tree.columnCount) { 195 // only if we are not in the last column 196 $tdChild = tree.$tdList.eq(level); 197 $ul = $(node.ul).detach(); 198 $tdChild.empty().append($ul); 199 } 200 } 201 }, 202 }); 203 // Value returned by `require('jquery.fancytree..')` 204 return $.ui.fancytree; 205}); // End of closure 206