Единый форум поддержки

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Единый форум поддержки » Новые возможности форумов » Скрипты от пользователей 3


Скрипты от пользователей 3

Сообщений 561 страница 577 из 577

1

Администрация MyBB не гарантирует работоспособность данных скриптов, вы ставите их на свой страх и риск.

Для тех кто выкладывает скрипты:
1) Дайте краткое описание скрипта.
2) Обязательно укажите куда его вставлять.
3) Сам скрипт вставьте в bb-коды [сode] [/сode] или в [quotе] [/quotе]

Авторы скриптов, размещающие свои разработки на бесплатной и добровольной основе, оставляют за собой право в любой момент вносить в них изменения на своё усмотрение (в том числе: обновление с целью улучшения функционала и стабильности; изъятие из публичного пользования; включение рекомендательных интеграций, содержащих информацию о других разработках, относящихся к MyBB). Скрипты предоставляются авторами "как есть" и без каких-либо гарантий, высказанных или подразумеваемых. При этом размещаемый скрипт должен соответствовать условиям Пользовательского соглашения, не содержать вредоносного кода и не использоваться для рекламы и продвижения сторонних ресурсов, не относящихся к MyBB.

Пользователь, устанавливающий скрипт к себе на форум, имеет право сохранить копию скрипта, в том числе в файлы форума (если в описании к скрипту не указано иное) и использовать эту копию вместо оригинального файла. Однако следует понимать, что такая копия будет лишена каких-либо обновлений и может перестать работать вследствие изменений на сервисе. По этой причине рекомендуется использовать оригинальные версии скриптов, за исключением случаев крайней необходимости.

Данные правила относятся ко всем свободно распространяемым скриптам, размещаемым как в этой теме, так и в других темах раздела Новые возможности форумов.

В данной теме запрещено задавать вопросы и просить скрипты. Для этого есть раздел  Запросы по скриптам[10], при нарушение данного правила будет выдаваться предупреждение в профиль.

Отредактировано Alex_63 (Пт, 14 Мар 2025 11:28:27)

+8

561

Быстроплюсы справо в соообщении и плюс с коммментариями(для форумов русфф) через плюсик в Профиле

Плюсик ставится сразу по клику на сердечко(без двойного нажатия)

https://upforme.ru/uploads/001a/fc/23/321/t966505.jpg

