PageSourceSearch

https://hoaphuong.gov.vn/assets/js/app.js

js hoaphuong.gov.vn collected 2026-09-28 18:02:06 UTC 27,565 bytes, 700 lines download raw bytes

1/* ------------------------------------------------------------------------------
2 *
3 *  # Template JS core
4 *
5 *  Includes minimum required JS code for proper template functioning
6 *
7 * ---------------------------------------------------------------------------- */
8
9
10// Setup module
11// ------------------------------
12
13const App = function () {
14
15
16    // Utils
17    // -------------------------
18
19    //
20    // Transitions
21    //
22
23    // Disable all transitions
24    const transitionsDisabled = function() {
25        document.body.classList.add('no-transitions');
26    };
27
28    // Enable all transitions
29    const transitionsEnabled = function() {
30        document.body.classList.remove('no-transitions');
31    };
32
33
34    //
35    // Detect OS to apply custom scrollbars
36    //
37
38    // Custom scrollbar style is controlled by CSS. This function is needed to keep default
39    // scrollbars on MacOS and avoid usage of extra JS libraries
40    const detectOS = function() {
41        const platform = window.navigator.platform,
42              windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'],
43              customScrollbarsClass = 'custom-scrollbars';
44
45        // Add class if OS is windows
46        windowsPlatforms.indexOf(platform) != -1 && document.documentElement.classList.add(customScrollbarsClass);
47    };
48
49
50
51    // Sidebars
52    // -------------------------
53
54    //
55    // On desktop
56    //
57
58    // Resize main sidebar
59    const sidebarMainResize = function() {
60
61        // Elements
62        const sidebarMainElement = document.querySelector('.sidebar-main'),
63              sidebarMainToggler = document.querySelectorAll('.sidebar-main-resize'),
64              resizeClass = 'sidebar-main-resized',
65              unfoldClass = 'sidebar-main-unfold';
66
67
68        // Config
69        if (sidebarMainElement) {
70
71            // Define variables
72            const unfoldDelay = 150;
73            let timerStart,
74                timerFinish;
75
76            // Toggle classes on click
77            sidebarMainToggler.forEach(function(toggler) {
78                toggler.addEventListener('click', function(e) {
79                    e.preventDefault();
80                    sidebarMainElement.classList.toggle(resizeClass);
81                    !sidebarMainElement.classList.contains(resizeClass) && sidebarMainElement.classList.remove(unfoldClass);
82                });                
83            });
84
85            // Add class on mouse enter
86            sidebarMainElement.addEventListener('mouseenter', function() {
87                clearTimeout(timerFinish);
88                timerStart = setTimeout(function() {
89                    sidebarMainElement.classList.contains(resizeClass) && sidebarMainElement.classList.add(unfoldClass);
90                }, unfoldDelay);
91            });
92
93            // Remove class on mouse leave
94            sidebarMainElement.addEventListener('mouseleave', function() {
95                clearTimeout(timerStart);
96                timerFinish = setTimeout(function() {
97                    sidebarMainElement.classList.remove(unfoldClass);
98                }, unfoldDelay);
99            });
100        }
101    };
102
103    // Toggle main sidebar
104    const sidebarMainToggle = function() {
105
106        // Elements
107        const sidebarMainElement = document.querySelector('.sidebar-main'),
108              sidebarMainRestElements = document.querySelectorAll('.sidebar:not(.sidebar-main):not(.sidebar-component)'),
109              sidebarMainDesktopToggler = document.querySelectorAll('.sidebar-main-toggle'),
110              sidebarMainMobileToggler = document.querySelectorAll('.sidebar-mobile-main-toggle'),
111              sidebarCollapsedClass = 'sidebar-collapsed',
112              sidebarMobileExpandedClass = 'sidebar-mobile-expanded';
113
114        // On desktop
115        sidebarMainDesktopToggler.forEach(function(toggler) {
116            toggler.addEventListener('click', function(e) {
117                e.preventDefault();
118                sidebarMainElement.classList.toggle(sidebarCollapsedClass);
119            });                
120        });
121
122        // On mobile
123        sidebarMainMobileToggler.forEach(function(toggler) {
124            toggler.addEventListener('click', function(e) {
125                e.preventDefault();
126                sidebarMainElement.classList.toggle(sidebarMobileExpandedClass);
127
128                sidebarMainRestElements.forEach(function(sidebars) {
129                    sidebars.classList.remove(sidebarMobileExpandedClass);
130                });
131            });                
132        });
133    };
134
135    // Toggle secondary sidebar
136    const sidebarSecondaryToggle = function() {
137
138        // Elements
139        const sidebarSecondaryElement = document.querySelector('.sidebar-secondary'),
140              sidebarSecondaryRestElements = document.querySelectorAll('.sidebar:not(.sidebar-secondary):not(.sidebar-component)'),
141              sidebarSecondaryDesktopToggler = document.querySelectorAll('.sidebar-secondary-toggle'),
142              sidebarSecondaryMobileToggler = document.querySelectorAll('.sidebar-mobile-secondary-toggle'),
143              sidebarCollapsedClass = 'sidebar-collapsed',
144              sidebarMobileExpandedClass = 'sidebar-mobile-expanded';
145
146        // On desktop
147        sidebarSecondaryDesktopToggler.forEach(function(toggler) {
148            toggler.addEventListener('click', function(e) {
149                e.preventDefault();
150                sidebarSecondaryElement.classList.toggle(sidebarCollapsedClass);
151            });                
152        });
153
154        // On mobile
155        sidebarSecondaryMobileToggler.forEach(function(toggler) {
156            toggler.addEventListener('click', function(e) {
157                e.preventDefault();
158                sidebarSecondaryElement.classList.toggle(sidebarMobileExpandedClass);
159
160                sidebarSecondaryRestElements.forEach(function(sidebars) {
161                    sidebars.classList.remove(sidebarMobileExpandedClass);
162                });
163            });                
164        });
165    };
166
167    // Toggle right sidebar
168    const sidebarRightToggle = function() {
169
170        // Elements
171        const sidebarRightElement = document.querySelector('.sidebar-end'),
172              sidebarRightRestElements = document.querySelectorAll('.sidebar:not(.sidebar-end):not
172(.sidebar-component)'),
173              sidebarRightDesktopToggler = document.querySelectorAll('.sidebar-end-toggle'),
174              sidebarRightMobileToggler = document.querySelectorAll('.sidebar-mobile-end-toggle'),
175              sidebarCollapsedClass = 'sidebar-collapsed',
176              sidebarMobileExpandedClass = 'sidebar-mobile-expanded';
177
178        // On desktop
179        sidebarRightDesktopToggler.forEach(function(toggler) {
180            toggler.addEventListener('click', function(e) {
181                e.preventDefault();
182                sidebarRightElement.classList.toggle(sidebarCollapsedClass);
183            });                
184        });
185
186        // On mobile
187        sidebarRightMobileToggler.forEach(function(toggler) {
188            toggler.addEventListener('click', function(e) {
189                e.preventDefault();
190                sidebarRightElement.classList.toggle(sidebarMobileExpandedClass);
191
192                sidebarRightRestElements.forEach(function(sidebars) {
193                    sidebars.classList.remove(sidebarMobileExpandedClass);
194                });
195            });                
196        });
197    };
198
199    // Toggle component sidebar
200    const sidebarComponentToggle = function() {
201
202        // Elements
203        const sidebarComponentElement = document.querySelector('.sidebar-component'),
204              sidebarComponentMobileToggler = document.querySelectorAll('.sidebar-mobile-component-toggle'),
205              sidebarMobileExpandedClass = 'sidebar-mobile-expanded';
206
207        // Toggle classes
208        sidebarComponentMobileToggler.forEach(function(toggler) {
209            toggler.addEventListener('click', function(e) {
210                e.preventDefault();
211                sidebarComponentElement.classList.toggle(sidebarMobileExpandedClass);
212            });                
213        });
214    };
215
216
217    // Navigations
218    // -------------------------
219
220    // Sidebar navigation
221    const navigationSidebar = function() {
222
223        // Elements
224        const navContainerClass = 'nav-sidebar',
225              navItemOpenClass = 'nav-item-open',
226              navLinkClass = 'nav-link',
227              navLinkDisabledClass = 'disabled',
228              navSubmenuContainerClass = 'nav-item-submenu',
229              navSubmenuClass = 'nav-group-sub',
230              navScrollSpyClass = 'nav-scrollspy',
231              sidebarNavElement = document.querySelectorAll(`.${navContainerClass}:not(.${navScrollSpyClass})`);
232
233        // Setup
234        sidebarNavElement.forEach(function(nav) {
235            nav.querySelectorAll(`.${navSubmenuContainerClass} > .${navLinkClass}:not(.${navLinkDisabledClass})`).forEach(function(link) {
236                link.addEventListener('click', function(e) {
237                    e.preventDefault();
238                    const submenuContainer = link.closest(`.${navSubmenuContainerClass}`);
239                    const submenu = link.closest(`.${navSubmenuContainerClass}`).querySelector(`:scope > .${navSubmenuClass}`);
240
241                    // Collapsible
242                    if(submenuContainer.classList.contains(navItemOpenClass)) {
243                        new bootstrap.Collapse(submenu).hide();
244                        submenuContainer.classList.remove(navItemOpenClass);
245                    }
246                    else {
247                        new bootstrap.Collapse(submenu).show();
248                        submenuContainer.classList.add(navItemOpenClass);
249                    }
250
251                    // Accordion
252                    if (link.closest(`.${navContainerClass}`).getAttribute('data-nav-type') == 'accordion') {
253                        for (let sibling of link.parentNode.parentNode.children) {
254                            if (sibling != link.parentNode && sibling.classList.contains(navItemOpenClass)) {
255                                sibling.querySelectorAll(`:scope > .${navSubmenuClass}`).forEach(function(submenu) {
256                                    new bootstrap.Collapse(submenu).hide();
257                                    sibling.classList.remove(navItemOpenClass);
258                                });
259                            }
260                        }
261                    }
262                });
263            });
264        });
265    };
266
267
268    // Components
269    // -------------------------
270
271    // Tooltip
272    const componentTooltip = function() {
273        const tooltipSelector = document.querySelectorAll('[data-bs-popup="tooltip"]');
274
275        tooltipSelector.forEach(function(popup) {
276            new bootstrap.Tooltip(popup, {
277                boundary: '.page-content'
278            });
279        });
280    };
281
282    // Popover
283    const componentPopover = function() {
284        const popoverSelector = document.querySelectorAll('[data-bs-popup="popover"]');
285
286        popoverSelector.forEach(function(popup) {
287            new bootstrap.Popover(popup, {
288                boundary: '.page-content'
289            });
290        });
291    };
292
293    // "Go to top" button
294    const componentToTopButton = function() {
295
296        // Elements
297        const toTopContainer = document.querySelector('.content-wrapper'),
298              toTopElement = document.createElement('button'),
299              toTopElementIcon = document.createElement('i'),
300              toTopButtonContainer = document.createElement('div'),
301              toTopButtonColorClass = 'btn-secondary',
302              toTopButtonIconClass = 'ph-arrow-up',
303              scrollableContainer = document.querySelector('.content-inner'),
304              scrollableDistance = 250,
305              footerContainer = document.querySelector('.navbar-footer');
306
307
308        // Append only if container exists
309        if (scrollableContainer) {
310
311            // Create button container
312            toTopContainer.appendChild(toTopButtonContainer);
313            toTopButtonContainer.classList.add('btn-to-top');
314
315            // Create button
316            toTopElement.classList.add('btn', toTopButtonColorClass, 'btn-icon', 'rounded-pill');
317            toTopElement.setAttribute('type', 'button');
318            toTopButtonContainer.appendChild(toTopElement);
319            toTopElementIcon.classList.add(toTopButtonIconClass);
320            toTopElement.appendChild(toTopElementIcon);
321
322            // Show and hide on scroll
323            const to_top_button = document.querySelector('.btn-to-top'),
324                  add_class_on_scroll = () => to_top_button.classList.add('btn-to-top-visible'),
325                  remove_class_on_scroll = () => to_top_button.classList.remove('btn-to-top-visible');
326
327            scrollableContainer.addEventListener('scroll', function() { 
328                const scrollpos = scrollableContainer.scrollTop;
329                scrollpos >= scrollableDistance ? add_class_on_scroll() : remove_class_on_scroll();
330                if(footerContainer) {
331                    if (this.scrollHeight - this.scrollTop - this.clientHeight <= footerContainer.clientHeight) {
332                        to_top_button.style.bottom = footerContainer.clientHeight + 20 + 'px';
333                    }
334                    else {
335                        to_top_button.removeAttribute('style');
336                    }
337                }
338            });
339
340            // Scroll to top on click
341            document.querySelector('.btn-to-top .btn').addEventListener('click', function() {
342                scrollableContainer.scrollTo(0, 0);
343            });
344        }
345    };
346
347
348    // Card actions
349    // -------------------------
350
351    // Reload card (uses BlockUI extension)
352    const cardActionReload = function() {
353
354        // Elements
355        const buttonClass = '[data-card-action=reload]',
356              containerClass = 'card',
357              overlayClass = 'card-overlay',
358              spinnerClass = 'ph-circle-notch',
359              overlayAnimationClass = 'card-overlay-fadeout';
360
361        // Configure
362        document.querySelectorAll(buttonClass).forEach(function(button) {
363            button.addEventListener('click', function(e) {
364                e.preventDefault();
365
366                // Elements
367                const parentContainer = button.closest(`.${containerClass}`),
368                      overlayElement = document.createElement('div'),
369                      overlayElementIcon = document.createElement('i');
370
371                // Append overlay with icon
372                overlayElement.classList.add(overlayClass);
373                parentContainer.appendChild(overlayElement);
374                overlayElementIcon.classList.add(spinnerClass, 'spinner', 'text-body');
375                overlayElement.appendChild(overlayElementIcon);
376
377                // Remove overlay after 2.5s, for demo only
378                setTimeout(function() {
379                    overlayElement.classList.add(overlayAnimationClass);
380                    ['animationend', 'animationcancel'].forEach(function(e) {
381                        overlayElement.addEventListener(e, function() {
382                            overlayElement.remove();
383                        });
384                    });
385                }, 2500);
386            });
387        });
388    };
389
390    // Collapse card
391    const cardActionCollapse = function() {
392
393        // Elements
394        const buttonClass = '[data-card-action=collapse]',
395              cardCollapsedClass = 'card-collapsed';
396
397        // Setup
398        document.querySelectorAll(buttonClass).forEach(function(button) {
399            button.addEventListener('click', function(e) {
400                e.preventDefault();
401
402                const parentContainer = button.closest('.card'),
403                      collapsibleContainer = parentContainer.querySelectorAll(':scope > .collapse');
404
405                if (parentContainer.classList.contains(cardCollapsedClass)) {
406                    parentContainer.classList.remove(cardCollapsedClass);
407                    collapsibleContainer.forEach(function(toggle) {
408                        new bootstrap.Collapse(toggle, {
409                            show: true
410                        });
411                    });
412                }
413                else {
414                    parentContainer.classList.add(cardCollapsedClass);
415                    collapsibleContainer.forEach(function(toggle) {
416                        new bootstrap.Collapse(toggle, {
417                            hide: true
418                        });
419                    });
420                }
421            });
422        });
423    };
424
425    // Remove card
426    const cardActionRemove = function() {
427
428        // Elements
429        const buttonClass = '[data-card-action=remove]',
430              containerClass = 'card'
431
432        // Config
433        document.querySelectorAll(buttonClass).forEach(function(button) {
434            button.addEventListener('click', function(e) {
435                e.preventDefault();
436                button.closest(`.${containerClass}`).remove();
437            });
438        });
439    };
440
441    // Card fullscreen mode
442    const cardActionFullscreen = function() {
443
444        // Elements
445        const buttonAttribute = '[data-card-action=fullscreen]',
446              buttonClass = 'text-body',
447              buttonContainerClass = 'd-inline-flex',
448              cardFullscreenClass = 'card-fullscreen',
449              collapsedClass = 'collapsed-in-fullscreen',
450              scrollableContainerClass = 'content-inner',
451              fullscreenAttr = 'data-fullscreen';
452
453        // Configure
454        document.querySelectorAll(buttonAttribute).forEach(function(button) {
455            button.addEventListener('click', function(e) {
456                e.preventDefault();
457
458                // Get closest card container
459                const cardFullscreen = button.closest('.card');
460
461                // Toggle required classes
462                cardFullscreen.classList.toggle(cardFullscreenClass);
463
464                // Toggle classes depending on state
465                if (!cardFullscreen.classList.contains(cardFullscreenClass)) {
466                    button.removeAttribute(fullscreenAttr);
467                    cardFullscreen.querySelectorAll(`:scope > .${collapsedClass}`).forEach(function(collapsedElement) {
468                        collapsedElement.classList.remove('show');
469                    });
470                    document.querySelector(`.${scrollableContainerClass}`).classList.remove('overflow-hidden');
471                    button.closest(`.${buttonContainerClass}`).querySelectorAll(`:scope > .${buttonClass}:not(${buttonAttribute})`).forEach(function(actions) {
472                        actions.classList.remove('d-none');
473                    });
474                }
475                else {
476                    button.setAttribute(fullscreenAttr, 'active');
477                    cardFullscreen.removeAttribute('style');
478                    cardFullscreen.querySelectorAll(`:scope > .collapse:not(.show)`).forEach(function(collapsedElement) {
479                        collapsedElement.classList.add('show', `.${collapsedClass}`);
480                    });
481                    document.querySelector(`.${scrollableContainerClass}`).classList.add('overflow-hidden');
482                    button.closest(`.${buttonContainerClass}`).querySelectorAll(`:scope > .${buttonClass}:not(${buttonAttribute})`).forEach(function(actions) {
483                        actions.classList.add('d-none');
484                    });
485                }
486            });
487        });
488    };
489
490
491    // Misc
492    // -------------------------
493
494    // Dropdown submenus. Trigger on click
495    const dropdownSubmenu = function() {
496
497        // Classes
498        const menuClass = 'dropdown-menu',
499              submenuClass = 'dropdown-submenu',
500              menuToggleClass = 'dropdown-toggle',
501              disabledClass = 'disabled',
502              showClass = 'show';
503
504        if(submenuClass) {
505
506            // Toggle submenus on all levels
507            document.querySelectorAll(`.${menuClass} .${submenuClass}:not(.${disabledClass}) .${menuToggleClass}`).forEach(function(link) {
508                link.addEventListener('click', function(e) {
509                    e.stopPropagation();
510                    e.preventDefault();
511
512                    // Toggle classes
513                    link.closest(`.${submenuClass}`).classList.toggle(showClass);
514                    link.closest(`.${submenuClass}`).querySelectorAll(`:scope > .${menuClass}`).forEach(function(children) {
515                        children.classList.toggle(showClass);
516                    });
517
518                    // When submenu is shown, hide others in all siblings
519                    for (let sibling of link.parentNode.parentNode.children) {
520                        if (sibling != link.parentNode) {
521                            sibling.classList.remove(showClass);
522                            sibling.querySelectorAll(`.${showClass}`).forEach(function(submenu) {
523                                submenu.classList.remove(showClass);
524                            });
525                        }
526                    }
527                });
528            });
529
530            // Hide all levels when parent dropdown is closed
531            document.querySelectorAll(`.${menuClass}`).forEach(function(link) {
532                if(!link.parentElement.classList.contains(submenuClass)) {
533                    link.parentElement.addEventListener('hidden.bs.dropdown', function(e) {
534                        link.querySelectorAll(`.${menuClass}.${showClass}`).forEach(function(children) {
535                            children.classList.remove(showClass);
536                        });
537                    });
538                }
539            });
540        }
541    };
542
543
544
545    //
546    // Return objects assigned to module
547    //
548
549    return {
550
551        // Disable transitions before page is fully loaded
552        initBeforeLoad: function() {
553            detectOS();
554            transitionsDisabled();
555        },
556
557        // Enable transitions when page is fully loaded
558        initAfterLoad: function() {
559            transitionsEnabled();
560        },
561        // Initialize all components
562        initComponents: function() {
563            componentTooltip();
564            componentPopover();
565            componentToTopButton();
566        },
567
568        // Initialize all sidebars
569        initSidebars: function() {
570            sidebarMainResize();
571            sidebarMainToggle();
572            sidebarSecondaryToggle();
573            sidebarRightToggle();
574            sidebarComponentToggle();
575        },
576
577        // Initialize all navigations
578        initNavigations: function() {
579            navigationSidebar();
580        },
581
582        // Initialize all card actions
583        initCardActions: function() {
584            cardActionReload();
585            cardActionCollapse();
586            cardActionRemove();
587            cardActionFullscreen();
588        },
589
590        // Dropdown submenu
591        initDropdowns: function() {
592            dropdownSubmenu();
593        },
594
595        // Initialize core
596        initCore: function() {
597            App.initBeforeLoad();
598            App.initSidebars();
599            App.initNavigations();
600            App.initComponents();
601            App.initCardActions();
602            App.initDropdowns();
603        }
604    };
605}();
606
607
608
609// Initialize module
610// ------------------------------
611function ChonMenu(menu) {
612    $("#_NavMenu li.nav-item a.nav-link").removeClass('active');
613    $("#_NavMenu li.nav-item a.nav-link[href='" + menu + "']").addClass('active');
614
615    $("#_NavMenu").find("li[class*='nav-item-submenu']").removeClass('nav-item-expanded');
616    $("#_NavMenu").find("li[class*='nav-item-submenu']").removeClass('nav-item-open');
617    $("#_NavMenu").find("ul[class*='nav-group-sub']").attr('style', 'display:none');
618
619    var _class = $("#_NavMenu li.nav-item a.nav-link[href='" + menu + "']").parent().parent().parent().attr('class');
620    if (_class === undefined) return;
621    if (_class.toString().indexOf("nav-item-submenu") >= 0) {
622        $("#_NavMenu li.nav-item a.nav-link[href='" + menu + "']").parent().parent().parent().addClass("nav-item-expanded");
623        $("#_NavMenu li.nav-item a.nav-link[href='" + menu + "']").parent().parent().parent().addClass("nav-item-open");
624        $("#_NavMenu li.nav-item a.nav-link[href='" + menu + "']").parent().parent().attr('style', 'display:block');
625    }
626
627    if (getWidth() < 1000) {
628        if ($('body').hasClass('sidebar-xs') === true) {
629            $('body').removeClass('sidebar-xs');
630        }
631
632        if ($('body').hasClass('sidebar-mobile-main') === true) {
633            $('body').removeClass('sidebar-mobile-main');
634        }
635        //sidebar-mobile-main
636    }
637
638}
639
640function getWidth() {
641    return Math.max(
642        document.body.scrollWidth,
643        document.documentElement.scrollWidth,
644        document.body.offsetWidth,
645        document.documentElement.offsetWidth,
646        document.documentElement.clientWidth
647    );
648}
649
650function KhoiTaoApp() {
651
652    if (localStorage.getItem('sidebarType') != null) {
653        $('body').addClass(localStorage.getItem('sidebarType'));
654    }
655
656    App.initBeforeLoad();
657    App.initCore();
658    App.initAfterLoad();
659    // FixedSidebarCustomScroll.init();
660}
661
662// Initialize module
663// ------------------------------
664
665// When content is loaded
666document.addEventListener('DOMContentLoaded', function() {
667    App.initCore();
668});
669
670// When page is fully loaded
671window.addEventListener('load', function() {
672    App.initAfterLoad();
673});
674
675function toggleFullScreen() {
676
677    var elem = document.body;
678    // ## The below if statement seems to work better ## if ((document.fullScreenElement && document.fullScreenElement !== null) || (document.msfullscreenElement && document.msfullscreenElement !== null) || (!document.mozFullScreen && !document.webkitIsFullScreen)) {
679    if ((document.fullScreenElement !== undefined && document.fullScreenElement === null) || (document.msFullscreenElement !== undefined && document.msFullscreenElement === null) || (document.mozFullScreen !== undefined && !document.mozFullScreen) || (document.webkitIsFullScreen !== undefined && !document.webkitIsFullScreen)) {
680        if (elem.requestFullScreen) {
681            elem.requestFullScreen();
682        } else if (elem.mozRequestFullScreen) {
683            elem.mozRequestFullScreen();
684        } else if (elem.webkitRequestFullScreen) {
685            elem.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
686        } else if (elem.msRequestFullscreen) {
687            elem.msRequestFullscreen();
688        }
689    } else {
690        if (document.cancelFullScreen) {
691            document.cancelFullScreen();
692        } else if (document.mozCancelFullScreen) {
693            document.mozCancelFullScreen();
694        } else if (document.webkitCancelFullScreen) {
695            document.webkitCancelFullScreen();
696        } else if (document.msExitFullscreen) {
697            document.msExitFullscreen();
698        }
699    }
700}

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.