Дата: Воскресенье, 30.11.2025, 06:39 | Сообщение # 1 |
|
Написал: Начинающий
Автор темы
Мурчанн
не в сети
Сообщений: 123
Это более продвинутый модуль с встроенным парсером, системой управления кнопками и системой управления рейтингом с цветовой индикацией. Установлены скрипты, которые динамически контролируют изменение цвета элементов в зависимости от рейтинга. При желании можно дополнительно подключить стили для настройки внутреннего дизайна всплывающих окон. По сути, этот модуль является продолжением первой темы. Парсер настроен на любой блог: укажите ссылку на нужную тему, и он автоматически будет подтягивать пользователей, которые оставляют комментарии в указанной теме. Так формируется список последних активных пользователей. Логика работы следующая: устанавливается кнопка «Жалобы и предложения», доступ к теме возможен только через ваш профиль. Как только пользователь заходит и оставляет комментарий, он автоматически подтягивается парсером к форме комментариев. Для работы достаточно просто изменить ссылку на нужную тему. Это полностью исходный код со всеми скриптами - без всяких плясок с бубнами у костра и прочих обёрток. Другими словами, если ты в теме, разберёшься легко, а для остальных это просто набор символов.Код
<script src="https://bro.usite.pro/js/rep01.js"></script> <div class="rep-do-list"><img src="/.s/img/wd/1/ajax.gif"></div> <input type="hidden" class="rep-do-id" value="$_USER_ID$"> <input type="hidden" class="rep-do-group" value="$GROUP_ID$"> <div class="rep-rating-buttons"> <button class="rep-btn" data-val="2">Плюс</button> <button class="rep-btn" data-val="0">Нейтрально</button> <button class="rep-btn" data-val="1">Минус</button> <!-- скрытые input для формы --> <input type="radio" name="rep" value="2" id="rep-good" hidden> <input type="radio" name="rep" value="0" id="rep-neutral" hidden> <input type="radio" name="rep" value="1" id="rep-bad" hidden> </div> <style> .rep-rating-buttons { display: flex; gap: 6px; position: relative; /* чтобы можно было смещать */ top: 220px; /* смещение вверх */ left: 270px; /* смещение вправо */ } .rep-btn { width: 100px; height: 20px; border: 2px solid #ccc; border-radius: 5px; background-color: #fff; color: #333; font-weight: bold; font-size: 10px; /* ← вот здесь задаём размер шрифта */ cursor: pointer; transition: all 0.2s ease; } /* Наведение */ .rep-btn[data-val="2"]:hover { background-color: #4caf50; color: #fff; border-color: #4caf50; } .rep-btn[data-val="0"]:hover { background-color: #9e9e9e; color: #fff; border-color: #9e9e9e; } .rep-btn[data-val="1"]:hover { background-color: #f44336; color: #fff; border-color: #f44336; } /* Выбранная кнопка фиксируется */ .rep-btn.selected[data-val="2"] { background-color: #4caf50; color: #fff; border-color: #4caf50; } .rep-btn.selected[data-val="0"] { background-color: #9e9e9e; color: #fff; border-color: #9e9e9e; } .rep-btn.selected[data-val="1"] { background-color: #f44336; color: #fff; border-color: #f44336; } /* Сдвигаем форму вверх */ .rep-do-reason { margin-top: -30px; /* отрицательный отступ поднимает вверх */ /* или альтернативно */ /* transform: translateY(-50px); */ } </style> <script> $(function(){ $('.rep-btn').click(function(){ // Снимаем выделение со всех кнопок $('.rep-btn').removeClass('selected'); // Фиксируем выбранную кнопку $(this).addClass('selected'); // Ставим значение в скрытый input const val = $(this).data('val'); if(val == 2) $('#rep-good').prop('checked', true); if(val == 0) $('#rep-neutral').prop('checked', true); if(val == 1) $('#rep-bad').prop('checked', true); }); }); </script> <div class="feedback-form"> <!-- Кнопка смайлов --> <textarea class="rep-do-reason" name="rtext" rows="3" placeholder="Напиши свой отзыв..."></textarea> <!-- Кнопка смайлов --> <input class="btn-primary rep-do-go" type="submit" value="Добавить отзыв"> <button type="button" class="rep-do-add">Загрузить еще</button> <!-- Панель смайлов --> <div class="rep-smiley-panel" id="smilePanel"></div> <style> /* Родительский блок */ .parent-container { position: relative; /* кнопка позиционируется внутри */ } /* Сама кнопка */ .rep-smiley-btn { position: absolute; /* привязка к родителю */ top: -15px; /* расстояние от верхнего края родителя */ right: 1px; /* расстояние от правого края */ z-index: 10; /* над другими элементами */ cursor: pointer; font-size: 20px; border: none; background: transparent; outline: none; } /* Кнопка смайлов */ .rep-smiley-btn { display: inline-flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; width: 25px; height: 25px; border-radius: 8px; border: 1px solid #488BFA; background-color: #fff; color: #488BFA; cursor: pointer; transition: all 0.3s ease; /* ПОДЪЁМ КНОПКИ ВВЕРХ (без растяжения!) */ position: relative; bottom: 35px; /* ↑ кнопка едет ВВЕРХ */ } </style> <button class="rep-smiley-btn" id="smileBtn">😎</button> <!-- Родительский блок --> <div id="login-form" style="position: relative;"> <!-- сама форма входа --> <!-- Контейнер друзей привязан под формой --> <div class="ffc-wrapper"> <div class="ffc-container"> <div id="ffc-widget"></div> <script> $(function() { const blogUrl = '/blog/murchann/2025-11-21-3'; const maxFriends = 6; const styles = ` <style> .ffc-wrapper { position: absolute; /* привязка к родителю */ top: -400%; /* сразу под формой */ left: 0; /* при необходимости центрировать можно через left: 50% + transform */ transform: translateX(0); width: 82%; /* можно ограничить ширину */ } .ffc-container { display: flex !important; gap: 0px !important; flex-wrap: wrap !important; justify-content: center !important; align-items: center !important; padding: 8px !important; } /* карточки и аватар */ .ffc-card { display: flex !important; flex-direction: column !important; align-items: center !important; text-decoration: none !important; color: inherit !important; width: 85px !important; margin: -8px !important; transition: transform 0.3s ease !important; } .ffc-card:hover { transform: scale(1.07); } .ffc-name { font-family: 'Roboto', sans-serif !important; font-weight: 500 !important; font-size: 11px !important; margin-top: 4px !important; color: #111 !important; text-align: center !important; text-shadow: 0 1px 2px rgba(0,0,0,0.2) !important; } .ffc-card img { width: 40px !important; height: 40px !important; border-radius: 50% !important; object-fit: cover !important; border: 5px solid #fff !important; outline: 2px solid #0a66c2 !important; outline-offset: -9px !important; box-shadow: 0 2px 8px rgba(0,0,0,0.2) !important; transition: transform 0.3s ease, outline-color 0.3s ease, box-shadow 0.3s ease; } .ffc-card:hover img { transform: scale(1.12); outline-color: #3b8cf6; box-shadow: 0 6px 15px rgba(0,0,0,0.35), 0 0 6px #3b8cf6; } /* адаптивность */ @media (max-width: 480px) { .ffc-card { width: 70px; margin: 2px; } .ffc-card img { width: 50px; height: 50px; } .ffc-name { font-size: 12px; margin-top: 4px; } } </style> `; $('head').append(styles); /* Загрузка гостей как “друзей” */ function loadFriends() { $.get(blogUrl, function(data) { const tempDom = $('<div>').html(data); const comments = tempDom.find('.comEnt').slice(0, maxFriends); if (comments.length === 0) { $('#ffc-widget').html(''); return; } /* Формируем HTML */ let html = '<div class="ffc-wrapper">'; html += '<div class="ffc-container">'; comments.each(function() { const author = $(this).find('.uc-profile-link span').text() || 'Гость'; const avatar = $(this).find('.comm-card-avatar img').attr('src') || '/.s/src/profile/img/profile_photo_thumbnail.png'; const profileLink = $(this).find('.uc-profile-link').attr('href') || '#'; html += ` <a href="${profileLink}" target="_blank" class="ffc-card ffc-card"> <img src="${avatar}"> <div class="ffc-name" title="${author}">${author}</div> </a> `; }); html += '</div></div>'; html += '</div>'; /* Полоска снизу отдельно */ html += ` `; $('#ffc-widget').html(html); }); } loadFriends(); setInterval(loadFriends, 30000); }); </script> </div> </div> </div> <!-- ========== Репутация: чистый вид + управляемые кнопки ========== --> <div id="rep-widget"> <div class="rep-row"> <div class="rep-label">Репутация:</div> <div class="rep-content"> <span class="rep-badge"> <a href="$_REP_READ_URL$" class="rep-link">$_REPUTATION$</a> </span> <?if($_REP_DO_URL$)?><span class="rep-small"> <a href="$_REP_DO_URL$" class="rep-edit">изменить</a> </span> <?endif?> </div> </div> <div class="rep-controls" aria-hidden="false"> <?if($_REP_DO_URL$)?><a href="$_REP_DO_URL$" class="rep-btn rep-btn-left" title="Форма репутации">◀︎</a><?endif?> <span class="rep-btn rep-btn-reset" title="Сброс">●</span> <a href="$_REP_READ_URL$" class="rep-btn rep-btn-right" title="Список репутаций">▶︎</a> </div> </div> <style> /* Универсальные стили для репутации без фона блока */ #rep-widget { display:inline-block; padding:0; border:none; } .rep-row { display:flex; align-items:center; gap:5px; } .rep-label { font-weight:bold; font-size:14px; color:#222; } .rep-content { display:flex; align-items:center; gap:6px; } .rep-badge a.rep-link { padding:2px 6px; border-radius:4px; font-weight:bold; font-size:13px; background:#e5e5e5; color:#000; text-decoration:none; } .rep-small a.rep-edit { font-size:11px; color:#444; text-decoration:underline; opacity:0.8; } /* Контейнер кнопок слева */ .rep-controls { display:flex; justify-content:flex-start; align-items:center; gap:4px; margin-top:4px; } /* Кнопки */ a.rep-btn, span.rep-btn { display:inline-flex; justify-content:center; align-items:center; border-radius:50%; text-decoration:none; user-select:none; transition: transform 0.15s; font-size:8px; width:14px; height:14px; background:#555; color:#fff; } a.rep-btn-left { background:#555; } a.rep-btn-right { background:#555; } span.rep-btn-reset { width:22px; background:#999; border-radius:8px; } a.rep-btn:hover, span.rep-btn:hover { transform:scale(1.15); } </style> <script> (function(){ const widget = document.getElementById('rep-widget'); if (!widget) return; const badgeAnchors = widget.querySelectorAll('.rep-badge .rep-link'); // Окрас репутации badgeAnchors.forEach(a => { const raw = (a.textContent || '').trim(); const match = raw.match(/-?\d+/); const v = match ? parseInt(match[0], 10) : 0; a.textContent = v > 0 ? '+' + v : '' + v; const badge = a.closest('.rep-badge'); if (!badge) return; const gradeClasses = ['rep-1','rep-10','rep-50','rep-100','rep--1','rep--10','rep--50','rep--100','rep-poop','rep-0']; gradeClasses.forEach(c => badge.classList.remove(c)); if (v >= 100) badge.classList.add('rep-100'); else if (v >= 50) badge.classList.add('rep-50'); else if (v >= 10) badge.classList.add('rep-10'); else if (v >= 1) badge.classList.add('rep-1'); else if (v <= -100) badge.classList.add('rep-poop'); else if (v <= -50) badge.classList.add('rep--50'); else if (v <= -10) badge.classList.add('rep--10'); else if (v <= -1) badge.classList.add('rep--1'); else badge.classList.add('rep-0'); }); })(); </script> </div> <script> const smiles = document.querySelectorAll('.rep-smile'); smiles.forEach(smile => { smile.addEventListener('click', () => { // снимаем выделение с других smiles.forEach(s => s.classList.remove('selected')); // выделяем кликнутый smile.classList.add('selected'); // ставим значение в скрытую радиокнопку const val = smile.dataset.val; const radio = document.querySelector(`input[name="rep"][value="${val}"]`); if(radio) radio.checked = true; }); }); </script>
Остальные стили остаются в первой теме, они, в принципе, не менялись. Это дополнение к тому стилю - просто добавляйте нужные элементы избирательно, не обязательно всё подряд, только то, что действительно необходимо.Код
.rep-do-list .prj-date { padding-left: 17px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjlCQUI4OTZFQ0VGMTFFNEE2MDRBRjkwNDhBOUVDRkQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjlCQUI4OTdFQ0VGMTFFNEE2MDRBRjkwNDhBOUVDRkQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowQTE0QzZGRkVDQkYxMUU0QTYwNEFGOTA0OEE5RUNGRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowQTE0QzcwMEVDQkYxMUU0QTYwNEFGOTA0OEE5RUNGRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmLnSBYAAACBSURBVHjaYrSwc2dAAsZAbAHEU6H8UiDeB8RnYQpYgHg9EPNA+QJQHADlqwBxGBB/gPK/gjTwA7ETVEAWiNWAeC+UD7L+KhA/gfL3sTCggsdQDAM70eQZmJDYwVCMj82AbEMqEDMC8Vo8bBQNHkSwB7uTiAIgG1iBeDuR6lkBAgwAqRwaxBLXcoAAAAAASUVORK5CYII=) no-repeat 0; white-space: nowrap; display: inline-block; } /* Scoped styles — только внутри #rep-widget чтобы не ломать сайт */ #rep-widget { font-family: "Roboto", system-ui, -apple-system, "Segoe UI", "Helvetica Neue", Arial; display:inline-block; } #rep-widget .rep-row { display:flex; align-items:center; gap:10px; padding:6px 8px; border-radius:8px; background: #fafafa; max-width: 420px; box-sizing: border-box; } /* label */ #rep-widget .rep-label { font-weight:600; font-size:14px; color:#222; margin-right:2px; flex: 0 0 auto; } /* content area */ #rep-widget .rep-content { display:flex; align-items:center; gap:8px; flex:1 1 auto; } /* badge base */ #rep-widget .rep-badge { display:inline-block; } #rep-widget .rep-badge .rep-link { display:inline-block; font-weight:700; font-size:14px; padding:4px 6px; border-radius:6px; text-decoration:none; color:inherit; min-width:26px; text-align:center; box-sizing:border-box; transition: box-shadow .18s ease, transform .12s ease; border:2px solid transparent; } /* edit link */ #rep-widget .rep-small .rep-edit { font-weight:600; font-size:12px; padding:4px 6px; border-radius:6px; text-decoration:none; color:#0a66c2; border:1px solid rgba(10,102,194,0.12); transition: background .15s ease, color .15s ease, transform .08s; } #rep-widget .rep-small .rep-edit:hover { background:#0a66c239; color:#063b6b; transform:translateY(-1px); } /* Positive gradation (clearly different colors) */ #rep-widget .rep-1 .rep-link { background:#e8f8ee; color:#1f7a3b; border-color:#bfe8c6; } #rep-widget .rep-10 .rep-link { background:#8fe59c; color:#063b12; border-color:#66c376; box-shadow:0 4px 12px rgba(46,204,113,0.12); } #rep-widget .rep-50 .rep-link { background:#38c172; color:#001; border-color:#2aa65a; box-shadow:0 6px 18px rgba(56,193,114,0.14); } #rep-widget .rep-100 .rep-link { background:linear-gradient(135deg,#ffd966,#ffb300); color:#2b2200; border-color:#d4a81a; box-shadow:0 8px 20px rgba(212,168,26,0.18); } /* Negative gradation (clearly different) */ #rep-widget .rep--1 .rep-link { background:#fff0f0; color:#9b2b2b; border-color:#f3c1c1; } #rep-widget .rep--10 .rep-link { background:#ffb6b6; color:#7a0606; border-color:#ff8b8b; box-shadow:0 6px 14px rgba(220,53,69,0.12); } #rep-widget .rep--50 .rep-link { background:#e74c3c; color:#fff; border-color:#c4332b; box-shadow:0 8px 18px rgba(231,76,60,0.18); } #rep-widget .rep--100 .rep-link { background:#3a0d0d; color:#fff; border-color:#2b0707; box-shadow:0 8px 22px rgba(0,0,0,0.45); } /* Extremely negative — brown "poop" with tiny flies (subtle) */ #rep-widget .rep-poop .rep-link { background:#5b3d26; color:#f3e6d8; border-color:#4b2f1e; box-shadow: inset 0 -4px 8px rgba(0,0,0,0.15); position:relative; } #rep-widget .rep-poop .rep-link::after { content:"??"; font-size:12px; margin-left:6px; display:inline-block; opacity:0.8; transform:translateY(-1px); animation: flysmall .9s ease-in-out infinite alternate; } @keyframes flysmall { from{transform:translateY(-1px) rotate(0deg);} to{transform:translateY(-6px) rotate(20deg);} } /* Neutral */ #rep-widget .rep-0 .rep-link { background:#eef3f7; color:#334; border-color:#d5dee6; } /* Controls (buttons) */ #rep-widget .rep-controls { margin-top:8px; display:flex; gap:8px; align-items:center; } #rep-widget .rep-btn { -webkit-appearance:none; appearance:none; border:2px solid #0a66c2; background:#fff; color:#0a66c2; padding:6px 10px; border-radius:8px; font-weight:700; cursor:pointer; transition: background .15s ease, color .15s ease, transform .12s ease, box-shadow .12s; box-shadow: 0 2px 6px rgba(10,102,194,0.08); } #rep-widget .rep-btn:hover { background:#0a66c2; color:#fff; transform:translateY(-2px); box-shadow:0 8px 24px rgba(10,102,194,0.18); } #rep-widget .rep-btn:active { transform:translateY(0); box-shadow:0 4px 12px rgba(10,102,194,0.12); } #rep-widget .rep-btn.rep-btn-reset { border-color:#777; color:#333; background:#fff; } /* Фиксированный размер смайлов внутри комментариев */ .rep-do-list .answer .text .rep-smile { width: 26px !important; height: 26px !important; object-fit: contain; /* сохраняет пропорции */ vertical-align: middle; /* чтобы по центру текста выравнивалось */ } /* Настройки сдвига и позиции */ :root { --photos-horizontal-shift: 120px; /* вправо = +, влево = - */ --photos-vertical-shift: 30px; /* вверх = -, вниз = + */ --photo-size: 100px; /* размер фото */ --photo-border-radius: 0px; /* скругление */ --photo-border-hover: #000; /* цвет рамки при наведении */ } /* Контейнер профиля */ .profile-header { display: flex; align-items: flex-start; justify-content: flex-start; /* ник слева */ position: relative; /* чтобы фото были абсолютными относительно этого блока */ padding-top: 10px; } /* Сетка фото — фиксированная справа и сверху окна */ .profile-photo-grid { display: flex; gap: 10px; flex-wrap: wrap; position: fixed; /* фиксируем относительно окна */ top: 40px; /* расстояние от верхнего края окна */ right: 20px; /* расстояние от правого края окна */ z-index: 999; /* всегда поверх */ } /* Фото карточки */ .photo-card img { width: var(--photo-size); height: var(--photo-size); object-fit: cover; border-radius: 8px; border: 1px solid #0a66c2; transition: all 0.3s ease; cursor: pointer; } /* Эффекты при наведении */ .photo-card img:hover { transform: scale(1.1); filter: brightness(0.8); box-shadow: 0 6px 18px rgba(0,0,0,0.35); }
Пока идёт разработка, я параллельно занимаюсь другими проектами, и могу докидывать стили в запарке , не относящиеся напрямую к этой задаче. Возможны также дубли - моя специфика , когда я сразу работаю над несколькими задачами одновременно это обычное дело. История Репутации и Отзывы (без API) UcOz JS
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.
Дата: Воскресенье, 30.11.2025, 07:13 | Сообщение # 2 |
|
Написал: Начинающий
Автор темы
Мурчанн
не в сети
Сообщений: 123
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.
Дата: Воскресенье, 30.11.2025, 20:46 | Сообщение # 3 |
|
Написал: Начинающий
Автор темы
Мурчанн
не в сети
Сообщений: 123
Обязательно подключите Код
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.
Дата: Среда, 03.12.2025, 00:53 | Сообщение # 4 |
|
Написал: Начинающий
Автор темы
Мурчанн
не в сети
Сообщений: 123
Пример того, как обычно выглядит стандартная шкала замечаний на Ucoz, а также пример того, как можно создать свою собственную шкалу замечаний с помощью JavaScript. Пример того как можно создать свою шкалу замечаний.JS Код
document.addEventListener('DOMContentLoaded', function () { const ratingImgs = Array.from(document.querySelectorAll('.profile-row-content img[src*="/img/fr/w"]')); if (!ratingImgs.length) return; ratingImgs.forEach(img => { const row = img.closest('.profile-row-content'); if (!row) return; // Берём процент const percentAnchor = row.querySelector('.banPercent'); let percent = 0; if (percentAnchor) { const match = percentAnchor.textContent.match(/\d{1,3}/); if (match) percent = Math.min(100, Math.max(0, parseInt(match[0], 10))); } // Прячем оригинальную системную полоску Ucoz img.style.display = 'none'; // Подменяем wm.gif на прозрачный 1×1 и убираем размер const iconWM = row.querySelector('img[src*="wm.gif"]'); if (iconWM) { iconWM.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; iconWM.style.width = '1px'; iconWM.style.height = '1px'; iconWM.style.padding = '0'; iconWM.style.margin = '0'; iconWM.style.border = '0'; iconWM.style.opacity = '0'; iconWM.style.display = 'inline-block'; } // Создаём обёртку для шкалы + процента const wrapper = document.createElement('div'); wrapper.className = 'ban-bar-wrapper'; wrapper.style.display = 'inline-flex'; wrapper.style.alignItems = 'center'; wrapper.style.gap = '6px'; // Кнопки + − const btnPlus = document.createElement('button'); const btnMinus = document.createElement('button'); [btnPlus, btnMinus].forEach(btn => { btn.type = 'button'; btn.style.width = '22px'; btn.style.height = '22px'; btn.style.background = '#0a9fff'; btn.style.border = 'none'; btn.style.borderRadius = '4px'; btn.style.color = '#fff'; btn.style.fontWeight = '900'; btn.style.fontSize = '14px'; btn.style.cursor = 'pointer'; btn.style.boxShadow = '0 2px 5px rgba(10,159,255,0.3)'; btn.style.transition = '0.15s'; btn.onmouseover = () => btn.style.background = '#0077dd'; btn.onmouseout = () => btn.style.background = '#0a9fff'; btn.onmousedown = () => btn.style.transform = 'scale(0.9)'; btn.onmouseup = () => btn.style.transform = 'scale(1)'; }); btnPlus.textContent = '+'; btnMinus.textContent = '−'; // Шкала const bar = document.createElement('div'); bar.style.position = 'relative'; bar.style.width = '340px'; bar.style.height = '10px'; bar.style.background = '#fff'; bar.style.border = '1px solid #ddd'; bar.style.borderRadius = '6px'; bar.style.overflow = 'hidden'; bar.style.boxShadow = 'inset 0 0 3px rgba(0,0,0,0.1)'; // Деления линейки как на линейке const ruler = document.createElement('div'); ruler.style.position = 'absolute'; ruler.style.top = '0'; ruler.style.left = '0'; ruler.style.width = '100%'; ruler.style.height = '100%'; ruler.style.backgroundImage = 'repeating-linear-gradient(90deg, rgba(0,0,0,0.25) 0 2px, transparent 2px 68px)'; ruler.style.pointerEvents = 'none'; // Заливка процента const fill = document.createElement('div'); fill.style.position = 'absolute'; fill.style.top = '0'; fill.style.left = '0'; fill.style.height = '100%'; fill.style.width = percent + '%'; fill.style.borderRadius = '6px'; fill.style.transition = 'width 0.35s ease, background 0.35s ease'; // Цвет градиентом только для 20% function updateFill(p) { percentDisplay.textContent = p + '%'; fill.style.width = p + '%'; if (p <= 20) fill.style.background = 'linear-gradient(135deg, #ffd966, #ffb300)'; else if (p <= 40) fill.style.background = '#ff9900'; else if (p <= 60) fill.style.background = '#ff6600'; else if (p <= 80) fill.style.background = '#ff3300'; else if (p <= 100) fill.style.background = '#cc0000'; } bar.appendChild(ruler); bar.appendChild(fill); // Контейнер для процента (всегда справа) const percentDisplay = percentAnchor && percentAnchor.cloneNode(true) || document.createElement('div'); percentDisplay.style.marginLeft = '8px'; percentDisplay.style.fontSize = '13px'; percentDisplay.style.fontWeight = '700'; percentDisplay.style.color = '#fff'; percentDisplay.style.background = '#0a9fff'; percentDisplay.style.padding = '2px 6px'; percentDisplay.style.borderRadius = '6px'; // Собираем wrapper.appendChild(btnMinus); wrapper.appendChild(bar); wrapper.appendChild(btnPlus); wrapper.appendChild(percentDisplay); // Вставляем шкалу после самого процента в профиле if(percentAnchor){ percentAnchor.style.display='none'; // ← чтобы не дублировался старый % row.insertBefore(wrapper, percentAnchor.nextSibling); } else { row.appendChild(wrapper); } // Навешиваем клики + − btnPlus.onclick = e => { e.preventDefault(); percent = Math.min(100, percent + 5); updateFill(percent); }; btnMinus.onclick = e => { e.preventDefault(); percent = Math.max(0, percent - 5); updateFill(percent); }; updateFill(percent); }); });
На uCoz можно создать отдельный глобальный блок, который будет отвечать только за шкалу замечаний, и потом подключать его в любой модуль: профиль, форум, каталог файлов, новости и т.д. Это мой блок .Код
<div id="" style="fixed-ban-block "> <div class="profile-row"> <div class="profile-row-content"> <a class="banPercent" title="Смотреть историю замечаний" href="$_BAN_READ_URL$"> $_BAN_PERCENT$% </a> <img src="http://s28.ucoz.net/img/fr/w$_BAN_RATING$.gif"/> </div> </div> </div> <script src="https://bro.usite.pro/js/ban.js"></script> <?if($_BAN_DO_URL$)?> <a href="$_BAN_DO_URL$" style="position:absolute; top:1px; left:460px;"> <img title="Изменить" src="https://www.kolobok.us/smiles/icq/bomb.gif"/> </a> <?endif?>
Для размещения и управленияКод
<!-- Бан --> <div class="profile-section-content" style="position: relative;"> <div id="ban-anchor" style="position: absolute; top: -15px; right: 42px;"> $GLOBAL_BAN$ </div> </div> <!-- Бан -->
ПретензииКод
<div class="profile-section-content" style="position: relative;"> <div id="ban-anchor" style="position: absolute; top: -14px; right: 510px;"> Претензии: </div> </div>
Делайте так, как считаете нужным - полностью на ваше усмотрение. Суть работы скрипта заключается в том, что шкала имеет встроенную возможность ручной демонстрационной регулировки. Каждый пользователь может посмотреть, как выглядит анимация шкалы в действии, но реальное управление её значением остаётся исключительно за администратором
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.