PageSourceSearch

https://www.ncausa.org/DesktopModules/NOAH_Common/WebControls/Dict…/WebSupport/js/tree/tree.js

js ncausa.org collected 2026-10-01 08:55:29 UTC 29,540 bytes, 596 lines download raw bytes

1try {
2    versioning.reportVersion({
3        major: 1,
4        minor: 0,
5        revision: 4,
6        system: 12,
7        iteration: 1,
8        year: 2019,
9        name: 'tree.js',
10        requires: ['NOAH.Include.Config.js', 'NOAH.Include.js']
11    });
12} catch (ex) { console.log(ex.message); }
13
14$.fn.treePlugin = function (options) {
15    var myPlugin = this;
16    try {
17        var node = '<div id="wrap_{id}" class="FormLabel HTML5-Tree-Label"><i id="icon_{id}" class="{wrapperClass}"></i><input id="cb_{id}" type="checkbox" class="{controlClass}" value="{value}"><label id="lbl_{id}" for="cb_{id}" runat="server">{label}</label><div id="hidden{id}" class="hidden"></div></div>';
18        myPlugin.element = $(this);
19
20        var _defaults = {
21            id: 'myID',
22            data: {}
23        };
24        var settings = $.extend({}, _defaults, options);
25
26        var _DefaultString = 'Node';
27        var _NotSet = 'NOTSET';
28        var _MinNumber = Number.MIN_VALUE;
29
30        var noahAttributes = {
31            GroupType: _NotSet,
32            GroupCode: _NotSet,
33            MasterCode: _NotSet,
34            McInstructions: _NotSet,
35            parentid: _MinNumber
36        };
37
38        var item = {
39            id: _MinNumber,
40            text: _DefaultString,
41            NOAH: noahAttributes,
42            subMenuItems: {}
43        };
44
45        if (!settings.data || !settings.data.hasOwnProperty("root")) {
46            settings.data = JSON.parse(myPlugin.element.find('[treeData]').val() || "{}");
47        }
48
49        myPlugin.templates = {
50            tree: '',
51            leaf: '',
52            branch: ''
53        }
54
55        myPlugin.templates.tree = '<div id="{0}" class="FormControl HTML5-Tree-Node HTML5-Root-Tree {3}" {4} orphan="true"><div class="FormLabel HTML5-Tree-Label"><i class="HTML-Tree-Navigation-Icon fa fa-minus" openClass="fa-plus" closeClass="fa-minus" bindOpenClose="true"></i><input type="checkbox" id="cb{0}" class="HTML5-Tree-Trigger" value="{1}" event="detectchange" {formid} {ischecked} /><label id="lbl{0}" for="cb{0}">{6}</label><input id="hfData_{0}_Storage" controldatatype="Storage" type="hidden" isForTree="true" value="{5}" {4} /><LIST class="FormControl HTML5-Tree-Node HTML5-Root-Tree HTML5-Branch-Tree {2}" openCloseTarget="true"></LIST></div></div>';
56        myPlugin.templates.leaf = '<LISTITEM id="{0}" class="FormControl HTML5-Tree-Node HTML5-Tree-Leaf {3}" {4} orphan="true"><div class="FormLabel HTML5-Tree-Label"><i class="HTML-Tree-Navigation-Icon fa fa-leaf"></i><input type="checkbox" id="cb{0}" class="HTML5-Tree-Trigger" value="{1}" event="detectchange" {formid} {ischecked} /><label id="lbl{0}" for="cb{0}">{6}</label><div class="hidden"><input id="hfData_{0}_Storage" controldatatype="Storage" type="hidden" isForTree="true" value="{5}" {4} /></div></div></LISTITEM>';
57        myPlugin.templates.branch = '<LISTITEM id="{0}" class="FormControl HTML5-Tree-Node {3}" {4} orphan="true"><div class="FormLabel HTML5-Tree-Label"><i class="HTML-Tree-Navigation-Icon fa fa-plus" openClass="fa-plus" closeClass="fa-minus" bindOpenClose="true"></i><input type="checkbox" id="cb{0}" class="HTML5-Tree-Trigger" value="{1}" event="detectchange" {formid} {ischecked} /><label id="lbl{0}" for="cb{0}">{6}</label><input id="hfData_{0}_Storage" controldatatype="Storage" type="hidden" isForTree="true" value="{5}" {4} /><LIST class="FormControl HTML5-Tree-Node HTML5-Branch-Tree {2}" openCloseTarget="true" style="display: none;" ></LIST></div></LISTITEM>';
58
59
60        myPlugin.data = settings.data;
61        myPlugin.createUI = function (options) {
62            try {
63                var passOptions = {
64                    data: options.data,
65                    formId: options.formId,
66                    root: true,
67                    options: {
68                        initialStart: true
69                    }
70                };
71                myPlugin.createNode(passOptions);
72
73            } catch (ex) {
74                console.log(ex.message);
75            }
76        };
77        myPlugin.createNode = function (options) {
78            var settings = {};
79            try {
80                var _defaults = {
81                    templateToUse: myPlugin.templates.tree,
82                    root: false,
83                    replaceValues: {
84                        id: '',
85                        valueOfChildren: '',
86                        nameOfGroup: '',
87                        classToUse: '',
88                        attributes: '',
89                        selectedValue: '',
90                        description: ''
91                    },
92                    options: {
93                        initialStart: false
94                    },
95                    data: null,
96                    formId: '',
97                }
98
99                settings = $.extend({}, _defaults, options);
100
101                if (!settings.options.initialStart) {
102                    settings.templateToUse = myPlugin.templates.leaf;
103                    if (settings.data && settings.data.items && settings.data.items.length > 0) {
104                        settings.templateToUse = myPlugin.templates.branch;
105                    }
106                }
107
108                var attributes = '';
109                var visibleAttr = '';
110                var checkedAttribute = '';
111
112                if (settings.data && settings.data.checked.toString().trim().toLowerCase() == 'true') { checkedAttribute = " checked='checked'" }
113
114
115                try { attributes += " MCInitialShow='" + settings.data.mcInitialShow.toString() + "'"; } catch (ex) { console.log(ex.message); }
116                try { attributes += " childCount='" + settings.data.childCount.toString() + "'"; } catch (ex) { console.log(ex.message); }
117                try { attributes += " level='" + settings.data.level.toString() + "'"; } catch (ex) { console.log(ex.message); }
118                try { attributes += " mcid='" + settings.data.mcid.toString() + "'"; } catch (ex) { console.log(ex.message); }
119                try { attributes += " parentmcid='" + settings.data.NOAH.parentMCid.toString() + "'"; } catch (ex) { console.log(ex.message); }
120                try { attributes += " GroupType='" + settings.data.NOAH.groupType.toString() + "'"; } catch (ex) { console.log(ex.message); }
121                try { attributes += " GroupCode='" + settings.data.NOAH.groupCode.toString() + "'"; } catch (ex) { console.log(ex.message); }
122                try { attributes += " MasterCode='" + settings.data.NOAH.masterCode.toString() + "'"; } catch (ex) { console.log(ex.message); }
123                try { checkedAttribute += " reference_Table='" + settings.data.reference_Table.toString() + "'"; } catch (ex) { console.log(ex.message); }
124                try { checkedAttribute += " reference_PkId='" + settings.data.reference_PkId.toString() + "'"; } catch (ex) { console.log(ex.message); }
125                try { attributes += " dfbhtml5-id='" + settings.formId.toString() + "'"; } catch (ex) { console.log(ex.message); }
126
127                try { if (settings.root) { attributes += " root='root'"; } } catch (ex) { console.log(ex.message); }
128
129                settings.replaceValues.id = settings.data.mcid;
130                settings.replaceValues.valueOfChildren = options.data.NOAH.masterCode;
131                settings.replaceValues.nameOfGroup = settings.formId.toString();
132                settings.replaceValues.classToUse = 'NO-MARGIN';
133                settings.replaceValues.attributes = checkedAttribute + attributes;
134                settings.replaceValues.selectedValue = options.data.NOAH.masterCode.toString();
135                settings.replaceValues.description = settings.data.text;
136
137
138
139
140
141
142
143
144
145
146                var newTemplate = settings.templateToUse.replace(/\{0\}/g, settings.replaceValues.id)
147                    .replace(/\{1\}/g, settings.replaceValues.valueOfChildren)
148                    .replace(/\{2\}/g, settings.replaceValues.nameOfGroup)
149                    .replace(/\{3\}/g, settings.replaceValues.classToUse)
150                    .replace(/\{4\}/g, settings.replaceValues.attributes)
151                    .replace(/\{5\}/g, settings.replaceValues.selectedValue)
152                    .replace(/\{6\}/g, settings.replaceValues.description)
153                    .replace(/\{formid\}/g, " dfbhtml5-id='" + settings.formId + "'")
154                    .replace(/\{ischecked\}/g, checkedAttribute);
155
156                myPlugin.element.append(newTemplate);
157
158                $(settings.data.items).each(function () {
159                    try {
160                        myPlugin.createNode({
161                            data: this,
162                            root: false,
163                            formId: settings.formId,
164                            options: {
165                                initialStart: false
166                            }
167                        });
168                    } catch (ex) {
169                        console.log(ex.message);
170                    }
171                });
172            } catch (ex) {
173                console.log(ex.message);
174            }
175            return settings;
176        };
177        myPlugin.handleTreeLevel = function (id, levelOf, topGroupType) {
178            try {
179                var limitAttemptsTo = 10;
180                var i = 0;
181                var lastMCID = -1;
182
183
184                var topOrphan = null;
185                var idToWork = null;
186
187                var subItems = null;
188                var parentItem = null;
189
190                var level = levelOf;
191                var maxLevel = (levelOf + 2);
192
193                var startStack = null;
194                var orphanStack = null;
195                orphanStack = null;
196
197                if (level == 0) {
198
199                    orphanStack = $('[grouptype=' + topGroupType + '][orphan=true][level=0], [grouptype=' + topGroupType + '][orphan=true][level=1]');
200                } else {
201
202                    orphanStack = $('[grouptype=' + topGroupType + '][orphan=true][parentmcid=' + id + ']');
203                }
204
205                try {
206                    startStack = $(orphanStack[0]);
207                } catch (ex) {
208                    console.log(ex.message);
209                }
210                var start = new Date;
211
212                var selectedItem = null;
213                var branchItems = null;
214                var appendedOrphans = null;
215
216
217                while (orphanStack.length > 0 && i <= limitAttemptsTo) {
218                    topOrphan = $(orphanStack[0]);
219
220                    idToWork = topOrphan.attr('mcid');
221                    level = topOrphan.attr('level');
222
223
224
225                    if (lastMCID != idToWork) {
226                        selectedItem = $('[parentmcid=' + idToWork + ']').detach();
227                        branchItems = $('[mcid=' + idToWork + ']').find('LIST.HTML5-Branch-Tree');
228                        selectedItem.appendTo(branchItems);
229                    }
230
231                    $(orphanStack[0]).removeAttr('orphan');
232
233                    orphanStack.splice(0, 1);
234                    if (lastMCID == idToWork) {
235                        i++;
236                    } else {
237                        i = 0;
238                    }
239                    lastMCID = idToWork;
240                }
241
242                var end = new Date();
243                var diff = end - start;
244                console.log('elapse time: ' + diff.toString() + 'ms for grouptype=' + topGroupType);
245
246                if (startStack) {
247                    console.log('Plugin-Tree initial checking items (script run for change data values)...');
248                    if (startStack.find('.HTML5-Tree-Leaf[checked]').not('[assignedEvents]').length > 0) {
249                        startStack.find('.HTML5-Tree-Leaf[checked]').not('[assignedEvents]').each(function () {
250
251
252
253
254                            $($(this).find('input')[0]).prop('checked', 'checked').attr('assignedEvents', 'true');
255                        })
256                    }
257
258                    console.log('Plugin-Tree initial checking items (no script run ignore change data values)...');
259                    if (startStack.find('.HTML5-Tree-Leaf[checked]').not('[prechecked]').length > 0) {
260                        startStack.find('.HTML5-Tree-Leaf[checked]').not('[prechecked]').each(function () {
261
262                            var currentParent = $(this).parent();
263                            var maxParentsToTest = 100;
264                            var x = 0;
265                            while (!currentParent.hasClass('.HTML5-Root-Tree') && x < maxParentsToTest) {
266                                if (currentParent.is('li')) {
267                                    if (currentParent.hasClass('HTML5-Tree-Node')) {
268                                        $(currentParent.find('input.HTML5-Tree-Trigger')[0]).prop('checked', 'checked').attr('prechecked', 'true')
269                                    }
270                                    console.log(currentParent.attr('id') + " " + currentParent.attr('class') + " -> " + currentParent.hasClass('HTML5-Tree-Node'));
271                                }
272                                currentParent = currentParent.parent();
273
274                                x++;
275                            }
276                        });
277                    }
278                }
279            } catch (ex) {
280                console.log(ex.message);
281            }
282        };
283        myPlugin.init = function (options) {
284            var result = myPlugin;
285            try {
286                console.log('Plugin-Tree started, creating UI from data...');
287
288                myPlugin.element.find('[rootchecked] > div > input').prop('checked', 'checked');
289                myPlugin.element.find('[branchchecked] > div > input').prop('checked', 'checked');
290                myPlugin.element.find('[leafchecked] > div > input').prop('checked', 'checked');
291                myPlugin.element.find('[rootchecked]').removeProp('rootchecked');
292                myPlugin.element.find('[branchchecked]').removeProp('branchchecked');
293                myPlugin.element.find('[leafchecked]').removeProp('leafchecked');
294
295                myPlugin.element.find('div.HTML5-Root-Tree').each(function () {
296                    try {
297                        var rootID = parseInt($(this).attr('mcid'));
298                        var groupType = $(this).attr('grouptype');
299                        myPlugin.handleTreeLevel(rootID, 0, groupType);
300                    } catch (ex) {
301                        console.log(ex.message);
302                    }
303                })
304
305                console.log('Plugin-Tree finding bindable triggers...');
306                if (myPlugin.element.find('[bindOpenClose=true]').length > 0) {
307                    myPlugin.element.find('[bindOpenClose=true]').click(function () {
308                        try {
309                            isStartForm = false;
310                            var currentElement = $(this);
311                            var openIconClass = currentElement.attr('openClass');
312                            var closeIconClass = currentElement.attr('closeClass');
313                            var currentIconClass = 'noidea';
314                            var toggleToIconClass = 'noidea';
315
316                            var levelOf = (parseInt(currentElement.parent().parent().attr('level')) + 1);
317                            var mcid = (parseInt(currentElement.parent().parent().attr('mcid')));
318                            var groupType = currentElement.parent().parent().attr('groupType');
319
320                            try {
321                                showPleaseWait({
322
323                                    visible: true, workToDo: function () {
324                                        try {
325                                            myPlugin.handleTreeLevel(mcid, levelOf, groupType);
326
327                                            if (currentElement.hasClass(openIconClass)) {
328                                                currentIconClass = openIconClass;
329                                                toggleToIconClass = closeIconClass;
330                                            
330} else {
331                                                currentIconClass = closeIconClass;
332                                                toggleToIconClass = openIconClass;
333                                            }
334
335                                            currentElement.removeClass(currentIconClass).addClass(toggleToIconClass);
336                                            $(currentElement.parent().find('[openCloseTarget=true]')[0]).toggle();
337
338                                        }
339                                        catch (ex) {
340                                            console.log(ex.message);
341                                        }
342                                    }
343                                });
344                            } catch (ex) { }
345
346
347                        } catch (ex) {
348                            console.log(ex.message);
349                        }
350
351
352                    });
353                }
354
355
356                console.log('Plugin-Tree assigning expand/collapse triggers...');
357                if (myPlugin.element.find('listitem.HTML5-Tree-Node:not(.HTML5-Tree-Leaf)>div>input').length > 0) {
358                    myPlugin.element.find('listitem.HTML5-Tree-Node:not(.HTML5-Tree-Leaf)>div>input').click(function (item) {
359                        try { showPleaseWait({ visible: true }); } catch (ex) { console.log(ex.message); }
360                        try {
361                            var currentBranch = $(this).closest('listitem');
362                            var currentBranchTrigger = currentBranch.find('>div>input');
363                            var isBranchChecked = currentBranchTrigger.is(':checked');
364                            console.log('BRANCH ' + currentBranchTrigger.attr('id') + ' isChecked? ' + isBranchChecked);
365
366                            var ignoreDefaultBehavior = (currentBranchTrigger.attr('ignoreDefaultBehavior') || false);
367                            console.log('BRANCH ignoreDefaultBehavior? ' + ignoreDefaultBehavior)
368
369                            if (!ignoreDefaultBehavior) {
370                                if (isBranchChecked) {
371
372                                    currentBranch.attr('checked', 'checked');
373                                    currentBranch.next().attr('checked', 'checked');
374                                    currentBranch.prop('checked', 'checked');
375                                    currentBranch.next().prop('checked', 'checked');
376
377                                    currentBranchTrigger.attr('checked', 'checked');
378                                    currentBranchTrigger.next().attr('checked', 'checked');
379                                    currentBranchTrigger.prop('checked', 'checked');
380                                    currentBranchTrigger.next().prop('checked', 'checked');
381
382                                    currentBranch.find('list > listitem div > .HTML5-Tree-Trigger:not(:checked)').attr('ignoreDefaultBehavior', true).click();
383                                } else {
384
385                                    currentBranch.removeAttr('checked');
386                                    currentBranch.next().removeAttr('checked');
387                                    currentBranch.removeProp('checked');
388                                    currentBranch.next().removeProp('checked');
389
390                                    currentBranchTrigger.removeAttr('checked');
391                                    currentBranchTrigger.next().removeAttr('checked');
392                                    currentBranchTrigger.removeProp('checked');
393                                    currentBranchTrigger.next().removeProp('checked');
394
395                                    currentBranch.find('list > listitem div > .HTML5-Tree-Trigger:checked').attr('ignoreDefaultBehavior', true).click();
396                                }
397                            }
398
399
400
401                            try {
402                                console.log('   checking parents branch... ');
403
404                                var currentParentBranch = currentBranch.closest('list').closest('listitem');
405                                var currentParentBranchTrigger = currentParentBranch.find('>div>input');
406                                var parentBranchHasCheckedItems = (currentParentBranch.find('list [checked]').length > 0);
407                                var parentBranchIsChecked = currentParentBranchTrigger.prop('checked');
408
409                                console.log('branchIsChecked? ' + parentBranchIsChecked + ' hasCheckedItems? ' + parentBranchHasCheckedItems + ' ' + currentParentBranch.attr('id'));
410
411                                if (parentBranchHasCheckedItems) {
412                                    if (!parentBranchIsChecked) {
413
414                                        currentParentBranchTrigger.attr('ignoreDefaultBehavior', true);
415                                        currentParentBranchTrigger.click();
416                                    }
417                                } else {
418                                    if (parentBranchIsChecked) {
419
420                                        currentParentBranchTrigger.attr('ignoreDefaultBehavior', true);
421                                        currentParentBranchTrigger.click();
422                                    }
423                                }
424                            } catch (ex) {
425                                console.log(ex.message);
426                            }
427
428
429                            currentBranchTrigger.removeAttr('ignoreDefaultBehavior');
430
431                        } catch (ex) {
432                            console.log(ex.message);
433                        }
434
435                        if ($.browser == null) { $.browser = {}; }
436                        if ($.browser.chrome == null) { $.browser.chrome = /chrom(e|ium)/.test(navigator.userAgent.toLowerCase()); }
437                        if ($.browser.chrome) {
438
439
440                            try {
441                                $(this).closest('div[json].HTML5-Root-Tree').css('display', 'contents');
442
443                            } catch (ex) { console.log(ex.message); }
444                        }
445                    });
446                    showPleaseWait({ visible: false });
447                }
448
449                console.log('Binding additional LEAF click event ... ');
450                if (myPlugin.element.find('.HTML5-Tree-Leaf').length > 0) {
451                    myPlugin.element.find('.HTML5-Tree-Leaf').click(function (item) {
452                        showPleaseWait({ visible: true });
453                        try {
454                            var currentLeaf = $(this);
455                            var currentLeafTrigger = currentLeaf.find('>div>input');
456                            var isLeafChecked = currentLeafTrigger.is(':checked');
457                            console.log('   LEAF ' + currentLeaf.attr('id') + ' isChecked? ' + isLeafChecked);
458
459                            var ignoreDefaultBehavior = (currentLeafTrigger.attr('ignoreDefaultBehavior') || false);
460
461                            console.log('   LEAF ignoreDefaultBehavior? ' + ignoreDefaultBehavior)
462                            if (isLeafChecked) {
463
464                                currentLeaf.attr('checked', 'checked');
465                                currentLeaf.next().attr('checked', 'checked');
466                                currentLeaf.prop('checked', 'checked');
467                                currentLeaf.next().prop('checked', 'checked');
468
469                                currentLeafTrigger.attr('checked', 'checked');
470                                currentLeafTrigger.next().attr('checked', 'checked');
471                                currentLeafTrigger.prop('checked', 'checked');
472                                currentLeafTrigger.next().prop('checked', 'checked');
473                            } else {
474
475                                currentLeaf.removeAttr('checked');
476                                currentLeaf.next().removeAttr('checked');
477                                currentLeaf.removeProp('checked');
478                                currentLeaf.next().removeProp('checked');
479
480                                currentLeafTrigger.removeAttr('checked');
481                                currentLeafTrigger.next().removeAttr('checked');
482                                currentLeafTrigger.removeProp('checked');
483                                currentLeafTrigger.next().removeProp('checked');
484                            }
485
486                            try {
487
488                                if (!ignoreDefaultBehavior) {
489                                    console.log('checking parents branch... ');
490
491                                    var currentParentBranch = currentLeaf.closest('list').closest('listitem');
492                                    var currentParentBranchTrigger = currentParentBranch.find('>div>input');
493                                    var parentBranchHasCheckedItems = (currentParentBranch.find('list [checked]').length > 0);
494                                    var parentBranchIsChecked = currentParentBranchTrigger.prop('checked');
495
496                                    console.log('branchIsChecked? ' + parentBranchIsChecked + ' hasCheckedItems? ' + parentBranchHasCheckedItems + ' ' + currentParentBranch.attr('id'));
497
498                                    if ((isLeafChecked && !parentBranchIsChecked) || (parentBranchHasCheckedItems && !parentBranchIsChecked)) {
499                                        if (!parentBranchIsChecked) {
500
501                                            currentParentBranchTrigger.attr('ignoreDefaultBehavior', true);
502                                            currentParentBranchTrigger.click();
503                                        }
504                                    }
505
506                                    if (!parentBranchHasCheckedItems && parentBranchIsChecked) {
507                                        if (parentBranchIsChecked) {
508
509                                            currentParentBranchTrigger.attr('ignoreDefaultBehavior', true);
510                                            currentParentBranchTrigger.click();
511                                        }
512                                    }
513                                }
514                            } catch (ex) {
515                                console.log(ex.message);
516                            }
517
518                            currentLeafTrigger.removeAttr('ignoreDefaultBehavior');
519                        } catch (ex) {
520                            console.log(ex.message);
521                        }
522                        showPleaseWait({ visible: false });
523                    });
524                }
525                console.log('Plugin-Tree ended...');
526            } catch (ex) {
527                console.log(ex.message);
528            }
529        };
530
531    } catch (ex) {
532        console.log(ex.message);
533    }
534    return myPlugin;
535}
536
537function setupTrees(root, currentTree) {
538    try {
539        var thisTreePlugin = currentTree.treePlugin();
540
541        var data = {};
542        data = JSON.parse(thisTreePlugin.element.attr('json').replace(/'/g, '"'));
543
544        var dfbhtml5Id = thisTreePlugin.element.attr('dfbhtml5-id');
545
546        var options = {
547            data: data.root[0],
548            formId: dfbhtml5Id,
549            options: {
550                initialStart: true
551            }
552        };
553
554        thisTreePlugin.createUI(options);
555        thisTreePlugin.init();
556
557
558        thisTreePlugin.element.removeAttr('orphan');
559        $(thisTreePlugin.element.children()[0]).hide();
560
561        currentTree.find('[event*=detectchange]').change(function () {
562            try {
563                $(this).attr('changeDetected', 'true');
564            } catch (ex) { console.log(ex.message); }
565        });
566
567        setTimeout(function () { expandAll() }, 250);
568    } catch (ex) {
569        console.log(ex.message);
570    }
571}
572
573
574function expandAll() {
575    var result = false;
576    try {
577        $('.HTML5-Tree-Trigger:checked').prev().each(function () {
578            try {
579                var ele = $(this)
580                var classes = ele.attr('class').toLowerCase();
581                var isExpandable = (classes.indexOf('fa-plus') > -1);
582                var isCollapsable = (classes.indexOf('fa-minus') > -1);
583                var isBranchExpander = (isExpandable || isCollapsable);
584
585                result = isExpandable ? true : result;
586                if (isBranchExpander) {
587                    console.log('isBranchExpander? ' + isBranchExpander + '; isExpandable? ' + isExpandable + '; isCollapsable? ' + isCollapsable)
588                    if (isExpandable) { ele.click() } else { console.log('		-> Cannot expand anything ... '); }
589                }
590            } catch (ex) { console.log(ex.message); }
591        });
592
593        if (result) { setTimeout(function () { expandAll() }, 250); }
594    } catch (ex) { console.log(ex.message); }
595    return result;
596}

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.