В HTML верх(стиль можно отделить и поставить в конец первого окна стиля без тегов <style></style>

<style>
/*Быстроплюсы для Топика!*/
div .post-rating p a {
    text-align: center;
    outline: 1px solid transparent;
    font-weight: 700;
    background: url(https://forumstatic.ru/files/001a/fc/23/26514.svg) no-repeat center;
     background-size:36px auto;
     position:relative;
    z-index:100;
    width: 36px;
    height: 36px;
    text-align:center;
    font-size: 12px !important;
    display: inline-block;
    vertical-align: middle;
    line-height: 34px;
    letter-spacing: -.1px;
}
.noNull:before{content: "+";
    display: inline-block;
    margin-left: -1px;
    font-size: 9px;
    letter-spacing: 0!important;
}   
</style>

<!--// Быстроплюсы v.1 by Deff //-->
<script src="https://forumstatic.ru/files/001b/a6/d4/74583.js"></script>

+9

562

Автообёртывание Хештегов в Поисковую ссылку
(как в ВК, Инсте и Телеге)

       Тут на форуме forumgrimerka.ru дали
задание сделать скрипт поиска по Хештегам,
подумал многим будет полезен                     
 

Например для поиска по таким Хештегам (вставляемым в посты с нужным контентом):
#ЛучшиеПостыФорума
#audio
#video



Требования к Хештегам:
1. Сам Хештег должен быть  без пробелов, максимальная длина 22 символа вместе с #
2. Хештеги прописываем в конце сообщения с нужным контентом, если Хештегов несколько, - прописываем их в строку через пробел, либо каждый на новой строке.
3. При тегировании новых сообщений сразу в отправляемом сообщении поисковые ссылки начинают работать через 30-40мин, тегирование уже запощенных, старых сообщений при редактировании, поисковые ссылки срабатывают через сутки и более...
4. Для кастомизации вида ссылки у ссылки есть класс => .search
Самые актуальные Хештеги удобно выносить в шапку темы

Скрипт вставляем в HTML верх:

<!--// Обёртывание Хештегов в Поисковую ссылку //-->
<script type="text/javascript" src="//forumstatic.ru/files/0012/d8/04/74792.js"></script>



Тестируем, отписываемся в теме Запросы по скриптам #11

Отредактировано Deff (Чт, 27 Окт 2022 15:04:43)

+6

563

Нашлись проблемы в скрипте хештегов, как оказалось давно решённые в скрипте Alex_63 , основной код здесь => Запросы по скриптам[8]

Отредактировано Deff (Вт, 1 Ноя 2022 21:46:35)

+8

564

Тут в связи с установками скрипта поиска по Хештегам просили исключать их при полном цитировании сообщения (Дабы не засорять поиск вторичными тегами)

В HTML низ

Код:
<!-- Исключаем  Хештеги #xxxx, Подпись, Отредактировано при цитировании-->
<style>#pun:not(.gid1) .punbb .post-content p.lastedit{display:none;}</style>
<script>
$(function() {
quoteOld = window.quote;
window.quote = function(x,y){
var pst = $('#p'+y);pst.find('p.lastedit').remove();
var a = pst.find('.post-sig').remove(); quoteOld(x,y);
a.addClass('Deff').appendTo(pst.find('.post-content'));
$('#main-reply').val($('#main-reply').val().replace(/(\]|[\s])#[^\s\[]+/gim,'$1'));
}});
</script>

+5

565

Предварительный анонс нового функционала:

Alex_63 написал(а):

WYSI — визуальный редактор сообщений
Создан специально для форумов MyBB
https://upforme.ru/uploads/0015/c4/3f/2/613655.png

+3

566

+3

567

Обновление скрипта Новый загрузчик изображений, версия 1.2.0.
Исправлены старые баги и добавлены новые возможности.
Новая версия уже работает на форумах, где установлен код (в том числе и этом форуме)!

+1

568

Первые N тем в описании форума (v2.3)
(новая версия скрипта)

https://upforme.ru/uploads/0000/14/1c/15830/532425.png

Значительно переработал старый скрипт от Fover Первые N тем в описании форума.

Описание изменений
  • Теперь скрипт не парсит дочернюю страницу, а работает на форумном API.

  • Добавлена возможность отключать кэширование: если необходимо динамически загружать список тем при каждом открытии или в случае возникновения проблем.

  • В блоке со списком тем выделенные и закрытые темы имеют собственные классы для оформления: .sticky ‒ для выделенных, .closed ‒ для закрытых.

  • Выбрать желаемый вариант открытия блока со списком тем можно без переустановки скрипта: click ‒ по нажатию на символ ">", hover ‒ при наведении курсора на название форума.

  • Переработана логика появления и закрытия блока списка тем: для закрытия блока достаточно нажать в любом месте страницы.

  • Для режима 'click' добавлено закрытие по нажатию на символ.

  • Для режима 'hover' добавлено автоматическое закрытие по таймеру по истечению 2 секунд, если курсор находится вне пределов блока со списком тем или вне ссылки названия форума.

  • Добавлена возможность изменять значок (иконку) для действия click.

  • Добавлен перевод для английской версии форума (переключается автоматически при выборе языка в настройках форума или профиля).
    https://upforme.ru/uploads/0000/14/1c/15830/377955.png

  • Индивидуальная настройка каждого пользователя в профиле с сохранением.
    https://upforme.ru/uploads/0000/14/1c/15830/t184439.png

  • Добавлена возможность индивидуального отключения скрипта в своём профиле (для зарегистрированных пользователей).

  • Добавлен параметр touchDevice, позволяющий администраторам активировать принудительный вариант показа блока 'click' для пользователей с сенсорными устройствами
    (параметр полезен тем, что если Вы установили открытие блока 'hover' или пользователи выбрали у себя в профиле открытие блока "При наведении на заголовок", то при просмотре с сенсорного устройства у них автоматически переключится на 'click' ‒ "Открытие по нажатию на значок").

Код:
<!-- Первые N тем в описании форума (новая версия) -->
<style>
.topicslist {
  position: absolute;
  background-color: #fff;
  border: 1px solid rgba(0, 0, 0, .35);
  margin-top: 5px;
  padding: 10px;
  box-shadow: 0 4px 4px -2px rgba(0, 0, 0, .35);
  border-radius: 3px;
  max-width: 90vw;
  z-index: 110;
}
.topicslist .sticky a {
  font-weight: bold;
  color: #f00;  /* Цвет для выделенных тем */
}
.topicslist .closed a {
  color: #a9a9a9;  /* Цвет для закрытых тем */
}
.topicslist .load {
  animation: slow-load-blink 2s ease-in-out infinite;
}

.clickt {
  cursor: pointer;
  user-select: none;
}
.clickt img {
  border: 0;
  line-height: 1;
  max-height: 16px;
  max-width: 16px;
  vertical-align: middle;
}
@keyframes slow-load-blink{0%,100%{opacity:1}50%{opacity:.3}}
</style>
<script>
window.firstNtopics = {
    // Настройки скрипта
    count: 5,            // Максимальное количество выводимых тем форума
    touchDevice: 1,      // 1- включить принудительно вариант показа блока click для сенсорных устройств , 0 - выключить
    useSession: 1,       // 1- включить кэширование списка тем на 10 минут, 0 - выключить
    selectAct: 'click',  // Вариант показа блока: 'click' (нажатие по значку рядом с названием темы) или 'hover' (наведение курсора на название темы)

    // Шаблон для действия click
    templateClick: ' <span class="clickt" title="Показать список тем"><img src="https://forumstatic.ru/files/001c/3a/d4/70712.png" alt="Список тем"></span>',
};
</script>
<script type="module" src="https://forumstatic.ru/files/001c/3a/d4/90907.js"></script>

Примечание: Вариант с нажатием на символ ('click') рядом с названием форума будет предпочтительнее для сенсорных устройств.

Отредактировано Reysler (Пт, 13 Сен 2024 11:25:53)

+9

569

В теме частично актуализирована информация по скриптам 2015-2020 гг.

Обнаруженные неактуальные скрипты отключены и изъяты из публичного использования. Неактуальными считаются, в частности: нерабочие, устаревшие (имеющие более свежие версии), реализованные в движке форумов, добавленные в Администрирование - Скрипты. Из целей, в том числе, снижение нагрузки на сервис, т.к. многие из таких скриптов использовали ajax запросы к страницам форумов и/или были плохо оптимизированы, а целесообразность в их применении уже отпала ввиду реализации нового функционала от сервиса.

Отключенные скрипты могут содержать рекомендательные интеграции, направленные на популяризацию и распространение актуального функционала на форумах сервиса.

+4

570

Alex_63 написал(а):

Голосовые сообщения
в постах и ЛС

https://upforme.ru/uploads/0015/c4/3f/2/236977.png

+1

571

Alex_63 написал(а):

Мессенджер
Личные сообщения в формате диалогов

https://upforme.ru/uploads/0015/c4/3f/2/924555.png
(скриншот 1)

https://upforme.ru/uploads/0015/c4/3f/2/832158.png
(скриншот 2)

https://upforme.ru/uploads/0015/c4/3f/2/258950.png
(скриншот 3)

https://upforme.ru/uploads/0015/c4/3f/2/74673.png
(скриншот 4)

https://upforme.ru/uploads/0015/c4/3f/2/481269.png
(скриншот 5)

https://upforme.ru/uploads/0015/c4/3f/2/426867.png
(скриншот 6)

+1

572

Вынос наград RusFF в отдельное окно
Весь контент в HTML-низ
Огромное спасибо за помощь в составлении скрипта @Alex_63
https://upforme.ru/uploads/0000/14/1c/39248/960276.png

Сначала добавляем окно, в которое будет встраиваться информация:

Код:
<div id="awards-modal" style="display: none;">
    <div class="modal-content">
        <div class="container" style="display: none;">
            <div class="awards-header">
                 <h3>Награды пользователя</h3>
                 <div id="closeBtn">/*тут ваш крестик*/</div>
            </div>
            <table cellspacing="0">
                <tbody id="awards-content"></tbody>
            </table>
        </div>
    </div>
</div>

Здесь можно менять заголовок, надо добавить кнопку крестика. Контент будет вставляться внутрь #awards-content.
Если хочется вставлять внутрь некоего div, а не внутрь таблицы, можно просто убрать table и добавить div c id "awards-content"

Далее сам скрипт:

Код:
<script>
$(document).on('click', '.ProfileStat .pa-awards a', function (e) {
    e.preventDefault();
    e.stopPropagation();

    const awards = $(this).closest('.post-author').find('.pa-awards');
    const userId = awards.attr('data-id'); 

    const params = {
        check: {
            board_id: BoardID,
            user_id: UserID,
            partner_id: PartnerID,
            group_id: GroupID,
            user_login: UserLogin,
            user_lastvisit: UserLastVisit,
            user_avatar: UserAvatar,
            user_unique_id: UserUniqueID,
            host: document.domain,
            sign: ForumAPITicket
        },
        board_id: BoardID,
        sort: "user",
        users_ids: [userId]
    };

    $('#awards-modal').fadeIn();

    $.jsonRPC.request('awards/index', {
        params: params,
        success: function (data) {
            let tableContent = '';
            data.result[0].awards.forEach(award => {
                tableContent += `
                    <tr class="alt1">
                        <td class="tc2"><img src="${award.item.href}" alt="${award.item.name}"></td>
                        <td class="tcl"><b>${award.item.name}</b><br>${award.item.desc}<br>${award.desc}</td>
                    </tr>
                `;
            });

            $('#awards-content').html(tableContent);
            $('#awards-modal .container').show();
        },
        error: function (error) {
            $('#awards-modal .container').html('<div>Ошибка при загрузке данных. Пожалуйста, попробуйте позже.</div>').show();
        }
    });
});

$(document).on('click', function (e) {
    if ($(e.target).closest('#awards-modal .modal-content').length === 0) {
        $('#awards-modal').fadeOut();
    }
});

$(document).on('click', '#awards-modal #closeBtn', function (e) {
$('#awards-modal').fadeOut();
});

</script>

Контент добавляется в моменте tableContent +=
Если есть желание отображать в другой структуре, с другими столбцами, классами или не в формате таблицы, проч, то можно менять на этом месте.

Далее настраиваем стили (можно как HTML-низ внутри тега <style></style>, так и в Свой стиль)

Код:
/* awards */ 
div.modal-content h3 {
    font-family: 'Times New Roman';
    font-weight: bold;
    font-size: 21px;
    text-align: left;
}
 
#pun #awards-modal tr {
    display: block !important;
}
 
div.modal-content .container {
    padding: 4px 12px;
}
 
div.modal-content div#closeBtn {
    cursor: pointer;
    width: 16px;
    height: 16px;
    position: absolute;
    top: 7px;
    right: -4px;
}
 
#awards-modal .awards-header {
    position: relative;
}
 
