PageSourceSearch

https://www.ispsystem.ru/docs/assets/js/custom.js?1790577963

js ispsystem.ru collected 2026-10-02 04:57:02 UTC 56,010 bytes, 1,283 lines download raw bytes

1function include(url) {
2    var script = document.createElement('script');
3    script.src = url;
4    document.getElementsByTagName('head')[0].appendChild(script);
5}
6
7function setCookie(name, value, expires = 1, path = '/', expExact = 0) {
8    let max_age;
9    if (expExact > 0)
10        max_age = expExact;
11    else
12        max_age = 86400 * expires // по умолчанию - сутки
13    document.cookie = encodeURIComponent(name) + "=" + (encodeURIComponent(value) || "") + "; path=" + path + '; max-age=' + max_age + ';secure';
14}
15
16function deleteCookie(name) {
17    document.cookie = name + "=''; max-age=-1;";
18}
19
20function escapeHtml(text) {
21    var map = {
22      '&': '&',
23      '<': '&lt;',
24      '>': '&gt;',
25      '"': '&quot;',
26      "'": '&#039;'
27    };
28
29    return text.replace(/[&<>"']/g, function(m) { return map[m]; });
30}
31
32function getUpdatedUrl(url,direction) {
33    const urlParams = new URLSearchParams(new URL(url).search);
34    const p = parseInt(urlParams.get('p'));
35    if(direction === 'prev')
36        urlParams.set('p', p - 1);
37    else
38        urlParams.set('p', p + 1);
39    const updatedUrl = new URL(url);
40    updatedUrl.search = urlParams.toString();
41    return updatedUrl.toString();
42}
43
44// извлечение версии
45function extractVersion(ver) {
46    const match = ver.match(/v(\d+\.\d+(?:\.\d+)?)/i);
47    return match ? match[1] : null;
48}
49
50// извлечение названия раздела из URL
51function extractSectionName(url) {
52    const match = url.match(/\/docs\/([^\/]+)/);
53    return match ? match[1] : '';
54}
55
56const versionSelect = document.querySelector('.version-select');
57
58if (versionSelect) {
59    versionSelect.addEventListener('change', function() {
60        if (this.value) {
61            const selectedOption = this.options[this.selectedIndex];
62            const version = selectedOption.textContent.trim();
63
64            if (version) {
65                const s = extractSectionName(selectedOption.value); // имя пространства
66                setCookie('ver_'+s, version);
67            }
68
69            // Переходим на выбранную страницу
70            window.location.href = this.value;
71        }
72    });
73
74    // При загрузке страницы проверяем и сохраняем текущую версию
75    const selectedOption = versionSelect.options[versionSelect.selectedIndex];
76    if (selectedOption && selectedOption.value) {
77        const currentVersion = extractVersion(selectedOption.textContent.trim());
78        if (currentVersion) {
79            const s = extractSectionName(selectedOption.value); // имя пространства
80            setCookie('ver_'+s, currentVersion);
81        }
82    }
83}
84
85
86var d = new Date();
87var dt = d.getTime();
88var domainUpper = document.querySelector('html').attributes.hasOwnProperty('lang') && document.querySelector('html').attributes.lang.value == 'ru' ? 'ru' : 'com';
89include(`https://www.ispsystem.${domainUpper}/sites/all/themes/ispsystem/scripts/libraries/analyt.js?${dt}`);
90
91function trackPageVisit() {
92    const currentUrl = window.location.pathname;
93    const articleName = $('h1').text();
94
95        let visits = JSON.parse(localStorage.getItem('visitedPages')) || [];
96
97        const existingIndex = visits.findIndex(v => v.url === currentUrl);
98        if (existingIndex !== -1) {
99            visits[existingIndex].count += 1;
100        } else {
101            visits.push({ url: currentUrl, name: articleName, count: 1 });
102        }
103
104        visits = visits.filter(item => item.name !== '');
105        visits = visits.filter(item => $.trim(item.name) !== '404 - Страница не найдена');
106        visits = visits.filter(item => $.trim(item.name) !== '404 - Not found');
107        visits.sort((a, b) => b.count - a.count);
108        localStorage.setItem('visitedPages', JSON.stringify(visits));
109}
110
111function addToFavorites(pid, _this, lang) {
112
113    fetch("/docs/api/favorites", {
114        method: 'POST',
115        headers: {
116            'Content-Type': 'application/json'
117        },
118        body: JSON.stringify({
119            action: 'add',
120            pid: pid
121        })
122    })
123    .then(response => response.json())
124    .then(data => {
125        if (!data.hasOwnProperty('error')){
126            const $link = $(_this);
127            const add = lang == 'ru' ? 'Добавить' : 'Add';
128            const rff = lang == 'ru' ? 'Удалить из избранного' : 'Remove from Favorites';
129            const atf = lang == 'ru' ? 'Добавить в избранное' : 'Add to Favorites';
130            if ($link.text().includes(add)) {
131                $link.text(rff);
132                $link.parent().attr('data-t_text',rff);
133                $link.prepend('<svg style="width: 25px; height: 25px;"><use xlink:href="#ff-minus-a"></use></svg>');
134            } else {
135                $link.text(atf);
136                $link.parent().attr('data-t_text',atf);
137                $link.prepend('<svg style="width: 25px; height: 25px;"><use xlink:href="#ff-plus-a"></use></svg>');
138            }
139        }else {
140            if (data.hasOwnProperty('redir')) {
141                location.href = data.redir;
142            }
143        }
144    })
145    .catch(error => console.error('Error:', error));
146}
147
148$(document).ready(function () {
149    let lang = document.querySelector('html').attributes.hasOwnProperty('lang') && document.querySelector('html').attributes.lang.value == 'ru' ? 'ru' : 'en';
150
151    if ($('.sidebar-right').length) trackPageVisit();
152
153    if(localStorage.getItem('visitedPages')) {
154        let visits = JSON.parse(localStorage.getItem('visitedPages'));
155        if (visits.length > 4 ) {
156            let title = lang=='ru'?'Чаще всего вы смотрели':'Most often you visited';
157            let topURLs = `<div class="prev-page-block">${title}:<br><ul>`;
158            for(let i=0; i < 5; i++) {
159                topURLs += `<li><a href="${visits[i].url}">${visits[i].name}</a></li>`;
160            }
161            topURLs += '</ul></div>';
162            $('.sidebar-right').append(topURLs);
163        }
164    }
165
166    if ($('.sidebar-left').length) {
167        let placeholder = lang == 'ru' ? 'Поиск' : 'Search';
168        $('.sidebar-left').prepend(`<input class="searchInTree border border-gray-d9 px-20px py-15px rounded-7 w-full bg-white dark:bg-alm-black" type="text" placeholder="${placeholder}">`);
169
170        $('.searchInTree').on('input', function() {
171            $('.js-sidebar-menu-collapse').addClass('hidden');
172            var searchText = $(this).val().toLowerCase();
173            $('.js-doc-tree:not(.mt-20px) li').each(function() {
174                var $li = $(this);
175
176                $li.find('a').each(function(){
177                    let $a = $(this);
178                    var text = $a.text().toLowerCase();
179
180                    if (text.indexOf(searchText) !== -1) {
181                        $a.closest('li').removeAttr('hidden');
182                        $a.parents('li').find('.-rotate-90').removeClass('-rotate-90');
183                        $a.closest('li').parents('[hidden]').removeAttr('hidden');
184                    } else {
185                        $a.closest('li').attr('hidden', 'hidden');
186                    }
187
188                });
189            });
190
191            if (searchText === '') {
192                $('.js-doc-tree:not(.mt-20px) ul').attr('hidden', 'hidden');
193                $('.js-doc-tree:not(.mt-20px) button:not(.-rotate-90)').addClass('-rotate-90');
194                $('.js-doc-tree:not(.mt-20px) .is-current').parents('[hidden]').removeAttr('hidden');
195                $('.js-doc-tree:not(.mt-20px) .is-current').parents('li').find(' > a > .-rotate-90').removeClass('-rotate-90');
196                if ($('.is-current').length)
197                    $('.js-sidebar-menu-collapse').removeClass('hidden');
198                else {
199                    $('.js-sidebar-menu-collapse').remove();
200                    $('.sidebar-left.expanded').removeClass('expanded');
201                }
202            }
203        });
204    }
205
206    $('body').on('click', '.parent-item-link button', function(e){
207        $(this).toggleClass('-rotate-90');
208        let submenu = $(this).parent().next('ul');
209        let bool=submenu.is(":hidden");
210        submenu.attr('hidden',!bool);
211        let text = lang == 'ru' ? 'Свернуть содержание' : 'Collapse contents';
212        if (submenu.find('> li:not([hidden])').length) {
213            if ($('.sidebar-left .js-doc-tree > li > a > button').length === $('.sidebar-left .js-doc-tree > li > a > button.-rotate-90').length) {
214                $('.js-sidebar-menu-collapse').remove();
215                $('.sidebar-left.expanded').removeClass('expanded');
216            } else {
217                $('.sidebar-left:not(.expanded)').addClass('expanded');
218                if (!$('.js-sidebar-menu-collapse').length && !$('.searchInTree').val().length) {
219                    let menuCollapser = `<button type="button" class="js-sidebar-menu-collapse max-lg:block absolute">${text}</button>`;
220                    $('.page-tree-collapser.new').after(menuCollapser);
221                }
222            }
223            e.stopPropagation();
224            return false;
225        }
226    });
227
228    $('body').on('click', '.parent-item-link', function(e){
229        $(this).find('button').click();
230        return false;
231    });
232
233    $('body').on('click','.js-sidebar-menu-collapse',function(){
234        $('.js-doc-tree:not(.mt-20px) ul').attr('hidden', 'hidden');
235        $('.js-doc-tree:not(.mt-20px) button:not(.-rotate-90)').addClass('-rotate-90');
236        $(this).remove();
237        $('.sidebar-left.expanded').removeClass('expanded');
238        return false;
239    });
240
241    $('body').on('click', '.parent-item-link-mob', function(e){
242        $(this).find('button').click();
243        return false;
244    });
245    $('body').on('click', '.parent-item-link-mob button', function(e){
246        e.stopPropagation();
247    });
248
249    if($('#page .is-current').length){
250        let submenus = $('#page .is-current').parents('ul[hidden]');
251        submenus.each(function(){
252            $(this).prev('a').find('button').click();
253        });
254    }
255
256
257    $('.survey__button').click(function(){
258        setCookie('hide_survey_2', 1, 365);
259        $('.survey').fadeOut(300);
260    });
261
262    if ($('.centercontent').length && $(window).width() > 750) {
263        let selectedText = '';
264        let $menu = $('#selectionMenu');
265
266        // Показать меню при выделении текста
267        $(document).on('mouseup touchend', function(e) {
268            if ($($(e)[0].target).closest('.page').length) {
269                setTimeout(function() {
270                    selectedText = window.getSelection().toString().trim();
271
272                    if (selectedText.length > 0) {
273                        let selection = window.getSelection();
274                        let range = selection.getRangeAt(0);
275                        let rect = range.getBoundingClientRect();
276
277                        // Позиционируем меню над выделенным текстом
278                        let menuWidth = $menu.outerWidth();
279                        let menuHeight = $menu.outerHeight();
280
281                        let top = rect.top + window.scrollY - menuHeight - 10;
282                        let left = rect.left + window.scrollX + (rect.width / 2) - (menuWidth / 2);
283
284                        // Проверяем, чтобы меню не выходило за границы экрана
285                        if (left < 10) left = 10;
286                        if (left + menuWidth > $(window).width() - 10) {
287                            left = $(window).width() - menuWidth - 10;
288                        }
289
290                        $menu.css({
291                            top: top + 'px',
292                            left: left + 'px',
293                            display: 'block'
294                        });
295                    } else {
296                        $menu.hide();
297                    }
298                }, 10);
299            }
300        });
301
302        // Скрыть меню при клике вне его
303        $(document).on('mousedown', function(e) {
304            if (!$(e.target).closest('.selection-menu').length) {
305                if (window.getSelection().toString().trim().length === 0) {
306                    $menu.hide();
307                }
308            }
309        });
310
311        // Кнопка "написать"
312        $('#highlightBtn').on('click', function(e) {
313            e.preventDefault();
314            if (selectedText) {
315                let selection = window.getSelection();
316                if (selection !== '') {
317                    let frm = $('.sidebar-right');
318                    frm.find('.feedback-block__smile.orange input').click();
319                    let wrongText = lang == 'ru' ? 'Текст содержит ошибку' : 'The text contains an error';
320                    const errorText = `${wrongText}: ${selection}`;
321                    frm.find('.feedback-block__form textarea').val(errorText);
322                    frm.find('.feedback-block__form textarea').trigger('input');
323                    $menu.hide();
324                    window.getSelection().removeAllRanges();
325                }
326            }
327        });
328
329        // Кнопка "Найти"
330        $('#searchBtn').on('click', function(e) {
331            e.preventDefault();
332            if (selectedText) {
333                $menu.hide();
334                window.getSelection().removeAllRanges();
335                let sid = $('.breadcrumbs').eq(0).find('.breadcrumbs__item').eq(1).data('sid');
336                let searchUrl = '/docs/search?s='+sid+'&q=' + selectedText.replaceAll(' ','+');
337                window.open(searchUrl, '_blank');
338            }
339        });
340
341        // Кнопка "Копировать"
342        $('#copyBtn').on('click', function(e) {
343            e.preventDefault();
344            if (selectedText) {
345                $menu.hide();
346                window.getSelection().removeAllRanges();
347                navigator.clipboard.writeText(selectedText).then(function() {
348                    alert(`${lang == 'ru' ? 'Текст скопирован в буфер обмена' : 'Text copied to clipboard'}`);
349                    $menu.hide();
350                }).catch(function(err) {
351                    console.error('Copy error: ', err);
352                });
353            }
354        });
355    }
356
357    function sortErrorsList(list,prod) {
358        const headerItem = list.find(`a[href="/docs/${prod}-kb/oshibki/perechen-oshibok"]`).closest("li");
359        headerItem.detach();
360        const sortedItems = list
361            .children("li")
362            .sort(function (a, b) {
363                const numA = parseInt($(a).find("a").attr("href").split("/").pop());
364                const numB = parseInt($(b).find("a").attr("href").split("/").pop());
365                return numA - numB;
366            });
367        list.empty().append(headerItem).append(sortedItems);
368    }
369
370    if (location.pathname.indexOf('manager-kb') != -1) {
371        let prod;
372        if(location.pathname.indexOf('/docs/vmmanager-kb') != -1) prod = 'vmmanager';
373        if(location.pathname.indexOf('/docs/dcimanager-kb') != -1) prod = 'dcimanager';
374        const lists = $('.js-doc-tree').find(`a[href="/docs/${prod}
374-kb/oshibki/perechen-oshibok"]`).closest(".js-children");
375        lists.each(function () {
376            sortErrorsList($(this), prod);
377        });
378    }
379
380    if (location.pathname === '/docs/vmmanager-kb/oshibki' || location.pathname === '/docs/dcimanager-kb/oshibki') {
381        let prod;
382        if(location.pathname.indexOf('/docs/vmmanager-kb')) prod = 'vmmanager';
383        if(location.pathname.indexOf('/docs/dcimanager-kb')) prod = 'dcimanager';
384        sortErrorsList($('.tw-doc-tree'),prod)
385    }
386
387
388
389    if ($('.action-panel').length) {
390        let supportText = 'Написать в техподдержку ISPsystem';
391
392        if(location.pathname.split('/')[2] == 'clouden'){
393            supportText = 'Обратиться в техподдержку';
394        }
395
396
397        $('.action-panel__items').prepend(`
398            <div class="print-page tooltipio" data-t_text="${lang == 'ru' ? 'Распечатать статью' : 'Print article'}" onclick="window.print()">
399                <svg style="width: 20px; height: 20px;"><use xlink:href="#t-print"></use></svg>
400            </div>
401            <div class="support tooltipio" data-t_text="${lang == 'ru' ? supportText : 'Contact ISPsystem tech support'}">
402                <svg style="width: 20px; height: 20px;"><use xlink:href="#m-support"></use></svg>
403            </div>
404        `);
405
406        TooltipIO.reinit();
407
408        $('.action-panel .open-pdf').click(function(){
409            $('body').addClass('pdf');
410            $('.js-spoiler-content').show();
411            const element = document.querySelector('.centercontent article');
412
413            let filename = '';
414            filename += $('.breadcrumbs__item:last').text();
415            let opt = {
416                filename: filename,
417                title:filename,
418                margin:10,
419                // pagebreak:{mode:'avoid-all'},
420                pagebreak:{ mode:'css', avoid: ['.tw-code-block', '.js-spoiler','h2','h3','h4','h5','img','tr']},
421                html2canvas: {dpi: 300, letterRendering: true},
422                jsPDF: {
423                    orientation: 'portrait',
424                    filename: filename,
425                    title:filename
426                }
427            };
428
429            html2pdf()
430                .set(opt)
431                .from(element)
432                .toPdf()
433                .get('pdf')
434                .then((pdf) => {
435                    window.open(pdf.output("bloburl",filename));
436                    $('body').removeClass('pdf');
437                });
438            return false;
439        });
440    }
441
442    $('body').on('click', '.feedback-support-block__form-block .close, #popup-body .close', function(e){
443        $('.overlay').remove();
444        e.stopPropagation();
445        e.preventDefault();
446    });
447
448    $('body').on('submit','.feedback-support-block__form', function(){
449        $('.feedback-support-block__error').remove();
450        const frm = $(this);
451        frm.addClass('wait');
452        frm.find("input[type=email], textarea").each(function() {
453            let sanitizedValue = $(this).val().replace(/[<>\/\\'";]/g, "");
454            frm.val(sanitizedValue);
455        });
456        const link = location.origin+location.pathname;
457        const email = frm.find("input[type=email]").val();
458        const message = frm.find("textarea").val();
459        const subject = frm.find("input[name=subject]").val();
460
461        const formData = new FormData();
462        formData.append('func', 'doc_support');
463        formData.append('link', link);
464        formData.append('email', email);
465        formData.append('message', message);
466        formData.append('lang', lang);
467        formData.append('subject', subject);
468
469        const fileInput = frm.find("input[type=file]")[0];
470        if (fileInput && fileInput.files.length > 0) {
471            formData.append('attachment', fileInput.files[0]);
472        }
473
474        $.ajax({
475            url: '/ajax_api.php',
476            type: 'POST',
477            data: formData,
478            processData: false,  // Обязательно! Иначе jQuery испортит FormData
479            contentType: false,  // Обязательно! Иначе не будет boun
479dary для multipart
480            success: function(response) {
481                let res = JSON.parse(response);
482                if (res['res'] == 'ok') {
483                    $('.feedback-support-block__form-block').html('<div class="close">+</div>'+res['msg']);
484                    $('.bugtracker__response').html('<br><br><div class="bugtracker__comment-result">'+res['msg']+'</div>');
485                } else {
486                    if (res['res'] == 'error')
487                        $('.feedback-block__file').after('<div class="feedback-support-block__error">'+res['msg']+'</div>');
488                        // alert(res['msg']);
489                }
490
491                frm.removeClass('wait');
492            }
493        });
494
495        return false;
496    });
497
498    $('body').on('change', 'input[type=file][name=attachment]', function(e) {
499        const label = $(this).closest('label').find('.feedback-block__file-label');
500        const file = e.target.files[0];
501        if (!file) return;
502
503        const allowedExtensions = [
504            'jpg', 'jpeg', 'png', 'webp',
505            'pdf',
506            'avi', 'mp4', 'mov', 'webm',
507            'har',
508            'log', 'txt',
509            'tar.gz', 'tgz'
510        ];
511
512        const fileName = file.name.toLowerCase();
513
514        if (file) {
515            $('.feedback-support-block__error').remove();
516            const isValid = allowedExtensions.some(ext => fileName.endsWith('.' + ext));
517            const fileNameLen = file.name.length;
518
519            if (!isValid) {
520                const attach = lang == 'ru' ? 'Прикрепить файл' : 'Attach a file';
521                const errorType = lang == 'ru' ? 'Недопустимый тип файла, поддеживаются: .jpg, .jpeg, .png, .webp, .pdf, .avi, .mp4, .mov, .webm, .json, .har, .log, .tar.gz' : 'Invalid file type, supported: .jpg, .jpeg, .png, .webp, .pdf, .avi, .mp4, .webm, .mov, .json, .har, .log, .tar.gz';
522                label.text(attach);
523                $('.feedback-block__file').after('<div class="feedback-support-block__error">'+errorType+'</div>');
524                e.target.value = '';
525            } else {
526                let fileName = this.files[0].name
527                    .replace(/[<>\/\\'";]/g, '')
528                    .substring(0, 20);
529                if (fileNameLen > 20) fileName += '...';
530                label.text(fileName);
531            }
532
533
534        } else {
535            const attach = lang == 'ru' ? 'Прикрепить файл' : 'Attach a file';
536            label.text(attach);
537        }
538    });
539
540
541    Ya.share2('share-block', {
542        hooks: {
543            onready: function () {
544                let s = lang == 'ru' ? 'Поделиться' : 'Share';
545                $('.ya-share2__link_more-button-type_short').addClass('tooltipio');
546                $('.ya-share2__link_more-button-type_short').attr('data-t_text',s);
547                TooltipIO.reinit();
548
549                let bc = '';
550                $('header .breadcrumbs__item').each(function(i){
551                    if (i > 0) {
552                        bc += $.trim($(this).text())+' / ';
553                    }
554                });
555                bc = bc.slice(0,-3);
556                bc = bc.replace(/\s+/g, ' ');
557                let mt = encodeURI(`mailto:?subject=Shared From ISPsystem Documentation: "${bc}"&body=${bc}\nhttps://${location.hostname}${location.pathname}`);
558
559                let shortUrl = $('[itemprop="shortUrl"]').attr('content')
560
561                $('.ya-share2__popup .ya-share2__list').append(`
562                    <li class="ya-share2__item ya-share2__item_copy">
563                        <a class="ya-share2__link ya-share2__link_copy copy_shortlink" href="javascript:void(0);" title="${lang == 'ru' ? 'Скопировать короткую ссылку' : 'Copy short link'}">
564                            <span class="ya-share2__badge ya-share2__badge_copy"><span class="ya-share2__icon ya-share2__icon_copy"></span></span>
565                            <span class="ya-share2__title" style="margin-left: 2px;margin-right: 5px;">${lang == 'ru' ? 'Скопировать короткую ссылку' : 'Copy short link'}</span>
566                        </a>
567                        <input class="ya-share2__input_copy" value="${shortUrl}">
568                    </li>
569                `);
570
571                $('.ya-share2__link_copy.copy_shortlink').click(function(){
572                    const inputForCopy = $(this).next('.ya-share2__input_copy')
573                    const copyText = inputForCopy.val();
574
575                    if (navigator.clipboard) {
576                        navigator.clipboard.writeText(copyText);
577                    } else {
578                        inputForCopy.val().select();
579                        document.execCommand('copy');
580                    }
581                    $('.ya-share2__popup_visible').removeClass('ya-share2__popup_visible');
582                    return false;
583                });
584
585                $('.ya-share2__popup .ya-share2__list').append(`
586                    <li class="ya-share2__item">
587                        <a class="ya-share2__link" href="${mt}" target="_blank" title="${lang == 'ru' ? 'Отправить ссылку по почте' : 'Send link by mail'}">
588                            <svg style="width: 15px;height: 19px;margin-right: 8px;margin-left: 2px;"><use xlink:href="#p-mail"></use></svg>
589                            <span class="ya-share2__title" style="margin-right: 5px;">${lang == 'ru' ? 'Отправить ссылку по почте' : 'Send link by mail'}</span>
590                        </a>
591                    </li>
592                `);
593            }
594        }
595    });
596
597    $('.action-panel .support').click(function(){
598        if(location.pathname.split('/')[2] == 'clouden'){
599            window.open('https://lk.astra.ru', '_blank');
600            return false;
601        }
602
603        const title = lang == 'ru' ? 'Сообщение в техподдержку' : 'Message to technical support';
604        const email = lang == 'ru' ? 'Ваш E-mail' : 'E-mail';
605        const msg = lang == 'ru' ? 'Ваше сообщение' : 'Message text';
606        const sbj = lang == 'ru' ? 'Тема обращения' : 'Subject';
607        const attach = lang == 'ru' ? 'Прикрепить файл' : 'Attach a file';
608        const send = lang == 'ru' ? 'Отправить' : 'Send';
609        const myEmail = $('#myemail').length ? $('#myemail').data('email') : '';
610        const disclaimer = lang == 'ru' ? 'Вы отправляете сообщение в техподдержку ISPsystem - разработчика программного обеспечения. Если вопрос касается услуги, которую вам предоставляет хостинг-провайдер, напишите в техподдержку вашего провайдера. Контакты провайдера вы можете найти на сайте, с которого заказывали услугу.' : "You are sending a message to the technical support team at ISPsystem, the software developer. If your question concerns a service provided by your hosting provider, please contact your provider's technical support team. You can find your provider's contact details on the website where you ordered the service.";
611        $('body').append(`
612            <div class="overlay">
613                <div class="feedback-support-block">
614                    <div class="feedback-support-block__title">${title}</div>
615                    <form action="" method="post" class="feedback-support-block__form">
616                        <div class="feedback-support-block__form-block">
617                            <div class="close">+</div>
618                            <div class="feedback-support-block__subtitle">${email}: <span>*</span></div>
619                            <input type="email" name="email" required="required" value="${myEmail}">
620
621                            <div class="feedback-support-block__subtitle">${sbj}: <span>*</span></div>
622                            <input type="text" name="subject" required="required">
623
624                            <div class="feedback-support-block__subtitle">${msg}: <span>*</span></div>
625                            <textarea name="text" required="required"></textarea>
626
627                            <div class="feedback-block__file">
628                                <label>
629                                    <span class="feedback-block__file-label">${attach}</span>
630                                    <input type="file" name="attachment" accept=".jpg, .jpeg, .png, .webp, .pdf, .avi, .mp4, .mov, .webm, .json, .har, .log, .tar.gz">
631                                </label>
632                            </div>
633
634                            <div class="feedback-support-block__disclaimer">${disclaimer}</div>
635                            <button class="feedback-block__btn">${send}</button>
636                        </div>
637                    </form>
638                </div>
639            </div>`);
640    });
641
642    let currentController = null;
643    let prevText = '';
644    if ($('.header-search').length) {
645        const searchHeader = document.querySelector('.header-search');
646        const searchForm = searchHeader.querySelector(".header-search form");
647        const searchInput = searchForm.querySelector(".header-search input");
648        const searchResult = searchHeader.querySelector(".header-search .search-results-custom");
649        let i;
650        let searchOpen = false;
651
652        searchInput.onkeydown = e => {
653            if ("Enter" === e.key) {
654                searchInput.value = $.trim(searchInput.value);
655            }
656        }
657
658        searchInput.onkeyup = e => {
659            if ($.trim(searchInput.value).length && $.trim(prevText) != $.trim(searchInput.value) || $('.header-search:not(.wide)').length)
660                "Enter" !== e.key && "Space" !== e.code && (
661                $('.header-search:not(.wide)').addClass('wide'),
662                clearTimeout(i),
663                i = setTimeout(( () => {
664                    searchInput.value = $.trim(searchInput.value);
665                    prevText = searchInput.value;
666                    searchForm.dispatchEvent(new Event("customsubmit",{
667                        cancelable: !0
668                    }))
669                }
670                ), 500))
671            else {
672                if (!searchInput.value.length) {
673                    searchResult.innerHTML = e;
674                    searchResult.setAttribute("hidden", "");
675                    searchInput.classList.remove("rounded-t-7");
676                    searchInput.classList.add("rounded-7");
677                    document.getElementById("overlay-custom").setAttribute("hidden", "");
678                    $('html').removeClass('overflow-hidden');
679                    searchOpen = false;
680                }
681            }
682        }
683        searchResult.addEventListener("change", (e => {
684            "space" === e.target.name && (clearTimeout(i),
685            i = setTimeout(( () => {
686                searchForm.dispatchEvent(new Event("submit",{
687                    cancelable: !0
688                }))
689            }
690            ), 500))
691        }
692        ));
693
694        searchForm.addEventListener("change", (e => {
695            if ("version" !== e.target.name) return;
696            clearTimeout(i);
697            searchInput.value = $.trim(searchInput.value);
698            if (!searchOpen || !searchInput.value.length) return;
699            prevText = searchInput.value;
700            searchForm.dispatchEvent(new Event("customsubmit",{
701                cancelable: !0
702            }))
703        }
704        ));
705        searchForm.addEventListener("customsubmit", (t => {
706            if(searchInput.value.length) $(".header-search button:not(.preload)").addClass('preload');
707            t.preventDefault();
708
709            // Прерываем предыдущий запрос, если он есть
710            if (currentController) {
711                currentController.abort('Новый запрос инициирован');
712            }
713
714            // Создаём новый AbortController для текущего запроса
715            currentController = new AbortController();
716            const signal = currentController.signal;
717
718            const i = new FormData(searchForm);
719            searchResult.querySelectorAll('input[name="space"]:checked').forEach((e => {
720                i.append("spaces[]", e.value)
721            }));
722
723            let params = new URLSearchParams(i).toString();
724
725            if ($(searchHeader).find('input[name="s"]').length) {
726                params = params.replace('s=','spaces=');
727            }
728
729            params = params.replace('q=','s=');
730
731            if(searchInput.value.length) {
732                $('.header-search:not(.wide)').addClass('wide');
733                searchOpen = true;
734                fetch("/docs/api/livesearch?" + new URLSearchParams(params).toString(), { signal })
735                .then((e => e.text()))
736                .then((e => {
737                    if (searchOpen) {
738                        searchResult.innerHTML = e,
739                        searchResult.removeAttribute("hidden"),
740                        searchInput.classList.remove("rounded-7"),
741                        searchInput.classList.add("rounded-t-7"),
742                        document.getElementById("overlay-custom").removeAttribute("hidden"),
743                        $('html').addClass('overflow-hidden');
744                        $(".header-search button").removeClass('preload');
745                    }
746                }
747                )).catch((e => {
748                    console.log(e)
749                }));
750
751            } else {
752                $(".header-search button").removeClass('preload');
753            }
754
755        }));
756        document.addEventListener("click", (e => {
757            if(!$(e.target.closest(".header-search")).length) {
758                searchResult.setAttribute("hidden", "");
759                document.getElementById("overlay-custom").setAttribute("hidden", "");
760                $('html').removeClass('overflow-hidden');
761                searchOpen = false;
762                searchInput.classList.remove("rounded-t-7");
763                searchInput.classList.add("rounded-7");
764                $('.header-search.wide').removeClass('wide');
765                $(".header-search button").removeClass('preload');
766                clearTimeout(i);
767
768                // Прерываем текущий запрос, если он есть
769                if (currentController) {
770                    currentController.abort('Закрытие поиска');
771                }
772            } else {
773                const onInput = e.target === searchInput;
774
775                if (onInput)
776                    $('.header-search:not(.wide)').addClass('wide');
777
778                if (searchOpen)
779                    $('html:not(.overflow-hidden)').addClass('overflow-hidden');
780                else
781                    if (onInput && $.trim($(searchInput).val()).length)
782                        searchForm.dispatchEvent(new Event("customsubmit",{
783                            cancelable: !0
784                        }));
785            }
786        }), {
787                passive: !0
788        });
789    }
790
791
792    $('.favorites').click(
793        function(){
794            addToFavorites($('.article-section').data('pid'),this,lang);
795            return false;
796        }
797    );
798
799
800    $('.breadcrumbs').each(function(){
801        let prevName = $.trim($(this).find('.breadcrumbs__item:last').prev().prev().text())
802        let lastName = $.trim($(this).find('.breadcrumbs__item:last').text())
803        if(prevName == lastName) {
804            for (let i=0; i < 2; i++) {
805                $(this).find('.breadcrumbs__item:last').prev().remove()
806            }
807        }
808    });
809
810    function searchInTabs(tabsWrapper, input) {
811        const v = $.trim(input.val()).toLowerCase();
812        const activeTabBody = tabsWrapper.nextAll('.tabs-pane.active-pane');
813
814        // 1. Очищаем старую подсветку во всем табе перед новым поиском
815        removeHighlight(activeTabBody);
816        activeTabBody.find('.finded').removeClass('finded');
817
818        if (v.length === 0) {
819            // СБРОС: если инпут пустой, возвращаем все элементы в исходный вид
820            if (activeTabBody.find('.js-spoiler').length) {
821                activeTabBody.find('.js-spoiler').each(function() {
822                    const s = $(this);
823                    s.show().removeClass('finded');
824                    s.find('.js-spoiler-content').hide().find('*').removeClass('hidden').show();
825                    s.find('.js-spoiler-icon').removeClass('rotate-180');
826                });
827            } else {
828                activeTabBody.find('*').not('script, style').removeClass('hidden').show();
829            }
830            return;
831        }
832
833        // Полностью исправленная функция подсветки
834        function applyHighlight(element, searchStr) {
835            // Берём и сам элемент, и всех его потомков
836            element.add(element.find('*')).contents().each(function() {
837                if (this.nodeType === 3) { // Проверяем строго текстовые узлы (Node.TEXT_NODE)
838                    const text = this.nodeValue;
839                    const idx = text.toLowerCase().indexOf(searchStr);
840
841                    // Защита: не подсвечиваем, если текст уже находится внутри тега mark,
842                    // чтобы избежать бесконечного зацикливания
843                    if (idx >= 0 && $(this).parent().is('mark.tab-search-match') === false) {
844                        const regex = new RegExp('(' + escapeRegExp(searchStr) + ')', 'gi');
845                        const highlightedText = text.replace(regex, '<mark class="tab-search-match" style="background-color: #ffeb3b; color: #000; padding: 2px 0; border-radius: 2px;">$1</mark>');
846                        $(this).replaceWith(highlightedText);
847                    }
848                }
849            });
850        }
851
852
853        function escapeRegExp(string) {
854            return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
855        }
856
857        function removeHighlight(container) {
858            container.find('mark.tab-search-match').each(function() {
859                const inlineText = $(this).text();
860                $(this).replaceWith(document.createTextNode(inlineText));
861            });
862            if (container.length && container.get(0)) {
863                container.get(0).normalize();
864            }
865        }
866
867        // СЦЕНАРИЙ 1: В табе используются спойлеры
868        if (activeTabBody.find('.js-spoiler').length) {
869            activeTabBody.find('.js-spoiler').each(function() {
870                const s = $(this);
871                const content = s.find('.js-spoiler-content');
872                const icon = s.find('.js-spoiler-icon');
873
874                const childElements = content.children().not('script, style');
875
876                if (childElements.length > 0) {
877                    let spoilerHasMatch = false;
878
879                    // Изначально скрываем все элементы внутри контента спойлера
880                    childElements.addClass('hidden').hide();
881                    childElements.find('li').addClass('hidden').hide();
882
883                    childElements.each(function() {
884                        const el = $(this);
885
886                        // Если элемент — список, и он ещё не был принудительно открыт заголовком
887                        if (el.is('ul, ol')) {
888                            const items = el.find('li');
889                            let listHasMatch = false;
890
891                            // Если список скрыт, проверяем его внутренние li
892                            if (el.hasClass('hidden')) {
893                                items.each(function() {
894                                    const li = $(this);
895                                    if (li.text().toLowerCase().includes(v)) {
896                                        li.removeClass('hidden').show();
897                                        applyHighlight(li, v);
898                                        listHasMatch = true;
899                                        spoilerHasMatch = true;
900                                    }
901                                });
902
903                                if (listHasMatch) {
904                                    el.removeClass('hidden').show();
905                                    const prevLabel = el.prev();
906                                    if (prevLabel.length) {
907                                        prevLabel.removeClass('hidden').show();
908                                    }
909                                }
910                            }
911                        } else {
912                            // Если это заголовок или обычный текст (p, b, div)
913                            if (el.text().toLowerCase().includes(v)) {
914                                el.removeClass('hidden').show();
915                                applyHighlight(el, v);
916                                spoilerHasMatch = true;
917
918                                // Проверяем: если следующий за ним элемент является списком — показываем его целиком
919                                const nextList = el.next();
920                                if (nextList.length && nextList.is('ul, ol')) {
921                                    nextList.removeClass('hidden').show();
922                                    nextList.find('li').removeClass('hidden').show(); // Показываем все элементы списка
923                                }
924                            }
925                        }
926                    });
927
928                    if (spoilerHasMatch) {
929                        s.addClass('finded').show();
930                        icon.addClass('rotate-180');
931                        content.show();
932                    } else {
933                        s.hide();
934                        icon.removeClass('rotate-180');
935                        content.hide();
936                    }
937                } else {
938                    if (content.text().toLowerCase().includes(v)) {
939                        s.addClass('finded').show();
940                        icon.addClass('rotate-180');
941                        content.show();
942                        applyHighlight(content, v);
943                    } else {
944                        s.hide();
945                        icon.removeClass('rotate-180');
946                        content.hide();
947                    }
948                }
949            });
950        } else {
951            // СЦЕНАРИЙ 2: В табе нет спойлеров, только обычный текст и списки
952            const directChildren = activeTabBody.children().not('script, style');
953            directChildren.addClass('hidden').hide();
954            directChildren.find('li').addClass('hidden').hide();
955
956            directChildren.each(function() {
957                const el = $(this);
958                if (el.is('ul, ol')) {
959                    const items = el.find('li');
960                    let listHasMatch = false;
961
962                    if (el.hasClass('hidden')) {
963                        items.each(function() {
964                            const li = $(this);
965                            if (li.text().toLowerCase().includes(v)) {
966                                li.removeClass('hidden').show();
967                                applyHighlight(li, v);
968                                listHasMatch = true;
969                            }
970                        });
971
972                        if (listHasMatch) {
973                            el.removeClass('hidden').show();
974                            const prevLabel = el.prev();
975                            if (prevLabel.length) {
976                                prevLabel.removeClass('hidden').show();
977                            }
978                        }
979                    }
980                } else {
981                    if (el.text().toLowerCase().includes(v)) {
982                        el.removeClass('hidden').show();
983                        applyHighlight(el, v);
984
985                        const nextList = el.next();
986                        if (nextList.length && nextList.is('ul, ol')) {
987                            nextList.removeClass('hidden').show();
988                            nextList.find('li').removeClass('hidden').show();
989                        }
990                    }
991                }
992            });
993        }
994    }
995
996    $('.tabs-menu .menu-item a').click(function(){
997        const tab = $(this);
998        const tabID = tab.attr('href');
999        const tabMenu = tab.closest('.tabs-menu');
1000        const tabsWrapper = tabMenu.closest('.tabs-wrapper');
1001        tabMenu.find('.active-tab').removeClass('active-tab');
1002        tab.parent().addClass('active-tab');
1003        tabMenu.parent().nextAll('.tabs-pane').removeClass('active-pane');
1004        $('.tabs-pane'+tabID).addClass('active-pane');
1005        $('.tabs-search-wrapper input').val('');
1006        searchInTabs(tabsWrapper, $('.tabs-search-wrapper input'));
1007        return false;
1008    });
1009
1010    if ($('.tabs-menu').length) {
1011        const html = `
1012            <div class="tabs-search-wrapper relative">
1013                <div class="block fi fi-search absolute left-20px top-17px"></div>
1014                <input class="border border-gray-d9 px-20px py-15px pl-50px rounded-7 w-full bg-white dark:bg-alm-black" type="search" placeholder="" maxlength="255">
1015            </div>
1016        `;
1017        $('.tabs-menu').each(function(){
1018            $(this).wrap('<div class="tabs-wrapper"></div>');
1019            $(this).parent().append(html);
1020        });
1021    }
1022
1023    $('.tabs-search-wrapper input').on('input',function(){
1024        const input = $(this);
1025        const tabsWrapper = input.closest('.tabs-wrapper');
1026        searchInTabs(tabsWrapper, input)
1027    });
1028
1029    if ($('.survey').length) {
1030        let h = $('header').outerHeight()
1031        $('#page').css('padding-top',h+'px');
1032    }
1033
1034/*
1035* Horizontal scroll for tables
1036*/
1037    const tableContainers = document.querySelectorAll('.tw-content figure.table');
1038
1039    tableContainers.forEach(table => {
1040        const scrollbar = document.createElement('div');
1041        scrollbar.className = 'sticky-scrollbar';
1042
1043        const scrollbarInner = document.createElement('div');
1044        scrollbarInner.className = 'sticky-scrollbar-inner';
1045
1046        scrollbar.appendChild(scrollbarInner);
1047        document.body.appendChild(scrollbar);
1048
1049        const scrollbarAfter = document.createElement('div');
1050        scrollbarAfter.className = 'sticky-scrollbar-after';
1051        document.body.appendChild(scrollbarAfter);
1052        document.body.prepend
1053
1054        const syncWidth = () => {
1055            const tableWidth = table.scrollWidth;
1056            const containerWidth = table.clientWidth;
1057
1058            scrollbarInner.style.width = tableWidth + 'px';
1059            scrollbar.style.width = containerWidth + 'px';
1060            scrollbarAfter.style.width = containerWidth + 'px';
1061
1062            const rect = table.getBoundingClientRect();
1063            scrollbar.style.left = rect.left + 'px';
1064            scrollbarAfter.style.left = rect.left + 'px';
1065        };
1066
1067        const checkVisibility = () => {
1068            const rect = table.getBoundingClientRect();
1069            const windowHeight = window.innerHeight;
1070            const isVisible = (rect.top < windowHeight) && (rect.bottom > windowHeight + 20);
1071            const needsScroll = table.scrollWidth > table.clientWidth;
1072
1073            if (isVisible && needsScroll) {
1074                scrollbar.style.display = 'block';
1075                scrollbarAfter.style.display = 'block';
1076                syncWidth();
1077            } else {
1078                scrollbar.style.display = 'none';
1079                scrollbarAfter.style.display = 'none';
1080            }
1081        };
1082
1083        let isSyncingLeft = false;
1084        let isSyncingRight = false;
1085
1086        scrollbar.addEventListener('scroll', function() {
1087            if (!isSyncingLeft) {
1088                isSyncingRight = true;
1089                table.scrollLeft = this.scrollLeft;
1090            }
1091            isSyncingLeft = false;
1092        });
1093
1094        table.addEventListener('scroll', function() {
1095            if (!isSyncingRight) {
1096                isSyncingLeft = true;
1097                scrollbar.style.display = 'block';
1098                scrollbar.scrollLeft = this.scrollLeft;
1099                scrollbar.style.display = 'none';
1100            }
1101            isSyncingRight = false;
1102        });
1103
1104        window.addEventListener('scroll', checkVisibility);
1105        window.addEventListener('resize', () => {
1106            syncWidth();
1107            checkVisibility();
1108        });
1109
1110        syncWidth();
1111        checkVisibility();
1112    });
1113
1114    /*
1115    * Show date of update
1116    */
1117    if(!$(`.sidebar-left .js-doc-tree a[href="${location.pathname}"].parent-item-link`).length) {
1118        //if current link without children then show the date
1119        $('.updated-aricle-info').show();
1120    }
1121
1122    $('.focus-mode').click(function(){
1123        let use_o = $(this).find('use');
1124        let status_in = !(use_o.attr('xlink:href') == '#ff-resize-o');
1125        $('body').toggleClass('focused');
1126        if (status_in) {
1127            use_o.attr('xlink:href', '#ff-resize-o');
1128        } else {
1129            use_o.attr('xlink:href', '#ff-resize-i');
1130        }
1131    });
1132
1133
1134    $('.float-button.toggler').click(function(){
1135        $(this).find('span').toggleClass('rotated');
1136        $('.float-button.support').fadeToggle('fast');
1137        $('.float-button.trial').fadeToggle('fast');
1138    });
1139
1140
1141let analytInitinterval = setInterval(() => {
1142    if (typeof initAnalyt === 'boolean' && initAnalyt) {
1143        clearInterval(analytInitinterval);
1144        const trialButtonAllow = ['clouden','bc','b6c','dns6','vmmanager-admin','dcimanager-admin'];
1145        const locpath = location.pathname.split('/')
1146        const hasTrialButton = locpath.some(segment =>
1147            trialButtonAllow.some(allowed => segment.startsWith(allowed))
1148        );
1149
1150        if (hasTrialButton) {
1151            let getTrialText = lang == 'ru' ? 'Запросить триал' : 'Get a trial';
1152
1153            // Определяем URL формы один раз
1154            let frameURL = '';
1155            locpath.forEach(item => {
1156                if (item.includes('dcimanager-admin')) {
1157                    frameURL = lang == 'ru' ? 'https://www.ispsystem.ru/form/zakaz-triala-dcimanager' : 'https://www.ispsystem.com/form/zakaz-triala-dcimanager' ;
1158                } else if (item.includes('vmmanager-admin')) {
1159                    frameURL = lang == 'ru' ? 'https://www.ispsystem.ru/form/zakaz-triala-vmmanager' : 'https://www.ispsystem.com/form/zakaz-triala-vmmanager' ;
1160                } else if (item.includes('dns6')) {
1161                    frameURL = lang == 'ru' ? 'https://www.ispsystem.ru/form/zakaz-triala-dnsmanager' : 'https://www.ispsystem.com/form/zakaz-triala-dnsmanager';
1162                } else if (item.includes('b6c')) {
1163                    frameURL = lang == 'ru' ? 'https://www.ispsystem.ru/form/zakaz-triala-billmanager' : 'https://www.ispsystem.com/form/zakaz-triala-billmanager';
1164                } else if (item.includes('bc')) {
1165                    frameURL = 'https://www.ispsystem.ru/form/zakaz-triala-billmanager';
1166                } else if (item.includes('clouden')) {
1167                    frameURL = 'https://www.ispsystem.ru/form/zakaz-triala-billmanager-infra';
1168                }
1169            });
1170
1171            // Скрытый контейнер для предзагрузки iframe
1172            const hiddenHolder = document.createElement('div');
1173            hiddenHolder.id = 'trial-iframe-holder';
1174            document.body.appendChild(hiddenHolder);
1175
1176            const popupBody = document.createElement('div');
1177            popupBody.id = 'popup-body';
1178            hiddenHolder.appendChild(popupBody);
1179
1180            // Создаём iframe заранее и грузим в него форму
1181            const iframe = document.createElement('iframe');
1182            iframe.id = 'popup-trial-form';
1183            iframe.scrolling = 'no';
1184            iframe.src = frameURL;
1185            popupBody.appendChild(iframe);
1186
1187            const closeBTN = document.createElement('div');
1188            closeBTN.id = 'popup-trial-close';
1189            closeBTN.className = 'close';
1190            popupBody.appendChild(closeBTN);
1191
1192            let iframeReady = false;
1193
1194            iframe.addEventListener('load', () => {
1195                try {
1196                    const style = iframe.contentDocument.createElement('style');
1197
1198                    const cssToInject = `
1199                            .toolbar-tray-open.toolbar-vertical.toolbar-fixed {
1200                                margin-inline-start: 0;
1201                            }
1202                            #toolbar-administration,
1203                            .toolbar-tray-open .container--header,
1204                            .container.container--header,
1205                            footer,
1206                            iframe,
1207                            #cookieBanner,
1208                            .chat-icon
1209                             {
1210                                display:none !important;
1211                            }
1212                            .g-recaptcha-bubble-arrow + div iframe,
1213                            iframe[title] {
1214                                display:block !important;
1215                            }
1216                            #block-ispsystem-content {
1217                                max-width: 100%;
1218                                background-color: #13202c;
1219                                padding: 30px;
1220                            }
1221                            form .button-blue {
1222                                height: 58px;
1223                            }
1224                            .page .g-recaptcha iframe[title="reCAPTCHA"] {
1225                                display: block !important;
1226                            }`;
1227
1228                    style.textContent = cssToInject;
1229                    iframe.contentDocument.head.appendChild(style);
1230
1231                    const el = iframe.contentDocument.getElementById('block-ispsystem-content');
1232                    if (el) el.classList.add('form', 'form-popup');
1233
1234                    iframe.style.height = iframe.contentDocument.body.scrollHeight + 'px';
1235
1236                    const updateHeight = () => {
1237                        requestAnimationFrame(() => {
1238                            iframe.style.height = iframe.contentDocument.body.scrollHeight + 'px';
1239                        });
1240                    };
1241
1242                    const observer = new MutationObserver(updateHeight);
1243
1244                    observer.observe(iframe.contentDocument.body, {
1245                        childList: true,
1246                        subtree: true,
1247                        attributes: true,
1248                    });
1249
1250                    iframeReady = true;
1251
1252                    // Кнопка
1253                    $('.sidebar-right').append(`
1254                        <div class="get-trial-button">
1255                            <svg style="width: 17px; height: 17px;">
1256                                <use xlink:href="#download"></use>
1257                            </svg>
1258                            ${getTrialText}
1259                        </div>`);
1260
1261
1262                    $('.get-trial-button').click(function(){
1263                        $('#trial-iframe-holder').addClass('show');
1264                        const iframe = document.getElementById('popup-trial-form');
1265                        iframe.style.height = iframe.contentDocument.body.scrollHeight + 'px';
1266                    });
1267
1268                    $('#trial-iframe-holder .close').click(function(){
1269                        $('#trial-iframe-holder').removeClass('show');
1270                    });
1271                } catch (e) {
1272                    console.warn('Trial iframe styling failed:', e);
1273                    iframeReady = true; // всё равно показываем, что готово
1274                }
1275            });
1276        }
1277    }
1278}, 50);
1279
1280
1281
1282
1283});

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.