vendor: 15,966 bytes, lines 1-546
1/*! 2 * jquery.fancytree.table.js 3 * 4 * Render tree as table (aka 'tree grid', 'table tree'). 5 * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) 6 * 7 * Copyright (c) 2008-2019, Martin Wendt (https://wwWendt.de) 8 * 9 * Released under the MIT license 10 * https://github.com/mar10/fancytree/wiki/LicenseInfo 11 * 12 * @version 2.33.0 13 * @date 2019-10-29T08:00:07Z 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 function _assert(cond, msg) { 35 msg = msg || ""; 36 if (!cond) { 37 $.error("Assertion failed " + msg); 38 } 39 } 40 41 function insertFirstChild(referenceNode, newNode) { 42 referenceNode.insertBefore(newNode, referenceNode.firstChild); 43 } 44 45 function insertSiblingAfter(referenceNode, newNode) { 46 referenceNode.parentNode.insertBefore( 47 newNode, 48 referenceNode.nextSibling 49 ); 50 } 51 52 /* Show/hide all rows that are structural descendants of `parent`. */ 53 function setChildRowVisibility(parent, flag) { 54 parent.visit(function(node) { 55 var tr = node.tr; 56 // currentFlag = node.hide ? false : flag; // fix for ext-filter 57 if (tr) { 58 tr.style.display = node.hide || !flag ? "none" : ""; 59 } 60 if (!node.expanded) { 61 return "skip"; 62 } 63 }); 64 } 65 66 /* Find node that is rendered in previous row. */ 67 function findPrevRowNode(node) { 68 var i, 69 last, 70 prev, 71 parent = node.parent, 72 siblings = parent ? parent.children : null; 73 74 if (siblings && siblings.length > 1 && siblings[0] !== node) { 75 // use the lowest descendant of the preceeding sibling 76 i = $.inArray(node, siblings); 77 prev = siblings[i - 1]; 78 _assert(prev.tr); 79 // descend to lowest child (with a <tr> tag) 80 while (prev.children && prev.children.length) { 81 last = prev.children[prev.children.length - 1]; 82 if (!last.tr) { 83 break; 84 } 85 prev = last; 86 } 87 } else { 88 // if there is no preceding sibling, use the direct parent 89 prev = parent; 90 } 91 return prev; 92 } 93 94 $.ui.fancytree.registerExtension({ 95 name: "table", 96 version: "2.33.0", 97 // Default options for this extension. 98 options: { 99 checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx) 100 indentation: 16, // indent every node level by 16px 101 mergeStatusColumns: true, // display 'nodata', 'loading', 'error' centered in a single, merged TR 102 nodeColumnIdx: 0, // render node expander, icon, and title to this column (default: #0) 103 }, 104 // Overide virtual methods for this extension. 105 // `this` : is this extension object 106 // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree) 107 treeInit: function(ctx) { 108 var i, 109 n, 110 $row, 111 $tbody, 112 tree = ctx.tree, 113 opts = ctx.options, 114 tableOpts = opts.table, 115 $table = tree.widget.element; 116 117 if (tableOpts.customStatus != null) { 118 if (opts.renderStatusColumns == null) { 119 tree.warn( 120 "The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' instead." 121 ); 122 opts.renderStatusColumns = tableOpts.customStatus; 123 } else { 124 $.error( 125 "The 'customStatus' option is deprecated since v2.15.0. Use 'renderStatusColumns' only instead." 126 ); 127 } 128 } 129 if (opts.renderStatusColumns) { 130 if (opts.renderStatusColumns === true) { 131 opts.renderStatusColumns = opts.renderColumns; 132 // } else if( opts.renderStatusColumns === "wide" ) { 133 // opts.renderStatusColumns = _renderStatusNodeWide; 134 } 135 } 136 137 $table.addClass("fancytree-container fancytree-ext-table"); 138 $tbody = $table.find(">tbody"); 139 if (!$tbody.length) { 140 // TODO: not sure if we can rely on browsers to insert missing <tbody> before <tr>s: 141 if ($table.find(">tr").length) { 142 $.error( 143 "Expected table > tbody > tr. If you see this please open an issue." 144 ); 145 } 146 $tbody = $("<tbody>").appendTo($table); 147 } 148 149 tree.tbody = $tbody[0]; 150 151 // Prepare row templates: 152 // Determine column count from table header if any 153 tree.columnCount = $("thead >tr", $table) 154 .last() 155 .find(">th", $table).length; 156 // Read TR templates from tbody if any 157 $row = $tbody.children("tr").first(); 158 if ($row.length) { 159 n = $row.children("td").length; 160 if (tree.columnCount && n !== tree.columnCount) { 161 tree.warn( 162 "Column count mismatch between thead (" + 163 tree.columnCount + 164 ") and tbody (" + 165 n + 166 "): using tbody." 167 ); 168 tree.columnCount = n; 169 } 170 $row = $row.clone(); 171 } else { 172 // Only thead is defined: create default row markup 173 _assert( 174 tree.columnCount >= 1, 175 "Need either <thead> or <tbody> with <td> elements to determine column count." 176 ); 177 $row = $("<tr />"); 178 for (i = 0; i < tree.columnCount; i++) { 179 $row.append("<td />"); 180 } 181 } 182 $row.find(">td") 183 .eq(tableOpts.nodeColumnIdx) 184 .html("<span class='fancytree-node' />"); 185 if (opts.aria) { 186 $row.attr("role", "row"); 187 $row.find("td").attr("role", "gridcell"); 188 } 189 tree.rowFragment = document.createDocumentFragment(); 190 tree.rowFragment.appendChild($row.get(0)); 191 192 // // If tbody contains a second row, use this as status node template 193 // $row = $tbody.children("tr").eq(1); 194 // if( $row.length === 0 ) { 195 // tree.statusRowFragment = tree.rowFragment; 196 // } else { 197 // $row = $row.clone(); 198 // tree.statusRowFragment = document.createDocumentFragment(); 199 // tree.statusRowFragment.appendChild($row.get(0)); 200 // } 201 // 202 $tbody.empty(); 203 204 // Make sure that status classes are set on the node's <tr> elements 205 tree.statusClassPropName = "tr"; 206 tree.ariaPropName = "tr"; 207 this.nodeContainerAttrName = "tr"; 208 209 // #489: make sure $container is set to <table>, even if ext-dnd is listed before ext-table 210 tree.$container = $table; 211 212 this._superApply(arguments); 213 214 // standard Fancytree created a root UL 215 $(tree.rootNode.ul).remove(); 216 tree.rootNode.ul = null; 217 218 // Add container to the TAB chain 219 // #577: Allow to set tabindex to "0", "-1" and "" 220 this.$container.attr("tabindex", opts.tabindex); 221 // this.$container.attr("tabindex", opts.tabbable ? "0" : "-1"); 222 if (opts.aria) { 223 tree.$container 224 .attr("role", "treegrid") 225 .attr("aria-readonly", true); 226 } 227 }, 228 nodeRemoveChildMarkup: function(ctx) { 229 var node = ctx.node; 230 // node.debug("nodeRemoveChildMarkup()"); 231 node.visit(function(n) { 232 if (n.tr) { 233 $(n.tr).remove(); 234 n.tr = null; 235 } 236 }); 237 }, 238 nodeRemoveMarkup: function(ctx) { 239 var node = ctx.node; 240 // node.debug("nodeRemoveMarkup()"); 241 if (node.tr) { 242 $(node.tr).remove(); 243 node.tr = null; 244 } 245 this.nodeRemoveChildMarkup(ctx); 246 }, 247 /* Override standard render. */ 248 nodeRender: function(ctx, force, deep, collapsed, _recursive) { 249 var children, 250 firstTr, 251 i, 252 l, 253 newRow, 254 prevNode, 255 prevTr, 256 subCtx, 257 tree = ctx.tree, 258 node = ctx.node, 259 opts = ctx.options, 260 isRootNode = !node.parent; 261 262 if (tree._enableUpdate === false) { 263 // $.ui.fancytree.debug("*** nodeRender _enableUpdate: false"); 264 return; 265 } 266 if (!_recursive) { 267 ctx.hasCollapsedParents = node.parent && !node.parent.expanded; 268 } 269 // $.ui.fancytree.debug("*** nodeRender " + node + ", isRoot=" + isRootNode, "tr=" + node.tr, "hcp=" + ctx.hasCollapsedParents, "parent.tr=" + (node.parent && node.parent.tr)); 270 if (!isRootNode) { 271 if (node.tr && force) { 272 this.nodeRemoveMarkup(ctx); 273 } 274 if (node.tr) { 275 if (force) { 276 // Set icon, link, and title (normally this is only required on initial render) 277 this.nodeRenderTitle(ctx); // triggers renderColumns() 278 } else { 279 // Update element classes according to node state 280 this.nodeRenderStatus(ctx); 281 } 282 } else { 283 if (ctx.hasCollapsedParents && !deep) { 284 // #166: we assume that the parent will be (recursively) rendered 285 // later anyway. 286 // node.debug("nodeRender ignored due to unrendered parent"); 287 return; 288 } 289 // Create new <tr> after previous row 290 // if( node.isStatusNode() ) { 291 // newRow = tree.statusRowFragment.firstChild.cloneNode(true); 292 // } else { 293 newRow = tree.rowFragment.firstChild.cloneNode(true); 294 // } 295 prevNode = findPrevRowNode(node); 296 // $.ui.fancytree.debug("*** nodeRender " + node + ": prev: " + prevNode.key); 297 _assert(prevNode); 298 if (collapsed === true && _recursive) { 299 // hide all child rows, so we can use an animation to show it later 300 newRow.style.display = "none"; 301 } else if (deep && ctx.hasCollapsedParents) { 302 // also hide this row if deep === true but any parent is collapsed 303 newRow.style.display = "none"; 304 // newRow.style.color = "red"; 305 } 306 if (prevNode.tr) { 307 insertSiblingAfter(prevNode.tr, newRow); 308 } else { 309 _assert( 310 !prevNode.parent, 311 "prev. row must have a tr, or be system root" 312 ); 313 // tree.tbody.appendChild(newRow); 314 insertFirstChild(tree.tbody, newRow); // #675 315 } 316 node.tr = newRow; 317 if (node.key && opts.generateIds) { 318 node.tr.id = opts.idPrefix + node.key; 319 } 320 node.tr.ftnode = node; 321 // if(opts.aria){ 322 // $(node.tr).attr("aria-labelledby", "ftal_" + opts.idPrefix + node.key); 323 // } 324 node.span = $("span.fancytree-node", node.tr).get(0); 325 // Set icon, link, and title (normally this is only required on initial render) 326 this.nodeRenderTitle(ctx); 327 // Allow tweaking, binding, after node was created for the first time 328 // tree._triggerNodeEvent("createNode", ctx); 329 if (opts.createNode) { 330 opts.createNode.call(tree, { type: "createNode" }, ctx); 331 } 332 } 333 } 334 // Allow tweaking after node state was rendered 335 // tree._triggerNodeEvent("renderNode", ctx); 336 if (opts.renderNode) { 337 opts.renderNode.call(tree, { type: "renderNode" }, ctx); 338 } 339 // Visit child nodes 340 // Add child markup 341 children = node.children; 342 if (children && (isRootNode || deep || node.expanded)) { 343 for (i = 0, l = children.length; i < l; i++) { 344 subCtx = $.extend({}, ctx, { node: children[i] }); 345 subCtx.hasCollapsedParents = 346 subCtx.hasCollapsedParents || !node.expanded; 347 this.nodeRender(subCtx, force, deep, collapsed, true); 348 } 349 } 350 // Make sure, that <tr> order matches node.children order. 351 if (children && !_recursive) { 352 // we only have to do it once, for the root branch 353 prevTr = node.tr || null; 354 firstTr = tree.tbody.firstChild; 355 // Iterate over all descendants 356 node.visit(function(n) { 357 if (n.tr) { 358 if ( 359 !n.parent.expanded && 360 n.tr.style.display !== "none" 361 ) { 362 // fix after a node was dropped over a collapsed 363 n.tr.style.display = "none"; 364 setChildRowVisibility(n, false); 365 } 366 if (n.tr.previousSibling !== prevTr) { 367 node.debug("_fixOrder: mismatch at node: " + n); 368 var nextTr = prevTr ? prevTr.nextSibling : firstTr; 369 tree.tbody.insertBefore(n.tr, nextTr); 370 } 371 prevTr = n.tr; 372 } 373 }); 374 } 375 // Update element classes according to node state 376 // if(!isRootNode){ 377 // this.nodeRenderStatus(ctx); 378 // } 379 }, 380 nodeRenderTitle: function(ctx, title) { 381 var $cb, 382 res, 383 tree = ctx.tree, 384 node = ctx.node, 385 opts = ctx.options, 386 isStatusNode = node.isStatusNode(); 387 388 res = this._super(ctx, title); 389 390 if (node.isRootNode()) { 391 return res; 392 } 393 // Move checkbox to custom column 394 if ( 395 opts.checkbox && 396 !isStatusNode && 397 opts.table.checkboxColumnIdx != null 398 ) { 399 $cb = $("span.fancytree-checkbox", node.span); //.detach(); 400 $(node.tr) 401 .find("td") 402 .eq(+opts.table.checkboxColumnIdx) 403 .html($cb); 404 } 405 // Update element classes according to node state 406 this.nodeRenderStatus(ctx); 407 408 if (isStatusNode) { 409 if (opts.renderStatusColumns) { 410 // Let user code write column content 411 opts.renderStatusColumns.call( 412 tree, 413 { type: "renderStatusColumns" }, 414 ctx 415 ); 416 } else if (opts.table.mergeStatusColumns && node.isTopLevel()) { 417 $(node.tr) 418 .find(">td") 419 .eq(0) 420 .prop("colspan", tree.columnCount) 421 .text(node.title) 422 .addClass("fancytree-status-merged") 423 .nextAll() 424 .remove(); 425 } // else: default rendering for status node: leave other cells empty 426 } else if (opts.renderColumns) { 427 opts.renderColumns.call(tree, { type: "renderColumns" }, ctx); 428 } 429 return res; 430 }, 431 nodeRenderStatus: function(ctx) { 432 var indent, 433 node = ctx.node, 434 opts = ctx.options; 435 436 this._super(ctx); 437 438 $(node.tr).removeClass("fancytree-node"); 439 // indent 440 indent = (node.getLevel() - 1) * opts.table.indentation; 441 if (opts.rtl) { 442 $(node.span).css({ paddingRight: indent + "px" }); 443 } else { 444 $(node.span).css({ paddingLeft: indent + "px" }); 445 } 446 }, 447 /* Expand node, return Deferred.promise. */ 448 nodeSetExpanded: function(ctx, flag, callOpts) { 449 // flag defaults to true 450 flag = flag !== false; 451 452 if ((ctx.node.expanded && flag) || (!ctx.node.expanded && !flag)) { 453 // Expanded state isn't changed - just call base implementation 454 return this._superApply(arguments); 455 } 456 457 var dfd = new $.Deferred(), 458 subOpts = $.extend({}, callOpts, { 459 noEvents: true, 460 noAnimation: true, 461 }); 462 463 callOpts = callOpts || {}; 464 465 function _afterExpand(ok) { 466 setChildRowVisibility(ctx.node, flag); 467 if (ok) { 468 if ( 469 flag && 470 ctx.options.autoScroll && 471 !callOpts.noAnimation && 472 ctx.node.hasChildren() 473 ) { 474 // Scroll down to last child, but keep current node visible 475 ctx.node 476 .getLastChild() 477 .scrollIntoView(true, { topNode: ctx.node }) 478 .always(function() { 479 if (!callOpts.noEvents) { 480 ctx.tree._triggerNodeEvent( 481 flag ? "expand" : "collapse", 482 ctx 483 ); 484 } 485 dfd.resolveWith(ctx.node); 486 }); 487 } else { 488 if (!callOpts.noEvents) { 489 ctx.tree._triggerNodeEvent( 490 flag ? "expand" : "collapse", 491 ctx 492 ); 493 } 494 dfd.resolveWith(ctx.node); 495 } 496 } else { 497 if (!callOpts.noEvents) { 498 ctx.tree._triggerNodeEvent( 499 flag ? "expand" : "collapse", 500 ctx 501 ); 502 } 503 dfd.rejectWith(ctx.node); 504 } 505 } 506 // Call base-expand with disabled events and animation 507 this._super(ctx, flag, subOpts) 508 .done(function() { 509 _afterExpand(true); 510 }) 511 .fail(function() { 512 _afterExpand(false); 513 }); 514 return dfd.promise(); 515 }, 516 nodeSetStatus: function(ctx, status, message, details) { 517 if (status === "ok") { 518 var node = ctx.node, 519 firstChild = node.children ? node.children[0] : null; 520 if (firstChild && firstChild.isStatusNode()) { 521 $(firstChild.tr).remove(); 522 } 523 } 524 return this._superApply(arguments); 525 }, 526 treeClear: function(ctx) { 527 this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode)); 528 return this._superApply(arguments); 529 }, 530 treeDestroy: function(ctx) { 531 this.$container.find("tbody").empty(); 532 if (this.$source) { 533 this.$source.removeClass("fancytree-helper-hidden"); 534 } 535 return this._superApply(arguments); 536 }, 537 /*, 538 treeSetFocus: function(ctx, flag) { 539// alert("treeSetFocus" + ctx.tree.$container); 540 ctx.tree.$container.focus(); 541 $.ui.fancytree.focusTree = ctx.tree; 542 }*/ 543 }); 544 // Value returned by `require('jquery.fancytree..')` 545 return $.ui.fancytree; 546}); // End of closure
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.