#awards-modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}
 
#awards-modal .modal-content {
    max-width: 600px;
    width: 100%;
    text-align: center;
    border: 2px solid gray;
    background: white;
    box-shadow: 0 0 20px -11px #000;
}
 
#awards-modal .container table {
    width: 100%;
    border-collapse: collapse;
}
 
#awards-modal .container td {
    padding: 4px;
    text-align: left;
}

#awards-modal .container td.tc2 {
   width: 53px;
}

#awards-modal .container img {
    max-width: 53px;
    max-height: 53px;
    border: 1 double gray;
}

+3

573

Alex_63 написал(а):

Живые темы
Автоматическая загрузка новых ответов без обновления страницы

https://upforme.ru/uploads/0015/c4/3f/2/496388.gif

+2

574

Alex_63 написал(а):

Всплывающие кнопки форматирования
при выделении фрагмента в форме ответа
https://upforme.ru/uploads/0000/14/1c/32995/376303.gif

+1

575

Список поддержавших пост (классический простой вид, отображаемый внизу сообщения)

https://images4.imagebam.com/01/ab/26/ME12UW6G_o.jpg
Вставлять в HTML низ.

Код:
<script>
(function() {
    // Дожидаемся полной загрузки страницы, включая все ресурсы
    window.addEventListener('load', function() {
        function vv(fn) {
            var lang_obj = {
                'Поблагодарили': {
                    en: 'Thanked'
                }
            },
            lang = $('html')[0].lang;
 
            function _(text) {
                return (lang == 'ru' || !(lang_obj[text] && lang_obj[text][lang])) ? text : lang_obj[text][lang]
            };
 
            if ($('#pun-viewtopic').length) {
                var p_id = [];
 
                $('div.post').each(function(i) {
                    p_id[i] = $(this).attr('id').slice(1);
                });
 
                // Убедимся, что есть посты для обработки
                if (!p_id.length) return;
                
                function getJ(url, callback) {
                    $.get(url, function(d) {
                        $.isFunction(callback) && callback(d);
                    }, 'json');
                };
                
                // Функция обработки голосов с задержкой для гарантии загрузки FORUM.postVotes
                function processVotes(data) {
                    // Проверяем, что данные получены
                    if (!data || !data.response) return;
                    
                    // Убеждаемся, что объект FORUM существует
                    if (typeof FORUM === 'undefined' || !FORUM.postVotes) {
                        // Если объект не существует, повторяем попытку через 500мс
                        setTimeout(function() {
                            processVotes(data);
                        }, 500);
                        return;
                    }
                    
                    function votesInit(idp) {
                        // Убеждаемся, что post ID существует в FORUM.postVotes
                        var vot = FORUM.postVotes[idp];
                        if (!vot) return;
                        
                        var j = [], n = '';
                        
                        $.each(vot, function(z) {
                            var q = vot[z];
                            if (q.value == 1) {
                                j[z] = '<a href="/profile.php?id=' + q.user_id + '">' + q.username + '</a>';
                                n += j[z];
                                if (z < vot.length - 1) n += ', ';
                            }
                        });
                        
                        if (n) {
                            // Проверяем, что элемент для списка не существует, чтобы избежать дублирования
                            var postBox = $('.post#p' + idp + ' .post-box');
                            if (postBox.find('.postVoters').length === 0) {
                                n = '<div class="postVoters"><strong>' + _('Поблагодарили') + ':</strong> ' + n + '</div>';
                                postBox.append(n);
                            }
                        }
                    }
                    
                    // Обработка полученных данных
                    for (var i = 0; i < data.response.length; i++) {
                        var pid = data.response[i].post_id;
                    }
                    
                    // Обрабатываем каждый пост с голосами
                    for (var pid in FORUM.postVotes) {
                        votesInit(pid);
                    }
                    
                    $.isFunction(fn) && fn();
                }
                
                // Вызываем API для получения голосов
                getJ('/api.php?method=post.getVotesByPosts&post_id=' + p_id.join(',') + '&fields=post_id,user_id,username,value,datetime&sort_dir=desc', processVotes);
            }
        };
 
        vv(function() {});
        
        // Повторная проверка через 1.5 секунды для случаев AJAX-загрузки или медленной обработки данных
        setTimeout(function() {
            vv(function() {});
        }, 1500);
    });
})();
</script>

+2

576

🛠️Универсальный скрипт замены от Merlin777🛠️

Есть много скриптов замены одних элементов на форуме на другие. Но обычно при отправке сообщения замены элементов не отображаются, и видны лишь при 🔁перезагрузке.
🔥Данный скрипт показывает содержимое автозамен как на загруженных страницах, так и на отправленных постах (live-обновление).
(этот скрипт также совместим  с "живыми темами", если вы их включили, т.к. механизм добавления контента на страницу тот же самый)

💥Скрипт делает:

  • ✅Раскраску ников по группам

👀Посмотреть картинку🖼️

https://upforme.ru/uploads/0000/14/1c/38891/t163351.jpg

Стандартные группы:
1 - Администраторы
2 - Модераторы
3 - Гость
4 - Пользователи

  • ✅Раскраску основных и дополнительных полей в мини-профиле

👀Посмотреть картинку🖼️

https://upforme.ru/uploads/0000/14/1c/38891/t958727.jpg

  • ✅Замену названий в статистике под аватаром

👀Посмотреть картинку🖼️

https://upforme.ru/uploads/0000/14/1c/38891/t790599.jpg

  • ✅Замена личных ссылок в мини-профиле (Профиль, E-mail, ЛС, Вебсайт)

👀Посмотреть картинку🖼️

https://upforme.ru/uploads/0000/14/1c/38891/t598882.jpg

  • ✅Замена кнопок управления   (Удалить, Редактировать, Цитировать)

👀Посмотреть картинку🖼️

https://upforme.ru/uploads/0000/14/1c/38891/766886.jpg

  • ✅Раскрашивание ников по группам в блоке статистики  на главной странице форума

