Skip to content

Instantly share code, notes, and snippets.

@xTCry
Created November 29, 2025 15:32
Show Gist options
  • Select an option

  • Save xTCry/a2f408f0664e64476625864321d69bc5 to your computer and use it in GitHub Desktop.

Select an option

Save xTCry/a2f408f0664e64476625864321d69bc5 to your computer and use it in GitHub Desktop.
Bitrix. Admin panel fix style. Фикс вкладок и списка при большом количестве сайтов. (TODO: need fix)

Bitrix. Admin panel fix style. Фикс вкладок и списка при большом количестве сайтов

Удобно, если есть много сайтов и у сайтов указано множество доменов.
Этот фикс стилем ограничивает максимальную высоту popups и делает скроллинг вкладкам для настроек при выборе сайтов (чтобы страница настроек не была широченной)

Расположить файл тут php_interface/admin_header.php. Он подключается автоматом

TODO

функцию кастомизации popup временно отключена, надо фиксануть
срабатывает на другие popups, а не только на менюшку сайтов слева. нужно доработать селектор.. было некогда

<!-- Фикс большого количества вкладок, чтобы была их прокрутка -->
<style>
#bx-admin-prefix .adm-detail-content-item-block table {
table-layout: fixed;
}
#bx-admin-prefix .adm-detail-subtabs-block {
overflow-x: auto;
overflow-y: hidden;
}
</style>
<style>
#bx-admin-prefix .bx-core-popup-menu,
#bx-admin-prefix.bx-core-popup-menu {
max-height: 85vh;
overflow-y: auto;
}
</style>
<script>
// Colorize site-list menu
document.addEventListener('DOMContentLoaded', function() {
// TODO: need fix - срабатывает на другие попапы, на все набрасывается, а не только на менюшку сайтов слева
return;
function debounce(func, delay) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), delay);
};
}
function generateColor(id) {
let hash = 0;
for (let i = 0; i < id.length; i++) {
hash = id.charCodeAt(i) + ((hash << 5) - hash);
}
const hue = Math.abs(hash) % 360;
return {
bg: `hsl(${hue}, 60%, 95%)`, // Light background
border: `hsl(${hue}, 70%, 50%)` // Border color
};
}
function getSiteId(item) {
const textSpan = item.querySelector('.bx-core-popup-menu-item-text');
if (textSpan) {
const match = textSpan.textContent.match(/\[(.*?)\]$/);
return match ? match[1].toLowerCase() : 'default';
}
return 'default';
}
function colorizeSites() {
// Handle multiple #bx-admin-prefix
const prefixes = [...document.querySelectorAll('#bx-admin-prefix')].slice(-1);
prefixes.forEach(prefix => {
const items = Array.from(prefix.querySelectorAll('.bx-core-popup-menu-item'));
if (items.length === 0) return;
// For separators: sort and rebuild to avoid mutation issues
items.sort((a, b) => getSiteId(a).localeCompare(getSiteId(b)));
// Preserve angle if exists
const angle = prefix.querySelector('.bx-core-popup-menu-angle');
const fragment = document.createDocumentFragment();
if (angle) {
fragment.appendChild(angle.cloneNode(true)); // Clone to rebuild
}
let prevId = '';
items.forEach((item, index) => {
const siteId = getSiteId(item);
const colors = generateColor(siteId);
// Apply colors
item.style.backgroundColor = colors.bg;
item.style.borderLeft = `4px solid ${colors.border}`;
item.style.transition = 'background-color 0.2s ease'; // Smooth
// Add separator if group changes (simple <hr> div)
if (siteId !== prevId && index > 0) {
const separator = document.createElement('div');
separator.innerHTML = '<hr style="margin: 5px 0; border: none; border-top: 1px solid #ddd; opacity: 0.5;">';
fragment.appendChild(separator);
}
fragment.appendChild(item.cloneNode(true)); // Clone for rebuild
prevId = siteId;
});
// Rebuild container content
prefix.innerHTML = '';
prefix.appendChild(fragment);
});
}
const debouncedColorize = debounce(colorizeSites, 200);
const observer = new MutationObserver((mutations) => {
let shouldColorize = false;
for (const mutation of mutations) {
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
// Check if added nodes include menu items or prefix
const hasRelevantNode = Array.from(mutation.addedNodes).some(node =>
node.nodeType === 1 && (
node.id === 'bx-admin-prefix' ||
node.classList?.contains('bx-core-popup-menu-item') ||
node.querySelector?.('.bx-core-popup-menu-item')
)
);
if (hasRelevantNode) {
shouldColorize = true;
break;
}
}
}
if (shouldColorize) {
// Check if any item already has styles applied (to avoid re-coloring and flicker)
const prefixes = document.querySelectorAll('#bx-admin-prefix');
let alreadyStyled = false;
prefixes.forEach(prefix => {
const items = prefix.querySelectorAll('.bx-core-popup-menu-item');
if (Array.from(items).some(item =>
item.style.backgroundColor !== '' ||
item.style.borderLeft !== ''
)) {
alreadyStyled = true;
}
});
if (!alreadyStyled) {
debouncedColorize();
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
setTimeout(debouncedColorize, 500);
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment