NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Уникальные ID предметов // @version 1.1.0 // @author rek655869 // @license MIT // @match https://catwar.net/cw3/ // @match https://catwar.su/cw3/ // @require https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js // ==/UserScript== (function ($, window, document) { $(function () { const style = $('<style></style>').text(` /* Уникальные ID предметов */ /* для тем */ .uniq_ids { --uniq_ids-bg-color: #f0f0f0; --uniq_ids-text-color: #535353; --uniq_ids-header-bg-color: #555; --uniq_ids-header-color: #e7e7e7; --uniq_ids-border-color: #ccc; } .uniq_ids[theme="dark"] { --uniq_ids-bg-color: #2a2a2a; --uniq_ids-text-color: #c6c6c6; --uniq_ids-header-bg-color: #222222; --uniq_ids-header-color: #c6c6c6; --uniq_ids-border-color: #555; } /* для окна */ #uniq_ids-window { position: absolute; width: 300px; height: 200px; top: 100px; left: 100px; background-color: var(--uniq_ids-bg-color); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); border-radius: 8px; z-index: 1000; resize: both; overflow: hidden; // убираем внешний скроллбар color: var(--uniq_ids-text-color); } /* для заголовка */ #uniq_ids-header { height: 30px; background-color: var(--uniq_ids-header-bg-color); color: var(--uniq_ids-header-color); padding: 5px 10px; cursor: move; display: flex; align-items: center; justify-content: space-between; } /* для кнопки смены темы */ #uniq_ids-theme_button { cursor: pointer; border: none; background: transparent; color: var(--uniq_ids-header-color); display: flex; } /* для кнопки копирования */ .uniq_ids-copy-button { cursor: pointer; border: none; background: transparent; color: var(--uniq_ids-text-color); position: absolute; top: 50%; right: 0.01rem; transform: translateY(-50%); } /* содержимое окна */ #uniq_ids-content { padding: 5px; overflow-y: auto; height: calc(100% - 30px); color: var(--uniq_ids-text-color); } /* таблица */ #uniq_ids-content table { width: 100%; } #uniq_ids-content table td { border-bottom: 1px solid var(--uniq_ids-border-color); } #uniq_ids-content table td:last-of-type { position: relative; } #uniq_ids-content table tr td:first-child { padding: 5px; width: 50px; } #uniq_ids-content table img { width: 50px; height: 50px; } #uniq_ids-content table tr td:last-child { padding: 5px; } `); const baseClipboard = `<svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 22 22"><g> <path fill-rule="evenodd" d="M5.5 9.5A.5.5 0 0 1 6 9h4a.5.5 0 0 1 0 1H6a.5.5 0 0 1-.5-.5"/> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1z"/> <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0z"/> </g></svg>`; const fillClipboard = `<svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 22 22"><g> <path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5z"/> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708"/> </g></svg>`; let $settings = JSON.parse(localStorage.getItem('uniq_ids-settings')) || { theme: 'light', window: { width: 300, height: 300, top: 20, left: 500, }, }; const saveSettings = () => localStorage.setItem('uniq_ids-settings', JSON.stringify($settings)); // ждём открытие страницы и её загрузку const observer = new MutationObserver(() => { if ( location.href === 'https://catwar.net/cw3/' || location.href === 'https://catwar.su/cw3/' ) { let $itemList = $('#itemList'); if ($itemList.length) { showWindow($itemList); $('head').append(style); observer.disconnect(); } } }); function showWindow($itemList) { let $floatWindow = $('<div></div>') .addClass('uniq_ids') .attr({ id: 'uniq_ids-window', theme: $settings.theme, }) .css({ width: `${$settings.window.width}px`, height: `${$settings.window.height}px`, top: `${$settings.window.top}px`, left: `${$settings.window.left}px`, }); let $header = $('<div></div>') .attr('id', 'uniq_ids-header') .text('Уникальные ID предметов'); let $themeButton = $('<button></button>').attr( 'id', 'uniq_ids-theme_button', ) .html(`<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" class="bi bi-sun" viewBox="0 0 16 16"> <g><title>Сменить тему</title><path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"/> </g></svg>`); // переключение темы $themeButton.on('click', () => { const newTheme = $settings.theme === 'dark' ? 'light' : 'dark'; $floatWindow.attr('theme', newTheme); $settings.theme = newTheme; }); $header.append($themeButton); let $content = $('<div></div>').attr('id', 'uniq_ids-content'); let $table = $('<table></table>'); parseItems($itemList, $table); $content.append($table); $floatWindow.append($header); $floatWindow.append($content); $('body').append($floatWindow); // реализация перетаскивания let isDragging = false; let offsetX = 0; let offsetY = 0; $header.on('mousedown', (e) => { isDragging = true; offsetX = e.clientX - $floatWindow.offset().left; offsetY = e.clientY - $floatWindow.offset().top; $('body').css('userSelect', 'none'); }); $(document).on('mousemove', (e) => { if (isDragging) { $floatWindow.css({ left: `${e.clientX - offsetX}px`, top: `${e.clientY - offsetY}px`, }); } }); $(document).on('mouseup', () => { $settings.window.top = $floatWindow.offset().top; $settings.window.left = $floatWindow.offset().left; saveSettings(); isDragging = false; $('body').css('userSelect', ''); }); window.addEventListener('beforeunload', () => { $settings.window.width = $floatWindow.width(); $settings.window.height = $floatWindow.height(); saveSettings(); }); // добавление наблюдателя для элемента #itemList let observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'childList' || mutation.type === 'attributes') { $table.empty(); parseItems($itemList, $table); } }); }); observer.observe($itemList[0], { childList: true, attributes: false, subtree: true, }); } /** * Парсинг данных из itemList * @param $table Таблица, в которую будут добавлены данные * @param $itemList Список предметов */ function parseItems($itemList, $table) { let $items = $itemList.find('.itemInMouth'); let imageToIdsMap = new Map(); $items.each(function () { const $item = $(this); let id = $item.attr('id'); let $img = $item.find('img'); let src = $img.length > 0 ? $img[0].src : null; if (src) { if (!imageToIdsMap.has(src)) { imageToIdsMap.set(src, []); } imageToIdsMap.get(src).push(id); } }); // заполняем таблицу imageToIdsMap.forEach((ids, src) => { let $row = $('<tr></tr>'); let $imgElement = $('<img />').attr('src', src); let $copyButton = $('<button></button>') .addClass('uniq_ids-copy-button') .html(baseClipboard); $copyButton.on('click', () => { $('.uniq_ids-copy-button').html(baseClipboard); navigator.clipboard.writeText(ids.join('\n')).then(() => { $copyButton.html(fillClipboard); }); }); $row.append($('<td></td>').append($imgElement)); $row.append($('<td></td>').text(ids.join(', '))); $row.append($('<td></td>').append($copyButton)); $table.append($row); }); } observer.observe(document, { childList: true, subtree: true }); }); })(window.jQuery, window, document);