👀Посмотреть картинку🖼️

https://upforme.ru/uploads/0000/14/1c/38891/529498.jpg

🚨Особенность скрипта:
1) Скрипт  🔀динамически изменяет элементы оформления страницы в реальном времени ("живое" или live обновление).
2) Скрипт использует 👍единый обработчик событий и занимается  🎨заменой/перекраской только на изменившихся объектах, что значительно 🚀ускоряет его работу и радикально снижает нагрузку на браузер.
2) Имеет явную 🧩🧩модульную структуру, что позволяет легко изменять параметры,  добавлять или убирать ненужные блоки.
С модульным  строением также хорошо работают 🤖нейросети типа ChatGPT, которые можно использовать для изменения функционала скрипта.


🛠️Установка скрипта: Администрирование - Формы - HTML низ (желательно - в самый низ окошка "HTML низ")

👀Посмотреть код скрипта💫
Код:
<!-- Начало: Универсальный скрипт замены © Merlin777 kuban.mybb.ru -->
<script>
document.addEventListener("DOMContentLoaded", function () {

  // =========================
  // 📦 CONFIG — Настройки
  // =========================
  const CONFIG = {
    observerDelay: 0, // ⏳ Задержка обновления элементов (0 = requestAnimationFrame для максимально плавного обновления)
    
    // ✅ Разрешить покраску ников на главной странице сайта (в статистике)
   enableIndexNickColoring: true,
  
    // 🔤 Автозамены текста в профиле, кнопках и мини-профиле
    replacements: {
      profileElements: [
        ['.pl-email.profile', 'Профиль', '👤Профиль'],   // Заменяем текст "Профиль" на с эмодзи
        ['.pl-email.email', 'E-mail', '📧Mail'],        // "E-mail" → "📧Mail"
        ['.pl-email.pm', 'ЛС', '✉️\u00A0ЛС'],          // "ЛС" → "✉️ ЛС"
        ['.pl-website.website', 'Вебсайт', '🌐']        // "Вебсайт" → "🌐"
      ],
      postButtons: [
        ['.pl-edit a', 'Редактировать', '✍️\u00A0Редактировать'], // Кнопка редактирования
        ['.pl-delete a', 'Удалить', '❌\u00A0Удалить'],           // Кнопка удаления
        ['.pl-quote a', 'Цитировать', '💬\u00A0Цитировать'],     // Кнопка цитирования
        ['.pl-reply a', 'Ответить', '↩️\u00A0Ответить'],        // Кнопка ответа
        ['.pa-posts', 'Сообщений', '📨 Сообщений'],             // Кол-во сообщений с эмодзи
  
      ],
      miniProfile: [
        ['.pa-ip', 'IP', '🖧 IP'],                      // IP пользователя
        ['.pa-sex', 'Пол', '⚧️ Пол'],                  // Пол с эмодзи
        ['.pa-fld3', 'Создано тем', '➕ Создано тем'], // Кол-во созданных тем
        ['.fld-name', 'Откуда', '🧭 Откуда'],         // Местоположение
        ['.pa-respect', 'Уважение', '⭐ Рейтинг']      // Рейтинг
      ]
    },

    // 🎨 Селекторы мини-профиля для перекраски
    miniProfileSelectors: ["li.pa-title","li.pa-fld1"],

    // 🎨 Цвета ников по группам (основной и ховер)
    groupColors: {
      1: ['#008080','#a1b2cc'], // 🛡️ Админ
      2: ['#993232','#d15f13'], // 🧑‍⚖️ Модератор
      3: ['#000000','#B0B0B0'], // 👤 Гость (черный с серым ховером)
      4: ['#072387','#5869a3']  // 🧙‍♂️ Пользователь (темно-синий с светло-синим ховером)
    },

    // 🎨 Цвета для мини-профиля по именам
    miniProfileColors: {
      "Модератор": { color: ['#38761d','#6abd46'], groups: [2] },       // Зеленый оттенок
      "Администратор": { color: ['#5c1eba','#a1b2cc'], groups: [1] },    // Фиолетовый оттенок
      "The Wizard of the Realm": { color: ['#2986cc','#a1b2cc'], groups: [1] } // Синий
    }
  };

  // =========================
  // 💬 CSS hover — плавное изменение цвета при наведении
  // =========================
  const style = document.createElement('style');
  style.innerHTML = 'a[data-base-color], span[data-base]{transition: color 0.25s ease; cursor:pointer;}';
  document.head.appendChild(style);

  // =========================
  // 🔄 Функция автозамены текста
  // =========================
  function ChangeAll(scope=document){
    // Объединяем все массивы автозамен
    [].concat(CONFIG.replacements.profileElements,
             CONFIG.replacements.postButtons,
             CONFIG.replacements.miniProfile).forEach(function(r){
      var sel = r[0], from = r[1], to = r[2];
      // Находим элементы, которые еще не заменены
      scope.querySelectorAll(sel+':not([data-replaced])').forEach(function(el){
        if(el.innerHTML.indexOf(from) !== -1) el.innerHTML = el.innerHTML.replaceAll(from,to);
        el.dataset.replaced = 'true'; // Помечаем элемент как обработанный
      });
    });
  }

  // =========================
  // 🎨 Покраска ников в постах
  // =========================
  function recolorPostNicks(users, scope = document) {
  const userMap = {};
  users.forEach(u => {
    if (u.username) userMap[u.username.trim().toLowerCase()] = parseInt(u.group_id);
  });

  // 🧱 Общая функция покраски по элементу
  function colorNick(el, username) {
    const group_id = userMap[username.toLowerCase()] || 4; // default group
    const colors = CONFIG.groupColors[group_id];
    if (!colors) return;

    el.style.color = colors[0];
    el.dataset.baseColor = colors[0];
    el.dataset.hoverColor = colors[1] || colors[0];
  }

  // 🎯 1. Ники в постах
  scope.querySelectorAll('.post a[href^="javascript:to("]').forEach(el => {
    if (el.closest('.quote-box, .dropdown, #pun-navlinks, .vote-list, .user-menu')) return;
    const username = el.textContent.trim();
    colorNick(el, username);
  });

  // 🏠 2. Ники на главной (например, в #onlinelist)
  if (CONFIG.enableIndexNickColoring && document.getElementById('onlinelist')) {
    document.querySelectorAll('#onlinelist a[href*="profile.php"]').forEach(el => {
      const username = el.textContent.trim();
      colorNick(el, username);
    });
  }
}


  // =========================
  // 🎨 Покраска мини-профиля
  // =========================
  function recolorMiniProfile(scope=document){
    CONFIG.miniProfileSelectors.forEach(function(sel){
      scope.querySelectorAll(sel).forEach(function(el){
        if(el.dataset.mpRecolored) return; // Уже перекрашен
        let html = el.innerHTML;
        Object.entries(CONFIG.miniProfileColors).forEach(function([name,obj]){
          const [base,hover] = obj.color;
          if(html.includes(name)){
            // Заменяем текст на span с цветами
            html = html.replace(name,
              '<span data-base="'+base+'" data-hover="'+hover+'" style="font-weight:bold;color:'+base+';">'+name+'</span>'
            );
          }
        });
        el.innerHTML = html;
        el.dataset.mpRecolored = 'true'; // Отмечаем как обработанный
      });
    });
  }

  // =========================
  // 🎨 Универсальная перекраска всего (посты + мини-профиль)
  // =========================
  function recolorAll(scope=document){
    recolorPostNicks(JSON.parse(localStorage.getItem('UsersAdmList')?.split('|')[1] || '[]'), scope);
    recolorMiniProfile(scope);
  }

  // =========================
  // 🌐 Получение пользователей через API
  // =========================
  function fetchUsersAndRecolor(force=false, scope=document){
    var key='UsersAdmList';
    var now=Math.floor(Date.now()/1000);
    var cached=localStorage.getItem(key);

    if(cached && !force){
      try{
        var arr=cached.split('|');
        if((now-parseInt(arr[0]))<24*3600){ // ⏱ кеш на 24 часа
          recolorAll(scope);
          return;
        }
      }catch(e){console.warn(e);}
    }

    // Запрос через API
    fetch('/api.php',{
      method:'POST',
      headers:{'Content-Type':'application/x-www-form-urlencoded'},
      body:new URLSearchParams({method:'users.get',limit:'500',fields:'user_id,username,group_id'})
    }).then(r=>r.json()).then(function(data){
      if(data?.response?.users){
        var users=data.response.users;
        localStorage.setItem(key,now+'|'+JSON.stringify(users)); // Сохраняем кеш
        recolorAll(scope);
      }
    }).catch(console.error);
  }

  // =========================
  // 👆 Hover — меняем цвет при наведении
  // =========================
  document.body.addEventListener('mouseover',function(e){
    var el = e.target.closest('span[data-base], a[data-base-color]');
    if(el) el.style.color = el.dataset.hoverColor || el.dataset.hover || el.style.color;
  });
  document.body.addEventListener('mouseout',function(e){
    var el = e.target.closest('span[data-base], a[data-base-color]');
    if(el) el.style.color = el.dataset.baseColor || el.dataset.base || el.style.color;
  });

  // =========================
  // ⏳ Планирование обновления через requestAnimationFrame или setTimeout
  // =========================
  let scheduled = false;
  function scheduleUpdate(){
    if(scheduled) return;
    scheduled = true;
    if(CONFIG.observerDelay === 0){
      requestAnimationFrame(()=>{ ChangeAll(); recolorAll(); scheduled=false; });
    } else {
      setTimeout(()=>{ ChangeAll(); recolorAll(); scheduled=false; }, CONFIG.observerDelay);
    }
  }

  // =========================
  // 👁 MutationObserver — следим за изменениями DOM и автоматически перекрашиваем новые элементы
  // =========================
  const observer = new MutationObserver(()=>scheduleUpdate());
  observer.observe(document.body,{childList:true,subtree:true});

  // =========================
  // ▶ Инициализация при загрузке страницы
  // =========================
  ChangeAll();
  fetchUsersAndRecolor();

  // =========================
  // 🆕 Live-подгрузка новых постов
  // =========================
  document.addEventListener('pun_post',function(e){
    var scope = e.detail?.post || document.body;
    ChangeAll(scope);
    fetchUsersAndRecolor(true, scope); // форсируем обновление при новых постах
  });

});
</script>
<!-- Конец: Универсальный скрипт замены © Merlin777 kuban.mybb.ru -->
📄 Краткое текстовое описание работы скрипта по пунктам

