1/*! 2 * jquery.fancytree.wide.js 3 * Support for 100% wide selection bars. 4 * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) 5 * 6 * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de) 7 * 8 * Released under the MIT license 9 * https://github.com/mar10/fancytree/wiki/LicenseInfo 10 * 11 * @version 2.38.3 12 * @date 2023-02-01T20:52:50Z 13 */ 14 15(function (factory) { 16 if (typeof define === "function" && define.amd) { 17 // AMD. Register as an anonymous module. 18 define(["jquery", "./jquery.fancytree"], factory); 19 } else if (typeof module === "object" && module.exports) { 20 // Node/CommonJS 21 require("./jquery.fancytree"); 22 module.exports = factory(require("jquery")); 23 } else { 24 // Browser globals 25 factory(jQuery); 26 } 27})(function ($) { 28 "use strict"; 29 30 var reNumUnit = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/; // split "1.5em" to ["1.5", "em"] 31 32 /******************************************************************************* 33 * Private functions and variables 34 */ 35 // var _assert = $.ui.fancytree.assert; 36 37 /* Calculate inner width without scrollbar */ 38 // function realInnerWidth($el) { 39 // // http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/ 40 // // inst.contWidth = parseFloat(this.$container.css("width"), 10); 41 // // 'Client width without scrollbar' - 'padding' 42 // return $el[0].clientWidth - ($el.innerWidth() - parseFloat($el.css("width"), 10)); 43 // } 44 45 /* Create a global embedded CSS style for the tree. */ 46 function defineHeadStyleElement(id, cssText) { 47 id = "fancytree-style-" + id; 48 var $headStyle = $("#" + id); 49 50 if (!cssText) { 51 $headStyle.remove(); 52 return null; 53 } 54 if (!$headStyle.length) { 55 $headStyle = $("<style />") 56 .attr("id", id) 57 .addClass("fancytree-style") 58 .prop("type", "text/css") 59 .appendTo("head"); 60 } 61 try { 62 $headStyle.html(cssText); 63 } catch (e) { 64 // fix for IE 6-8 65 $headStyle[0].styleSheet.cssText = cssText; 66 } 67 return $headStyle; 68 } 69 70 /* Calculate the CSS rules that indent title spans. */ 71 function renderLevelCss( 72 containerId, 73 depth, 74 levelOfs, 75 lineOfs, 76 labelOfs, 77 measureUnit 78 ) { 79 var i, 80 prefix = "#" + containerId + " span.fancytree-level-", 81 rules = []; 82 83 for (i = 0; i < depth; i++) { 84 rules.push( 85 prefix + 86 (i + 1) + 87 " span.fancytree-title { padding-left: " + 88 (i * levelOfs + lineOfs) + 89 measureUnit + 90 "; }" 91 ); 92 } 93 // Some UI animations wrap the UL inside a DIV and set position:relative on both. 94 // This breaks the left:0 and padding-left:nn settings of the title 95 rules.push( 96 "#" + 97 containerId + 98 " div.ui-effects-wrapper ul li span.fancytree-title, " + 99 "#" + 100 containerId + 101 " li.fancytree-animating span.fancytree-title " + // #716 102 "{ padding-left: " + 103 labelOfs + 104 measureUnit + 105 "; position: static; width: auto; }" 106 ); 107 return rules.join("\n"); 108 } 109 110 // /** 111 // * [ext-wide] Recalculate the width of the selection bar after the tree container 112 // * was resized.<br> 113 // * May be called explicitly on container resize, since there is no resize event 114 // * for DIV tags. 115 // * 116 // * @alias Fancytree#wideUpdate 117 // * @requires jquery.fancytree.wide.js 118 // */ 119 // $.ui.fancytree._FancytreeClass.prototype.wideUpdate = function(){ 120 // var inst = this.ext.wide, 121 // prevCw = inst.contWidth, 122 // prevLo = inst.lineOfs; 123 124 // inst.contWidth = realInnerWidth(this.$container); 125 // // Each title is precceeded by 2 or 3 icons (16px + 3 margin) 126 // // + 1px title border and 3px title padding 127 // // TODO: use code from treeInit() below 128 // inst.lineOfs = (this.options.checkbox ? 3 : 2) * 19; 129 // if( prevCw !== inst.contWidth || prevLo !== inst.lineOfs ) { 130 // this.debug("wideUpdate: " + inst.contWidth); 131 // this.visit(function(node){ 132 // node.tree._callHook("nodeRenderTitle", node); 133 // }); 134 // } 135 // }; 136 137 /******************************************************************************* 138 * Extension code 139 */ 140 $.ui.fancytree.registerExtension({ 141 name: "wide", 142 version: "2.38.3", 143 // Default options for this extension. 144 options: { 145 iconWidth: null, // Adjust this if @fancy-icon-width != "16px" 146 iconSpacing: null, // Adjust this if @fancy-icon-spacing != "3px" 147 labelSpacing: null, // Adjust this if padding between icon and label != "3px" 148 levelOfs: null, // Adjust this if ul padding != "16px" 149 }, 150 151 treeCreate: function (ctx) { 152 this._superApply(arguments); 153 this.$container.addClass("fancytree-ext-wide"); 154 155 var containerId, 156 cssText, 157 iconSpacingUnit, 158 labelSpacingUnit, 159 iconWidthUnit, 160 levelOfsUnit, 161 instOpts = ctx.options.wide, 162 // css sniffing 163 $dummyLI = $( 164 "<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />" 165 ).appendTo(ctx.tree.$container), 166 $dummyIcon = $dummyLI.find(".fancytree-icon"), 167 $dummyUL = $dummyLI.find("ul"), 168 // $dummyTitle = $dummyLI.find(".fancytree-title"), 169 iconSpacing = 170 instOpts.iconSpacing || $dummyIcon.css("margin-left"), 171 iconWidth = instOpts.iconWidth || $dummyIcon.css("width"), 172 labelSpacing = instOpts.labelSpacing || "3px", 173 levelOfs = instOpts.levelOfs || $dummyUL.css("padding-left"); 174 175 $dummyLI.remove(); 176 177 iconSpacingUnit = iconSpacing.match(reNumUnit)[2]; 178 iconSpacing = parseFloat(iconSpacing, 10); 179 labelSpacingUnit = labelSpacing.match(reNumUnit)[2]; 180 labelSpacing = parseFloat(labelSpacing, 10); 181 iconWidthUnit = iconWidth.match(reNumUnit)[2]; 182 iconWidth = parseFloat(iconWidth, 10); 183 levelOfsUnit = levelOfs.match(reNumUnit)[2]; 184 if ( 185 iconSpacingUnit !== iconWidthUnit || 186 levelOfsUnit !== iconWidthUnit || 187 labelSpacingUnit !== iconWidthUnit 188 ) { 189 $.error( 190 "iconWidth, iconSpacing, and levelOfs must have the same css measure unit" 191 ); 192 } 193 this._local.measureUnit = iconWidthUnit; 194 this._local.levelOfs = parseFloat(levelOfs); 195 this._local.lineOfs = 196 (1 + 197 (ctx.options.checkbox ? 1 : 0) + 198 (ctx.options.icon === false ? 0 : 1)) * 199 (iconWidth + iconSpacing) + 200 iconSpacing; 201 this._local.labelOfs = labelSpacing; 202 this._local.maxDepth = 10; 203 204 // Get/Set a unique Id on the container (if not already exists) 205 containerId = this.$container.uniqueId().attr("id"); 206 // Generated css rules for some levels (extended on demand) 207 cssText = renderLevelCss( 208 containerId, 209 this._local.maxDepth, 210 this._local.levelOfs, 211 this._local.lineOfs, 212 this._local.labelOfs, 213 this._local.measureUnit 214 ); 215 defineHeadStyleElement(containerId, cssText); 216 }, 217 treeDestroy: function (ctx) { 218 // Remove generated css rules 219 defineHeadStyleElement(this.$container.attr("id"), null); 220 return this._superApply(arguments); 221 }, 222 nodeRenderStatus: function (ctx) { 223 var containerId, 224 cssText, 225 res, 226 node = ctx.node, 227 level = node.getLevel(); 228 229 res = this._super(ctx); 230 // Generate some more level-n rules if required 231 if (level > this._local.maxDepth) { 232 containerId = this.$container.attr("id"); 233 this._local.maxDepth *= 2; 234 node.debug( 235 "Define global ext-wide css up to level " + 236 this._local.maxDepth 237 ); 238 cssText = renderLevelCss( 239 containerId, 240 this._local.maxDepth, 241 this._local.levelOfs, 242 this._local.lineOfs, 243 this._local.labelSpacing, 244 this._local.measureUnit 245 ); 246 defineHeadStyleElement(containerId, cssText); 247 } 248 // Add level-n class to apply indentation padding. 249 // (Setting element style would not work, since it cannot easily be 250 // overriden while animations run) 251 $(node.span).addClass("fancytree-level-" + level); 252 return res; 253 }, 254 }); 255 // Value returned by `require('jquery.fancytree..')` 256 return $.ui.fancytree; 257}); // End of closure 258