1. Загрузка и конфигурация:

  • Скрипт выполняется после полной загрузки страницы (DOMContentLoaded).

  • В объекте CONFIG настраиваются:

  • текстовые автозамены (смайлики и подписи),

  • цвета групп (для ников),

  • цвета мини-профиля,

  • включение/отключение покраски на главной странице (enableIndexNickColoring),

  • задержка обновлений (через observerDelay),

  • список селекторов, в которых производится автозамена текста.

2. Замена текста (ChangeAll):

Заменяет стандартные подписи (например, "Профиль" → "👤Профиль") в:

  • мини-профилях,

  • кнопках постов,

  • элементах шапки/меню (если указано в селекторах).

Каждый элемент помечается data-changed="true", чтобы не заменять повторно.

3. Перекраска ников (recolorUsers и recolorPostNicks):

Загружает список пользователей с группами из:

  • localStorage (если кэш свежий),

  • либо через запрос к API форума.

  • Красит только ники в постах:

.post a[href^="javascript:to("] — ссылки на ники внутри тем.

  • Исключает ненужные области (шапка, цитаты, меню, dropdown'ы и т.п.).

  • Если включено enableIndexNickColoring, то красит ники в блоке #onlinelist на главной странице.

  • Поддерживает hover-эффект (цвет меняется при наведении).

4. Перекраска мини-профиля (recolorMiniProfile):

  • Красит элементы мини-профиля:

li.pa-title, li.pa-fld1, li.pa-fld2, и т.д.

Цвет задаётся в CONFIG.groupProfileColors по group_id.

  • Также поддерживает hover-эффект.

5. Объединённая функция перекраски (recolorAll):

  • Вызывает recolorPostNicks и recolorMiniProfile вместе.

  • Упрощает вызов в MutationObserver и при подгрузке новых сообщений.

6. Hover через делегирование:

  • На body навешиваются события mouseover и mouseout.

  • Отслеживаются все элементы с data-base или data-base-color.

  • При наведении цвет меняется на hover-цвет, при уходе — возвращается.

7. Обновление при динамических изменениях (MutationObserver):

  • Следит за изменениями в document.body.

  • Вызывает scheduleUpdate, который:

  • запускает обновление через requestAnimationFrame (если observerDelay: 0),

  • или через setTimeout (если указана задержка).

  • Позволяет скрипту корректно обрабатывать любые подгрузки и изменения DOM.

8. AJAX события (pun_post):

При событии pun_post (используется live-подгрузка на форуме):

  • вызывается scheduleUpdate() — обновляет DOM,

  • и fetchAndColor(true) — принудительно обновляет список пользователей и перекраску.

Это гарантирует, что все новые сообщения получают раскраску, как старые.

9. Кэширование пользователей (fetchAndColor):

  • Пользователи с username и group_id сохраняются в localStorage.

  • Кэш действует 24 часа (86400 секунд).

  • Это минимизирует запросы и ускоряет загрузку скрипта.

Отредактировано Merlin777 (Чт, 2 Окт 2025 17:10:56)

+3

577

Ещё раз про скрипты последних сообщений на форуме:)

Есть известные варианты от Alex_63:

Посмотреть

Для верха страницы:
"Последние N сообщений форума(в несколько столбцов)"  Скрипты от пользователей 3

Для низа страницы:
"Последние 10 сообщений форума, новая версия © Alex_63" Статистика форума, последние 10 сообщений, как добавить под шапку?



🔥Представляю вашему вниманию свой вариант списка последних тем, с "живым" автоматическим обновлением

🚨Внимание! Этот вариант не совместим с другими скриптами вывода тем на главную страницу, хотя вы можете их немного исправить для совместимости.

💥Это два файла, css и js.

✅Оба файла работают вместе как единое целое и реализуют панель "живых сообщений" — динамически обновляемую таблицу с последними сообщениями с сайта.
✅Панель вставляется на главную страницу, отображает последние сообщения с подсветкой новых, возможностью поставить обновления на паузу, а также адаптивным переключателем и стилями для удобного отображения.
✅Переключатель "стоп" останавливает загрузку таблицы.
✅Также встроена защита от перегрузок сервера при ошибках загрузки (лимит на запросы) и адаптация к плохому интернет соединению. При отключении интернета панель убирается, при восстановлении связи - 🔁автоматически загружается и заполняется.

Как 👀выглядит панель "живых сообщений": смотрите сайт https://gribnikikybani.mybb.ru/

🔀Как подключить к себе на сайт (самый простой вариант):

Вставить в HTML верх

👀Посмотреть код
Код:
<!--Последние сообщения на главной странице форума--> 
<link rel="stylesheet" href="https://forumstatic.ru/files/001a/f0/7d/58276.css">
<script src="https://forumstatic.ru/files/001a/f0/7d/14613.js"></script>
<!--Последние сообщения на главной странице форума-->

Там в подключаемом js файле  -  быстрый минифицированный код, который отлично работает.

🛠️Полные версии файлов, с комментариями в исходных кодах:

CSS
Код:
/* 📊 Стили для таблицы с живыми сообщениями */
.stats {
  table-layout: fixed;       /* 🧱 Фиксированная ширина колонок */
  width: 100%;               /* 📐 Таблица занимает всю ширину контейнера */
  border-collapse: collapse; /* ✂️ Убираем двойные границы */
  padding: 0!important;      /* 🧹 Убираем внутренние отступы */
  border-top: none!important; /* ❌ Без верхней границы */
}

/* 🧾 Стили для ячеек таблицы */
.stats th, .stats td {
  padding: 0.3em 0.5em;      /* 🧩 Отступы внутри ячеек */
  border: 1px solid #ccc;    /* 🌫️ Светло-серая граница */
  vertical-align: middle;    /* ↕️ Выравнивание текста по вертикали */
}

/* 📏 Ширина второй колонки (время) фиксирована */
.stats .tc2 { 
  width: 15% !important;     /* 🔒 Фиксируем ширину */
}

/* 📜 Тело таблицы с сообщениями: делаем скроллируемым блоком */
#live-posts-body {
  display: block;            /* 📦 Отдельный блочный контейнер */
  max-height: 140px;         /* 📏 Максимальная высота с прокруткой */
  overflow-y: auto;          /* ↕️ Вертикальная прокрутка */
  overflow-x: hidden;        /* ↔️ Горизонтальная прокрутка скрыта */
  width: 100%;               /* 📐 Обязательно растягиваем на всю ширину */
}

/* 📝 Каждая строка в теле таблицы — отдельная таблица для корректного отображения */
#live-posts-body tr {
  display: table;            /* 🧱 Возвращаем поведение таблицы */
  width: 100%;               /* 📐 Ширина строки на 100% */
  table-layout: fixed;       /* 🧱 Фиксированная ширина колонок */
  height: 28px;              /* 📏 Высота каждой строки */
}

/* 🧱 Стили для шапки таблицы */
.stats thead tr {
  display: table;            /* 🧱 Отображаем как таблицу */
  width: 100%;               /* 📐 На всю ширину */
  table-layout: fixed;       /* 🧱 Фиксированная ширина колонок */
}

/* ✨ Подсветка новых сообщений с плавным исчезновением */
#live-posts-body tr.new-message {
   background-color: #DBCDF1; /* 🌟 Фиолетово-сиреневый фон */
  transition: background-color 2s ease; /* 🎨 Плавное затухание подсветки */
}

/* 🔘 Стили для маленького toggle switch (переключателя паузы) */

/* Контейнер заголовка, чтобы позиционировать переключатель */
.stats th.tcl {
  position: relative;        /* 📍 Для абсолютного позиционирования потомков */
}

/* Контейнер переключателя */
.switch {
  position: absolute;        /* 📍 Абсолютное позиционирование */
  left: 4px;                 /* ⬅️ Отступ слева */
  display: inline-block;     /* 🔲 Блочный элемент с inline-отображением */
  width: 36px;               /* 📐 Ширина переключателя */
  height: 16px;              /* 📐 Высота переключателя */
}

/* Скрываем сам чекбокс */
.switch input { 
  display: none;             /* 🙈 */
}

/* Ползунок переключателя */
.slider {
  position: absolute;        /* 📍 Абсолютное позиционирование внутри .switch */
  cursor: pointer;           /* 🖱️ Курсор "рука" */
  background-color: #ccc;    /* 🌫️ Серый фон */
  transition: .4s;           /* 🎨 Плавный переход состояния */
  border-radius: 18px;       /* 🔵 Закругленные края */
  top: 0; left: 0; right: 0; bottom: 0; /* 🧭 Заполнение всей области */
}

/* Круглый ползунок внутри слайдера */
.slider:before {
  position: absolute;        /* 📍 Абсолютное позиционирование */
  content: "";               /* 🔤 Псевдоэлемент без текста */
  height: 14px;              /* 📏 Диаметр круга */
  width: 14px;               /* 📏 Диаметр круга */
  left: 2px;                 /* ⬅️ Отступ слева */
  bottom: 2px;               /* ⬇️ Отступ снизу */
  background-color: white;   /* ⚪ Белый цвет */
  transition: .4s;           /* 🎨 Плавный переход */
  border-radius: 50%;        /* ⚪ Круглая форма */
}

/* При включенном переключателе — меняем цвет и позицию ползунка */
input:checked + .slider { 
  background-color: #2196F3; /* 🔵 Синий фон */
}
input:checked + .slider:before { 
  transform: translateX(18px); /* ⬅️ Перемещаем ползунок вправо */
}

/* ✋ Текст "Стоп" рядом с переключателем */
.pause-label {
  display: inline-block;     /* 🔲 Блочный элемент */
  margin-left: 6px;          /* ➡️ Отступ слева */
  font-size: 13px;           /* 🔤 Размер шрифта */
  color: silver;             /* ⚪ Серый цвет */
  user-select: none;         /* 🚫 Запрет выделения текста */
  position: absolute;        /* 📍 Абсолютное позиционирование */
  left: 40px;                /* ⬅️ Позиция слева */
  top: 3px;                  /* ⬆️ Позиция сверху */
}

/* 📱 Скрываем текст "Стоп" на мобильных устройствах */
@media (max-width: 600px) {
  .pause-label { 
    display: none !important; /* 🙈 Скрываем */
  }
}

js
Код:
(function () {
  // 📦 URL для загрузки jQuery, если ещё не подключён
  const jQueryUrl = "https://code.jquery.com/jquery-3.6.0.min.js";
  const maxJQueryRetries = 50; // 🔁 Максимальное количество попыток загрузки jQuery
  let retryCount = 0;

  // ⏱ Задержка между попытками загрузки данных при сетевой ошибке (в мс)
  // Изменяя эту переменную, можно регулировать, через сколько появится "Ошибка загрузки сообщений"
  const retryDelay = 1500; // 1.5 секунды по умолчанию

  // ⚙️ Основная функция инициализации панели живых сообщений
  function initLivePanel($) {
    $(function () {
      // 🌍 Проверяем, что мы на главной странице
      if (window.location.pathname === "/" || window.location.pathname.endsWith("index.php")) {

        // 🔢 Настройки
        const maxBuffer = 10;      // Максимальное количество сообщений в таблице
        const seenIds = new Set(); // 🗂️ Храним уникальные ID сообщений
        let firstLoad = true;      // ⏳ Флаг первой загрузки (без подсветки)
        let paused = false;        // ⏸️ Флаг паузы автообновления
        let isTabActive = true;    // 👀 Флаг активности вкладки
        let inactiveTime = 0;      // ⏱ Время неактивности вкладки
        const inactiveCheckInterval = 5000; // Интервал проверки активности (мс)
        let hasError = false;      // ❌ Флаг ошибки загрузки
        let isFetching = false;    // ⚡ Флаг текущего запроса, чтобы не дублировать

        // 👀 Событие смены видимости вкладки
        document.addEventListener("visibilitychange", function () {
          isTabActive = document.visibilityState === "visible";
          if (isTabActive) {
            fetchLatestPosts(); // 🔄 Сразу пробуем загрузку при активации вкладки
            inactiveTime = 0;   // Сбрасываем таймер неактивности
          }
        });

        // 💾 Читаем состояние паузы из localStorage
        const storedPaused = localStorage.getItem('livePaused');
        if (storedPaused !== null) paused = storedPaused === 'true';

        // 🧱 Формируем HTML-контейнер таблицы с живыми сообщениями
        const html = `
          <div id="live-posts" class="stats section">
            <table class="container stats">
              <thead>
                <tr>
                  <th class="tcl" style="position:relative; white-space:nowrap;">
                    <label class="switch">
                      <input type="checkbox" id="pause-updates">
                      <span class="slider"></span>
                    </label>
                    <span class="pause-label">Стоп</span>
                    🧑‍💻 Автор
                  </th>
                  <th class="tc2">🕒 Время</th>
                  <th class="tcr">💬 Последнее сообщение</th>
                </tr>
              </thead>
              <tbody class="hasicon" id="live-posts-body">
                <tr><td colspan="3">Загрузка сообщений...</td></tr>
              </tbody>
            </table>
          </div>
        `;

        // 📍 Вставка контейнера в страницу
        if ($('#pun-debug').length) $('#pun-debug').replaceWith(html);
        else if ($('#pun-ulinks').length) $('#pun-ulinks').after(html);
        else $('body').prepend(html);

        let $tbody = $('#live-posts-body'); // 🔗 Ссылка на tbody для удобства

        // 🛑 Инициализация состояния чекбокса "Пауза"
        $('#pause-updates').prop('checked', paused);
        $('#pause-updates').on('change', function () {
          paused = this.checked;
          localStorage.setItem('livePaused', paused); // 💾 Сохраняем состояние
        });

        // ❌ Функция отображения ошибки загрузки сообщений
        function showError() {
          hasError = true;
          $tbody.html('<tr><td colspan="3">❌ Ошибка загрузки сообщений.</td></tr>');
        }

        // ✅ Функция очистки ошибок и сообщений "Идёт соединение"
        function clearError() {
          hasError = false;
          $tbody.find('tr:contains("Ошибка загрузки сообщений.")').remove();
          $tbody.find('tr:contains("Идёт соединение")').remove();
        }

        // 🔄 Функция загрузки последних сообщений
        function fetchLatestPosts(retryCountAjax = 0) {
          if (paused || isFetching) return; // ⏸️ Если на паузе или уже выполняется запрос

          isFetching = true; // ⚡ Помечаем запрос как активный

          // 📡 Загружаем скрипт с данными
          $.getScript("/export.php?type=js&max=10&_=" + new Date().getTime())
            .done(function () {
              isFetching = false;

              // ❓ Проверка, есть ли данные
              if (typeof content === "undefined") {
                if (retryCountAjax < 3) {
                  // 🔁 Пытаемся повторить запрос
                  if (!hasError && $tbody.find('tr:contains("Идёт соединение")').length === 0) {
                    $tbody.html('<tr><td colspan="3">🔄 Идёт соединение...</td></tr>');
                  }
                  setTimeout(() => fetchLatestPosts(retryCountAjax + 1), retryDelay); // ⏱ Повтор через retryDelay
                } else {
                  showError(); // ❌ После 3 неудач показываем ошибку
                }
                return;
              }

              clearError(); // ✅ Очистка сообщений об ошибке

              // 🔢 Сортируем сообщения по времени
              content.sort((a, b) => a[0] - b[0]);

              content.forEach(item => {
                const uniqueId = item[0] + '_' + item[1] + '_' + item[3];
                if (!item[3].includes('·') && !item[3].includes('¬') && !seenIds.has(uniqueId)) {

                  // ⏰ Форматируем дату и время
                  const ts = new Date(1000 * item[0]);
                  const mo = String(ts.getMonth() + 1).padStart(2, '0');
                  const dd = String(ts.getDate()).padStart(2, '0');
                  const hh = String(ts.getHours()).padStart(2, '0');
                  const mm = String(ts.getMinutes()).padStart(2, '0');
                  const timeStr = `${dd}.${mo} ${hh}:${mm}`;
                  const rowClass = firstLoad ? "" : "new-message"; // 🎨 Подсветка новых сообщений

                  // 🏗️ Создаём HTML-строку сообщения
                  const $row = $(`
                    <tr class="${rowClass}" style="display:none;">
                      <td class="tcl">🧑‍💻 ${item[1]}</td>
                      <td class="tc2">🕒 ${timeStr}</td>
                      <td class="tcr">💬 <a href="${item[2]}" target="_blank">${item[3]}</a></td>
                    </tr>
                  `);

                  $tbody.append($row);
                  $row.fadeIn(400, function () {
                    if (!firstLoad) {
                      setTimeout(() => {
                        $row.animate({ backgroundColor: "transparent" }, 2000, function () {
                          $row.removeClass('new-message'); // ✨ Убираем подсветку
                        });
                      }, 500);
                    }
                  });

                  seenIds.add(uniqueId); // ✅ Добавляем ID в множество
                  if ($tbody.children('tr').length > maxBuffer) {
                    $tbody.children('tr').first().fadeOut(400, function () { $(this).remove(); }); // 🧹 Удаляем старые
                  }

                  // 📜 Прокручиваем таблицу вниз
                  $tbody.stop().animate({ scrollTop: $tbody[0].scrollHeight }, 600);
                }
              });

              firstLoad = false; // ⏳ Флаг первой загрузки снят
            })
            .fail(function () {
              isFetching = false;
              if (retryCountAjax < 3) {
                if (!hasError && $tbody.find('tr:contains("Идёт соединение")').length === 0) {
                  $tbody.html('<tr><td colspan="3">🔄 Идёт соединение...</td></tr>');
                }
                setTimeout(() => fetchLatestPosts(retryCountAjax + 1), retryDelay); // ⏱ Повтор через retryDelay
              } else {
                showError(); // ❌ После 3 неудачных попыток
              }
            });
        }

        // ⏰ Основной таймер проверки активности вкладки и автообновления
        setInterval(() => {
          if (isTabActive) {
            fetchLatestPosts();
            inactiveTime = 0;
          } else {
            inactiveTime += inactiveCheckInterval;
            const interval = inactiveTime < 60000 ? 15000 : inactiveTime < 180000 ? 30000 : 60000;
            if (inactiveTime % interval === 0) fetchLatestPosts();
          }
        }, inactiveCheckInterval);

        // 🔌 Событие восстановления соединения
        window.addEventListener("online", () => {
          console.log("[Live] Соединение восстановлено. Перезапуск...");
          setTimeout(() => {
            hasError = false;  // ❌ Сбрасываем ошибку
            seenIds.clear();   // 🗑 Сбрасываем старые ID сообщений
            fetchLatestPosts(0); // 🔄 Мгновенно пробуем загрузить свежие сообщения
          }, 200); // ⏱ Минимальная пауза
        });

        // 🚀 Первая загрузка сообщений
        fetchLatestPosts();
      }
    });
  }

  // 🔄 Функция динамической загрузки jQuery, если ещё не подключён
  function loadjQuery() {
    if (typeof jQuery !== "undefined") { initLivePanel(jQuery); return; }
    if (retryCount >= maxJQueryRetries) {
      const errorDiv = document.createElement("div");
      errorDiv.style.color = "red";
      errorDiv.style.fontWeight = "bold";
      errorDiv.style.padding = "10px";
      errorDiv.textContent = "Ошибка загрузки jQuery";
      document.body.prepend(errorDiv);
      return;
    }
    retryCount++;
    const script = document.createElement("script");
    script.src = jQueryUrl;
    script.onload = function () { initLivePanel(jQuery); };
    script.onerror = function () { setTimeout(loadjQuery, 100); };
    document.head.appendChild(script);
  }

  // 🚀 Запуск
  loadjQuery();
})();
Подробное описание

### 🧩 Подробное описание JS и CSS файлов

Оба файла работают вместе как единое целое и реализуют панель "живых сообщений" — динамически обновляемую таблицу с последними сообщениями с сайта. Она вставляется на главную страницу, отображает последние сообщения с подсветкой новых, возможностью поставить обновления на паузу, а также адаптивным переключателем и стилями для удобного отображения.

---

## 🧠 JavaScript: Основная логика

### 📌 Назначение:
- Автоматически загружает и отображает последние сообщения с сервера.
- Проверяет, подключён ли jQuery — и, если нет, подключает его.
- Обновляет сообщения с интервалом, учитывая активность вкладки.
- Позволяет приостановить обновления с помощью переключателя.
- Обрабатывает ошибки загрузки, повторяет запросы при неудачах.
- Сохраняет состояние паузы в localStorage.

---

### 🔧 Ключевые функции:

#### 1. `loadjQuery()`
- Проверяет наличие jQuery.
- Если не найден — загружает из CDN с повторными попытками.
- Если не удалось загрузить — выводит ошибку.

#### 2. `initLivePanel($)`
- Инициализирует панель на главной странице (/ или index.php).
- Создаёт HTML-структуру таблицы.
- Вставляет её в нужное место на странице (например, после #pun-ulinks или в body).
- Управляет состоянием паузы и активности вкладки.

#### 3. `fetchLatestPosts()`
- Загружает данные из /export.php?type=js&max=10 с помощью $.getScript().
- Обрабатывает ошибки и повторяет запрос при необходимости.
- Добавляет новые сообщения в таблицу, удаляет старые, если превышено maxBuffer.
- Подсвечивает новые сообщения, если это не первая загрузка.
- Прокручивает таблицу вниз.

#### 4. `pause-updates (чекбокс)`
- Переключатель "Стоп" для остановки/запуска обновлений.
- Состояние сохраняется в localStorage.

#### 5. `visibilitychange / online`
- При возвращении на вкладку или восстановлении соединения — обновляет данные.
- При неактивности вкладки — увеличивает интервал обновления.

---

## 🎨 CSS: Стили и оформление

### 📌 Назначение:
- Стилизует таблицу с живыми сообщениями.
- Обеспечивает удобное отображение, фиксированную ширину колонок, прокрутку.
- Добавляет анимацию подсветки новых сообщений.
- Реализует стили для переключателя "Стоп".

---

### 🔧 Основные стили:

#### 1. `.stats (таблица)`
- table-layout: fixed — фиксированная ширина колонок.
- Без верхней границы, без внутренних отступов.
- Полностью растянута по ширине.

#### 2. `.stats .tc2 (колонка времени)`
- Фиксированная ширина 15%.

#### 3. `#live-posts-body (тело таблицы)`
- max-height: 140px, overflow-y: auto — прокрутка, если много сообщений.
- Каждая строка (tr) — отдельный table, чтобы сохранить ширину колонок.

#### 4. `.new-message`
- Подсветка новых строк: background-color: #DBCDF1.
- Плавное исчезновение подсветки за 2 секунды.

#### 5. `.switch (переключатель)`
- Кастомный стиль для чекбокса.
- Круглый слайдер, меняющий цвет при активации.
- Позиционируется рядом с заголовком таблицы.

#### 6. `.pause-label (надпись "Стоп")`
- Текст рядом с переключателем.
- Скрыта на мобильных устройствах (max-width: 600px).

---

## 🧩 Взаимодействие JS и CSS

- JS создаёт HTML-структуру, CSS её оформляет.
- Переключатель, созданный в JS, стилизуется с помощью CSS-классов .switch, .slider.
- Анимация новых сообщений реализована через CSS-переходы (transition) и JS-классы (new-message).
- Стили адаптированы под мобильные устройства.

---

## 🧪 Как использовать

1. Подключите оба файла на страницу (например, через <script> и <style> или внешние файлы).
2. Убедитесь, что /export.php?type=js&max=10 возвращает данные в нужном формате:
   content = [
     [timestamp, username, link, message],
     ...
   ];
3. Панель будет отображаться на главной странице сайта.

---

## 📌 Особенности

- Автоматическая загрузка jQuery, если отсутствует.
- Умная загрузка: при неактивной вкладке — увеличенный интервал.
- Сохранение состояния паузы между сессиями.
- Адаптивный дизайн и поддержка мобильных устройств.

P.S. Из исходного кода вы также можете сделать контейнер  для вставки панели с темами в любое нужное вам место.

Отредактировано Merlin777 (Ср, 8 Окт 2025 12:18:17)

+3


Вы здесь » Единый форум поддержки » Новые возможности форумов » Скрипты от пользователей 3