您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Автоматически добавляет хайд при создании тем и отправке сообщений на сайтах zelenka и lolz, так же отправляет хайд по Enter.
// ==UserScript== // @name AutoHideLZT + Enter // @namespace http://tampermonkey.net/ // @version 4.9-stable // @description Автоматически добавляет хайд при создании тем и отправке сообщений на сайтах zelenka и lolz, так же отправляет хайд по Enter. // @author eretly & Timka241 & Toil & llimonix // @match https://zelenka.guru/* // @match https://lolz.guru/* // @match https://lolz.live/* // @icon https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ6P-us9TBOHABul4NCBuCWU6_W-b1DA_8YmA&s // @grant none // @license BSD-3-Clause // ==/UserScript== /* * Copyright 2024 eretly * Licensed under the BSD 3-Clause License. */ (function () { "use strict"; // Флаги и переменные let isSending = false; let exceptIds = ""; let yourWords = ""; let wordsPosition = "none"; const storageKey = "eretlyHIDE"; // Ключ для localStorage const availableWordsPositions = ["none", "left", "right"]; const wordsPositionPhrases = { none: "Отключено", left: "Слева", right: "Справа", }; const usableWordsPositions = availableWordsPositions.filter((pos) => pos !== "none"); let hideOnButton = true; let hideOnEnter = true; let hideOnCreate = true; let ignoreHideList = false; let capitalizeFirstLetter = false; // Переменные для сохранения исходных значений при открытии настроек let originalCapitalizeFirstLetter = false; // Переменные для управления обработчиками капитализации let capitalizationHandlersAttached = false; let capitalizationObserver = null; function loadSettings() { const savedSettings = JSON.parse(localStorage.getItem(storageKey) ?? "{}"); return savedSettings || {}; } // Загрузка данных из localStorage при инициализации const savedSettings = loadSettings(); if (savedSettings) { exceptIds = savedSettings.exceptIds || ""; yourWords = savedSettings.yourWords || ""; wordsPosition = savedSettings.wordsPosition || "none"; hideOnButton = savedSettings.hideOnButton || false; hideOnEnter = savedSettings.hideOnEnter || false; hideOnCreate = savedSettings.hideOnCreate || false; ignoreHideList = savedSettings.ignoreHideList || false; capitalizeFirstLetter = savedSettings.capitalizeFirstLetter ?? false; } // Функция для отображения предупреждений function xfAlert(text) { if (typeof XenForo !== "undefined" && XenForo.alert) { XenForo.alert(text, "", 3000); return; } alert(text); } function magicChosen($select) { $select.chosen({ width: "auto", search_contains: false, inherit_select_classes: true, disable_search: 1, }); $select.trigger("chosen:updated"); } function hasWordsPosition(initiator = "") { if (initiator === "theme" && !addWordsOnCreate) { return false; } return yourWords && usableWordsPositions.includes(wordsPosition); } function hasExceptIds(initiator = "") { if (ignoreHideList) return false; if (initiator === "theme" && !hideOnCreate) return false; return exceptIds && exceptIds.trim() !== ""; } const canModify = (el, initiator = "") => el && (hasExceptIds(initiator) || hasWordsPosition(initiator)); const isInvalidAction = (el) => el.classList.contains("chat2-input") || window.location.href.match(/conversations\//) || window.location.href.match(/create-thread/); function checkContainsByInsertRegex(regex, words, message) { // Добавляем текст "test" перед последним "/" const regexStr = regex.toString(); const clearWords = words.replace("$&", "").replace(/[-[\]{}()*+?.,\\^$|]/g, "\\$&"); let newRegexStr = words.startsWith("$&") ? regexStr.replace(/\/$/, `${clearWords}/`) : regexStr.replace(/^\//, `/${clearWords}`); // Преобразуем обратно в объект RegExp let newRegex = new RegExp(newRegexStr.slice(1, -1)); return newRegex.exec(message); } function insertWordToMessage(message) { if (!yourWords.trim()) return message; const tempDiv = document.createElement("div"); tempDiv.innerHTML = message; const nodes = Array.from(tempDiv.childNodes); const isIgnorableBlockquote = (node) => node.nodeType === Node.ELEMENT_NODE && node.tagName === "BLOCKQUOTE" && !node.classList.length; if (wordsPosition === "left") { for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if (!isIgnorableBlockquote(node)) { if (node.nodeType === Node.TEXT_NODE) { node.textContent = yourWords + node.textContent; } else if (node.nodeType === Node.ELEMENT_NODE) { node.innerHTML = yourWords + node.innerHTML; } return tempDiv.innerHTML; } } tempDiv.insertAdjacentHTML("afterbegin", yourWords); } if (wordsPosition === "right") { for (let i = nodes.length - 1; i >= 0; i--) { const node = nodes[i]; if (!isIgnorableBlockquote(node)) { if (node.nodeType === Node.TEXT_NODE) { node.textContent = node.textContent + yourWords; } else if (node.nodeType === Node.ELEMENT_NODE) { node.innerHTML = node.innerHTML + yourWords; } return tempDiv.innerHTML; } } tempDiv.insertAdjacentHTML("beforeend", yourWords); } return tempDiv.innerHTML; } // Капитализация function getTextBeforeCaret(element) { const selection = window.getSelection(); if (!selection.rangeCount) return ''; const range = selection.getRangeAt(0); const preCaretRange = range.cloneRange(); preCaretRange.selectNodeContents(element); preCaretRange.setEnd(range.startContainer, range.startOffset); return preCaretRange.toString(); } function shouldCapitalize(textBefore) { if (!textBefore) return true; if (/^\s*@[a-zA-Z0-9_.-]+[,\s]\s*$/.test(textBefore)) return true; if (/[.!?]\s+$/.test(textBefore)) return true; if (/^\s*$/.test(textBefore)) return true; return false; } function insertCapitalizedChar(char) { const selection = window.getSelection(); if (!selection.rangeCount) return false; const range = selection.getRangeAt(0); const upperChar = char.toUpperCase(); range.deleteContents(); const textNode = document.createTextNode(upperChar); range.insertNode(textNode); range.setStartAfter(textNode); range.collapse(true); selection.removeAllRanges(); selection.addRange(range); return true; } function handleContentEditableInput(event) { if (!capitalizeFirstLetter) return; const element = event.target; if (!element.isContentEditable) return; if (event.inputType === 'insertText' && event.data) { const char = event.data; if (!/[a-zA-Zа-яёА-ЯЁ]/.test(char)) return; const textBefore = getTextBeforeCaret(element); if (shouldCapitalize(textBefore)) { event.preventDefault(); insertCapitalizedChar(char); } } } function handleTextAreaInput(event) { if (!capitalizeFirstLetter) return; const element = event.target; if (!(element.tagName === 'TEXTAREA' || (element.tagName === 'INPUT' && (element.type === 'text' || element.type === 'search')))) return; const value = element.value; const selectionStart = element.selectionStart; const selectionEnd = element.selectionEnd; if (selectionStart === selectionEnd && selectionStart > 0) { const lastChar = value[selectionStart - 1]; if (/[a-zA-Zа-яёА-ЯЁ]/.test(lastChar)) { const textBefore = value.substring(0, selectionStart - 1); if (shouldCapitalize(textBefore)) { const newValue = value.substring(0, selectionStart - 1) + lastChar.toUpperCase() + value.substring(selectionStart); element.value = newValue; element.setSelectionRange(selectionStart, selectionStart); } } } } function placeCursorAtEnd(el) { const range = document.createRange(); const sel = window.getSelection(); range.selectNodeContents(el); range.collapse(false); sel.removeAllRanges(); sel.addRange(range); } function enableCapitalization() { if (capitalizationHandlersAttached) return; document.addEventListener('beforeinput', handleContentEditableInput, true); document.addEventListener('input', handleTextAreaInput, false); capitalizationObserver = new MutationObserver(mutations => { for (const mutation of mutations) { if (mutation.type === 'childList' || mutation.type === 'characterData') { const target = mutation.target; let container = target.closest?.('[contenteditable="true"]') || target.parentNode; if (!container || !container.isContentEditable) { let current = target.parentNode; while (current && current !== document.body) { if (current.isContentEditable) { container = current; break; } const editableInside = current.querySelector?.('[contenteditable="true"]'); if (editableInside) { container = editableInside; break; } current = current.parentNode; } } if (!container || !capitalizeFirstLetter) continue; const text = container.innerText || container.textContent; const lastChar = text.trim().slice(-1); if (/[a-zа-яё]/.test(lastChar)) { const before = text.trim().slice(0, -1); if (shouldCapitalize(before)) { const capitalized = before + lastChar.toUpperCase(); container.innerText = capitalized; placeCursorAtEnd(container); } } } } }); const observeElement = (element) => { if (capitalizationObserver) { capitalizationObserver.observe(element, { characterData: true, childList: true, subtree: true }); } }; document.querySelectorAll('[contenteditable="true"]').forEach(observeElement); document.querySelectorAll('blockquote [contenteditable="true"]').forEach(observeElement); if (capitalizationObserver) { capitalizationObserver.observe(document.body, { characterData: true, childList: true, subtree: true }); } document.querySelectorAll('[contenteditable="true"], textarea, input[type="text"], input[type="search"]').forEach((el) => { attachAutoCapitalize(el); }); document.querySelectorAll('blockquote [contenteditable="true"], blockquote textarea, blockquote input[type="text"], blockquote input[type="search"]').forEach((el) => { attachAutoCapitalize(el); }); capitalizationHandlersAttached = true; } function disableCapitalization() { if (!capitalizationHandlersAttached) return; document.removeEventListener('beforeinput', handleContentEditableInput, true); document.removeEventListener('input', handleTextAreaInput, false); if (capitalizationObserver) { capitalizationObserver.disconnect(); capitalizationObserver = null; } document.querySelectorAll('[contenteditable="true"], textarea, input[type="text"], input[type="search"]').forEach((el) => { if (el._autoCapAttached) { el._autoCapAttached = false; } }); capitalizationHandlersAttached = false; } function toggleCapitalization(enabled) { if (enabled) { enableCapitalization(); } else { disableCapitalization(); } } function smartCapitalize(text) { if (!capitalizeFirstLetter) return text; return text.replace(/(^|[.!?]\s+|^\s*@[\w.\-]+[,\s]\s*)([a-zа-яё])/giu, (match, prefix, char) => { return prefix + char.toUpperCase(); }); } function traverseAndSmartCapitalize(root) { if (!root || !capitalizeFirstLetter) return; const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false); let node; while ((node = walker.nextNode())) { if (node.nodeValue && /[a-zа-яё]/i.test(node.nodeValue)) { const newText = smartCapitalize(node.nodeValue); if (newText !== node.nodeValue) { node.nodeValue = newText; } } } } function attachAutoCapitalize(el, type = "auto") { if (!el || el._autoCapAttached) return; el._autoCapAttached = true; if (el.isContentEditable) { el.addEventListener("beforeinput", (e) => { if (!capitalizeFirstLetter) return; if (e.inputType === "insertText" && e.data) { const selection = window.getSelection(); if (!selection.rangeCount) return; const range = selection.getRangeAt(0); const preCaretRange = range.cloneRange(); preCaretRange.selectNodeContents(el); preCaretRange.setEnd(range.startContainer, range.startOffset); const textBefore = preCaretRange.toString(); if (shouldCapitalize(textBefore)) { e.preventDefault(); const upperChar = e.data.toUpperCase(); const textNode = document.createTextNode(upperChar); range.deleteContents(); range.insertNode(textNode); range.setStartAfter(textNode); range.collapse(true); selection.removeAllRanges(); selection.addRange(range); } } }); } else if (el.tagName === "TEXTAREA" || (el.tagName === "INPUT" && (el.type === "text" || el.type === "search"))) { el.addEventListener("input", () => { if (!capitalizeFirstLetter) return; const value = el.value; const selectionStart = el.selectionStart; const selectionEnd = el.selectionEnd; if (selectionStart === selectionEnd && selectionStart > 0) { const lastChar = value[selectionStart - 1]; if (/[a-zA-Zа-яёА-ЯЁ]/.test(lastChar)) { const textBefore = value.substring(0, selectionStart - 1); if (shouldCapitalize(textBefore)) { const newValue = value.substring(0, selectionStart - 1) + lastChar.toUpperCase() + value.substring(selectionStart); el.value = newValue; el.setSelectionRange(selectionStart, selectionStart); } } } }); } } function observeFields() { const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (!(node instanceof HTMLElement)) continue; if (node.matches('[contenteditable="true"], textarea, input[type="text"], input[type="search"]')) { if (capitalizeFirstLetter) { attachAutoCapitalize(node); if (capitalizationObserver && node.matches('[contenteditable="true"]')) { capitalizationObserver.observe(node, { characterData: true, childList: true, subtree: true }); } } } const nestedElements = node.querySelectorAll?.('[contenteditable="true"], textarea, input[type="text"], input[type="search"]'); nestedElements?.forEach((el) => { if (capitalizeFirstLetter) { attachAutoCapitalize(el); if (capitalizationObserver && el.matches('[contenteditable="true"]')) { capitalizationObserver.observe(el, { characterData: true, childList: true, subtree: true }); } } }); if (node.tagName === 'BLOCKQUOTE' || node.querySelector('blockquote')) { const blockquoteElements = node.querySelectorAll?.('blockquote [contenteditable="true"], blockquote textarea, blockquote input[type="text"], blockquote input[type="search"]'); blockquoteElements?.forEach((el) => { if (capitalizeFirstLetter) { attachAutoCapitalize(el); if (capitalizationObserver && el.matches('[contenteditable="true"]')) { capitalizationObserver.observe(el, { characterData: true, childList: true, subtree: true }); } } }); } } } }); observer.observe(document.body, { childList: true, subtree: true }); } function updateHtmlContent(el, initiator = "") { if (!canModify(el, initiator)) { return; } // Сохраняем оригинальный HTML let currentHTML = el.innerHTML.trim(); let tempDiv = document.createElement("div"); tempDiv.innerHTML = currentHTML; currentHTML = tempDiv.innerHTML; // Вставка своих слов (если нужно) if (hasWordsPosition(initiator)) { currentHTML = insertWordToMessage(currentHTML); } const existingHideBlock = el.querySelector( 'blockquote.wysiwygHide[data-tag="users"], blockquote.wysiwygHide[data-tag="exceptids"], blockquote.wysiwygHide[data-tag="except"]' ); if (hasExceptIds(initiator) && !existingHideBlock) { const hideOpenTag = `<blockquote class="wysiwygHide needOption" data-tag="exceptids" data-phrase="Никнеймы пользователей, которые не смогут увидеть" data-align="left" data-option="${exceptIds}">`; const hideCloseTag = `</blockquote>`; currentHTML = `${hideOpenTag} ${currentHTML} ${hideCloseTag}`; } el.innerHTML = currentHTML; } function handleSendMessage(inputElement) { if (isSending) { return; // Если уже отправляется сообщение, выходим } isSending = true; // Устанавливаем флаг отправки const editorBoxElement = inputElement.closest(".defEditor"); if (!editorBoxElement) { isSending = false; return; } const sendButton = editorBoxElement.querySelector( ".lzt-fe-se-sendMessageButton, .button.primary.mbottom, .submitUnit .button.primary", ); if (!sendButton) { isSending = false; return; } console.log("Отправка сообщения..."); sendButton.click(); sendButton.disabled = true; // Отключаем кнопку отправки // Задержка перед отправкой setTimeout(() => { // sendButton.click(); // Симулируем клик по кнопке отправки inputElement.innerHTML = ""; // Очищаем поле ввода после отправки isSending = false; // Сбрасываем флаг после задержки sendButton.disabled = false; // Включаем кнопку отправки снова }, 100); } // Функция для обработки нажатия на кнопку отправки сообщения async function handleSendMessageButtonClick(event) { // Проверяем состояние чекбокса Хайд по кнопке if (!hideOnButton) { console.log("Галочка не включена. Отправка сообщения отменена."); // Лог для отладки return; } // Попытка найти родительский элемент с классом '.defEditor' или '#ProfilePoster' const defEditorElement = event.target.closest(".defEditor"); const profilePosterElement = event.target.closest("#ProfilePoster"); const parentEl = defEditorElement ?? profilePosterElement; const inputElement = parentEl?.querySelector('.fr-element.fr-view[contenteditable="true"]'); if (!inputElement) { return; } if (isInvalidAction(inputElement)) { return; } updateHtmlContent(inputElement); handleSendMessage(inputElement); } // Функция для обработки нажатия клавиши Enter function handleEnterKey(event) { // Проверяем состояние hideOnEnter if (!hideOnEnter) { // Если галочка не включена, просто предотвращаем действие Enter return; } const inputSearchElement = document.querySelector('input[name="keywords"]'); if (event.target === inputSearchElement && event.key === "Enter") { console.log("Поиск выполнен: ", inputSearchElement.value); return; } // Проверка, находимся ли мы в одной из форм, где нужно заблокировать Enter const formElement = event.target.closest( 'form[action="conversations/insert"], ' + 'form[action^="posts/"][action$="/save-inline"], ' + 'form[action^="profile-posts/comments/"][action$="/edit"]', ); if (formElement) { return; // Если фокус на одной из форм, просто выходим } // Проверяем, это клавиша Enter без зажатого Shift if (!(event.key === "Enter" || event.keyCode === 13) || event.shiftKey) { return; // Если это не Enter или зажат Shift, выходим } // Определяем, это ли редактор или чат const inputElement = document.querySelector( '.fr-element.fr-view[contenteditable="true"]:focus', ); if (!inputElement) { return; } if (isInvalidAction(inputElement)) { return; } event.preventDefault(); // Предотвращаем стандартное поведение event.stopPropagation(); // Останавливаем дальнейшую обработку события updateHtmlContent(inputElement); handleSendMessage(inputElement); } // Добавляем обработчик события клика на кнопку отправки сообщения document.addEventListener("mousedown", (event) => { const sendButton = event.target.closest( ".lzt-fe-se-sendMessageButton, .button.primary.mbottom, .submitUnit .button.primary", ); if (!sendButton) { return; } handleSendMessageButtonClick(event); }); // Добавляем обработчик нажатия клавиши Enter только в редакторе и чате document.addEventListener("keydown", handleEnterKey, true); let settings = JSON.parse(localStorage.getItem(storageKey)) || {}; let addWordsOnCreate = settings.addWordsOnCreate || false; // Обработчик для кнопки "Создать тему" document.addEventListener("click", function (event) { const button = event.target; // Проверяем, если это кнопка "Создать тему" if (!(button.type === "submit" && button.value === "Создать тему")) { return; } console.log("Кнопка 'Создать тему' нажата"); const inputElement = document.querySelector('.fr-element.fr-view[contenteditable="true"]'); if (!inputElement) { return; } updateHtmlContent(inputElement, "theme"); }); // Кнопки и все такое function createGearButton() { // Создаем обе кнопки сразу createDesktopButton() createMobileButton() } function createDesktopButton() { const gearButton = document.createElement("button") gearButton.id = "SettingsSwitcherHide" gearButton.classList.add("PopupControl", "Tooltip") gearButton.style.position = "absolute" gearButton.style.right = "12px" gearButton.style.top = "48%" gearButton.style.transform = "translateY(-50%)" gearButton.style.width = "22px" gearButton.style.height = "22px" gearButton.style.color = "#b3b3b3" gearButton.style.background = "none" gearButton.style.border = "none" gearButton.style.cursor = "pointer" gearButton.style.fontSize = "22px" gearButton.style.display = "inline-flex" gearButton.style.alignItems = "center" gearButton.style.justifyContent = "center" gearButton.style.padding = "0" gearButton.style.lineHeight = "25px" gearButton.setAttribute("title", "Настройки AutoHideLZT") gearButton.setAttribute("data-cachedtitle", "Настройки AutoHideLZT") const style = document.createElement("style") style.textContent = ` #SettingsSwitcherHide::before { width: 22px; height: 22px; content: ''; display: inline-block; background-image: url('data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 width=%2720%27 height=%2720%27 stroke=%27rgb(140,140,140)%27 stroke-width=%272%27 fill=%27none%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27 class=%27css-i6dzq1%27%3E%3Cpath d=%27M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 0 0-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 0 0-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.94-1.543.826-3.31 2.37-2.37c1 .608 2.296.07 2.572-1.065%27/%3E%3Cpath d=%27M9 12a3 3 0 1 0 6 0a3 3 0 0 0-6 0%27/%3E%3C/svg%3E'); background-size: 22px 22px; } #SettingsSwitcherHide:hover::before { background-image: url('data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 width=%2720%27 height=%2720%27 stroke=%27rgb(58, 169, 119)%27 stroke-width=%272%27 fill=%27none%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27 class=%27css-i6dzq1%27%3E%3Cpath d=%27M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 0 0-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 0 0-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.94-1.543.826-3.31 2.37-2.37c1 .608 2.296.07 2.572-1.065%27/%3E%3Cpath d=%27M9 12a3 3 0 1 0 6 0a3 3 0 0 0-6 0%27/%3E%3C/svg%3E'); } ` document.head.appendChild(style) const profileListItem = document.querySelector("#AccountMenu > ul > li:nth-child(1)") if (profileListItem) { profileListItem.style.position = "relative" profileListItem.appendChild(gearButton) setTimeout(() => { if (typeof window.XenForo !== "undefined" && window.XenForo.Tooltip) { window.XenForo.Tooltip(gearButton) } }, 200) gearButton.addEventListener("pointerdown", (event) => { event.stopPropagation() originalCapitalizeFirstLetter = capitalizeFirstLetter; toggleSettingsMenu() setTimeout(() => { const menu = document.getElementById("settingsMenu") if (menu) { menu.style.visibility = "visible" menu.style.opacity = 1 menu.style.transform = "translateY(0)" } }, 50) }) } } function createMobileButton() { function createMobileGearButton() { const profileButtons = Array.from(document.querySelectorAll("a.button")).filter((btn) => { const text = btn.textContent.trim() return text === "Перейти в профиль" || text.includes("профиль") || (btn.href && btn.href.includes("/members/")) }) for (const profileButton of profileButtons) { const parentBlock = profileButton.closest(".profile-block") || profileButton.closest(".memberHeader") || profileButton.closest(".userInfo") if (!parentBlock) { console.warn("Не найден допустимый контейнер для шестерёнки") return } if (parentBlock.querySelector("#SettingsSwitcherMobile")) return if (!parentBlock.contains(profileButton)) { console.warn("Кнопка вне ожидаемого контейнера, вставка отменена") return } let wrapper = profileButton.parentElement if (!wrapper || wrapper === parentBlock) { wrapper = document.createElement("div") wrapper.style.display = "inline-flex" wrapper.style.alignItems = "center" wrapper.style.gap = "8px" profileButton.parentNode.insertBefore(wrapper, profileButton) wrapper.appendChild(profileButton) } else { wrapper.style.display = "inline-flex" wrapper.style.alignItems = "center" wrapper.style.gap = "8px" } const gearButton = document.createElement("button") gearButton.id = "SettingsSwitcherMobile" gearButton.classList.add("PopupControl", "Tooltip") gearButton.setAttribute("title", "Настройки AutoHideLZT") gearButton.setAttribute("data-cachedtitle", "Настройки AutoHideLZT") Object.assign(gearButton.style, { width: "24px", height: "24px", background: "none", border: "none", padding: "0", cursor: "pointer", zIndex: "10", flexShrink: "0", display: "inline-flex", alignItems: "center", justifyContent: "center", color: "#b3b3b3", }) gearButton.innerHTML = ` <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='22' height='22' fill='none' stroke='#b3b3b3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'> <path d='M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 0 0-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 0 0-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.94-1.543.826-3.31 2.37-2.37c1 .608 2.296.07 2.572-1.065'/> <path d='M9 12a3 3 0 1 0 6 0a3 3 0 0 0-6 0'/> </svg> ` wrapper.appendChild(gearButton) setTimeout(() => { if (typeof window.XenForo !== "undefined" && window.XenForo.Tooltip) { window.XenForo.Tooltip(gearButton) } }, 200) gearButton.addEventListener("click", (event) => { event.stopPropagation() originalCapitalizeFirstLetter = capitalizeFirstLetter; toggleSettingsMenu() setTimeout(() => { const menu = document.getElementById("settingsMenu") if (menu) { menu.style.visibility = "visible" menu.style.opacity = 1 menu.style.transform = "translateY(0)" } }, 50) }) return } } createMobileGearButton() const observer = new MutationObserver(() => { if (!document.querySelector("#SettingsSwitcherMobile")) { setTimeout(createMobileGearButton, 100) } }) observer.observe(document.body, { childList: true, subtree: true, }) } const settingsMenu = document.createElement("div") settingsMenu.id = "settingsMenu" settingsMenu.style.position = "fixed" settingsMenu.style.backgroundColor = "#272727" settingsMenu.style.color = "white" settingsMenu.style.padding = "10px" settingsMenu.style.borderRadius = "6px" settingsMenu.style.visibility = "hidden" settingsMenu.style.opacity = 0 settingsMenu.style.transform = "translateY(-10px)" settingsMenu.style.zIndex = "9999" settingsMenu.style.right = "0px" settingsMenu.style.top = "0px" settingsMenu.style.height = "297px" settingsMenu.style.width = "350px" settingsMenu.style.transition = "opacity 100ms linear, transform 100ms linear, visibility 100ms linear" settingsMenu.style.outline = "1px solid #363636" function createSettingsMenu() { if (document.getElementById("settingsMenu")) { return } document.body.appendChild(settingsMenu) } function toggleSettingsMenu() { const settingsMenu = document.getElementById("settingsMenu") if (!settingsMenu) { createSettingsMenu() return } if (settingsMenu.style.visibility === "visible") { settingsMenu.style.visibility = "hidden" settingsMenu.style.opacity = 0 settingsMenu.style.transform = "translateY(-100%)" } else { settingsMenu.style.visibility = "visible" settingsMenu.style.opacity = 1 settingsMenu.style.transform = "translateY(0)" } } function initialize() { createSettingsMenu() createGearButton() observeFields() if (capitalizeFirstLetter) { toggleCapitalization(true); } } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", initialize) } else { initialize() } // Заголовок меню const settingsTitle = document.createElement("h3"); settingsTitle.textContent = "Настройки AutoHideLZT"; settingsTitle.style.margin = "0"; settingsTitle.style.color = "white"; settingsTitle.style.position = "relative"; settingsTitle.style.top = "-5px"; settingsTitle.style.display = "inline-block"; settingsTitle.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; settingsTitle.style.fontWeight = "bold"; settingsMenu.appendChild(settingsTitle); // Кнопка закрытия меню const closeButton = document.createElement("button"); closeButton.innerHTML = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'> <line x1='6' y1='6' x2='18' y2='18' stroke='currentColor' stroke-width='2'/> <line x1='18' y1='6' x2='6' y2='18' stroke='currentColor' stroke-width='2'/></svg>`; closeButton.style.color = "white"; closeButton.style.backgroundColor = "transparent"; closeButton.style.border = "none"; closeButton.style.cursor = "pointer"; closeButton.style.width = "30px"; closeButton.style.height = "30px"; closeButton.style.position = "absolute"; closeButton.style.top = "0px"; closeButton.style.right = "0px"; closeButton.onclick = () => { userIdInput.value = exceptIds; yourWordsInput.value = yourWords; $(wordsPositionSelect).val(wordsPosition).trigger("chosen:updated"); hideOnButtonCheckbox.checked = hideOnButton; addWordsOnCreateCheckbox.checked = addWordsOnCreate; hideOnCreateCheckbox.checked = hideOnCreate; hideOnEnterCheckbox.checked = hideOnEnter; ignoreHideListCheckbox.checked = ignoreHideList; capitalizeFirstLetterCheckbox.checked = originalCapitalizeFirstLetter; closeSettingsMenu(); }; settingsMenu.appendChild(closeButton); // Поле для ввода User ID const userIdInput = document.createElement("input"); userIdInput.classList.add("textCtrl"); userIdInput.placeholder = "Введите User ID через запятую"; userIdInput.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; userIdInput.style.width = "100%"; userIdInput.style.marginBottom = "5px"; userIdInput.value = exceptIds; // Создаем контейнер для кнопок const buttonsContainer = document.createElement("div"); buttonsContainer.style.display = "flex"; buttonsContainer.style.justifyContent = "flex-start"; buttonsContainer.style.marginTop = "0px"; // Создаем контейнер для your words const wordsPositionContainer = document.createElement("div"); wordsPositionContainer.style.display = "flex"; wordsPositionContainer.style.flexDirection = "column"; wordsPositionContainer.style.margin = "10px 0 2px"; // Кнопка сохранения const saveButton = document.createElement("button"); saveButton.classList.add("button", "primary"); saveButton.textContent = "Сохранить"; saveButton.style.marginRight = "5px"; saveButton.style.marginTop = "3px"; saveButton.style.padding = "0px 5px"; saveButton.style.fontSize = "12px"; saveButton.style.height = "26px"; saveButton.style.lineHeight = "26px"; saveButton.onclick = () => { exceptIds = userIdInput.value; yourWords = yourWordsInput.value; wordsPosition = $(wordsPositionSelect).val(); hideOnButton = hideOnButtonCheckbox.checked; addWordsOnCreate = addWordsOnCreateCheckbox.checked; hideOnCreate = hideOnCreateCheckbox.checked; hideOnEnter = hideOnEnterCheckbox.checked; ignoreHideList = ignoreHideListCheckbox.checked; const newCapitalizeState = capitalizeFirstLetterCheckbox.checked; capitalizeFirstLetter = newCapitalizeState; toggleCapitalization(newCapitalizeState); localStorage.setItem( storageKey, JSON.stringify({ exceptIds, hideOnButton, yourWords, wordsPosition, addWordsOnCreate, hideOnCreate, hideOnEnter, ignoreHideList, capitalizeFirstLetter: newCapitalizeState }), ); xfAlert("Настройки сохранены"); closeSettingsMenu(); }; // Кнопка отмены const cancelButton = document.createElement("button"); cancelButton.classList.add("button", "primary", "small-button"); cancelButton.textContent = "Отмена"; cancelButton.style.marginTop = "3px"; cancelButton.style.padding = "0px 5px"; cancelButton.style.fontSize = "12px"; cancelButton.style.height = "26px"; cancelButton.style.lineHeight = "26px"; cancelButton.onclick = () => { userIdInput.value = exceptIds; yourWordsInput.value = yourWords; $(wordsPositionSelect).val(wordsPosition).trigger("chosen:updated"); hideOnButtonCheckbox.checked = hideOnButton; addWordsOnCreateCheckbox.checked = addWordsOnCreate; hideOnCreateCheckbox.checked = hideOnCreate; hideOnEnterCheckbox.checked = hideOnEnter; ignoreHideListCheckbox.checked = ignoreHideList; capitalizeFirstLetterCheckbox.checked = originalCapitalizeFirstLetter; closeSettingsMenu(); }; // Чекбокс для включения/выключения хайда по Enter const hideOnEnterCheckbox = document.createElement("input"); hideOnEnterCheckbox.type = "checkbox"; hideOnEnterCheckbox.checked = hideOnEnter; hideOnEnterCheckbox.id = "hideOnEnterCheckbox"; const hideOnEnterLabel = document.createElement("label"); hideOnEnterLabel.textContent = "Добавлять хайд / yourWords по Enter"; hideOnEnterLabel.setAttribute("for", "hideOnEnterCheckbox"); hideOnEnterLabel.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; hideOnEnterLabel.style.fontSize = "12px"; hideOnEnterLabel.style.marginLeft = "-2px"; // Чекбокс для включения/выключения хайда по кнопке отправки const hideOnButtonCheckbox = document.createElement("input"); hideOnButtonCheckbox.type = "checkbox"; hideOnButtonCheckbox.checked = hideOnButton; hideOnButtonCheckbox.id = "hideOnButtonCheckbox"; hideOnButtonCheckbox.style.marginTop = "2px"; const hideOnButtonLabel = document.createElement("label"); hideOnButtonLabel.textContent = "Добавлять хайд / yourWords по кнопке отправки"; hideOnButtonLabel.setAttribute("for", "hideOnButtonCheckbox"); hideOnButtonLabel.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; hideOnButtonLabel.style.fontSize = "12px"; hideOnButtonLabel.style.marginLeft = "-2px"; // Чекбокс для включения/выключения хайда при создании темы const hideOnCreateCheckbox = document.createElement("input"); hideOnCreateCheckbox.type = "checkbox"; hideOnCreateCheckbox.checked = hideOnCreate; hideOnCreateCheckbox.id = "hideOnCreateCheckbox"; hideOnCreateCheckbox.style.marginTop = "2px"; const hideOnCreateLabel = document.createElement("label"); hideOnCreateLabel.textContent = "Добавлять хайд / yourWords при создании темы"; hideOnCreateLabel.setAttribute("for", "hideOnCreateCheckbox"); hideOnCreateLabel.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; hideOnCreateLabel.style.fontSize = "12px"; hideOnCreateLabel.style.marginLeft = "-2px"; // Чекбокс для добавления yourWords при создании темы const addWordsOnCreateCheckbox = document.createElement("input"); addWordsOnCreateCheckbox.type = "checkbox"; addWordsOnCreateCheckbox.checked = addWordsOnCreate; addWordsOnCreateCheckbox.id = "addWordsOnCreateCheckbox"; addWordsOnCreateCheckbox.style.marginTop = "6px"; const addWordsOnCreateLabel = document.createElement("label"); addWordsOnCreateLabel.textContent = "Добавлять yourWords при создании темы"; addWordsOnCreateLabel.setAttribute("for", "addWordsOnCreateCheckbox"); addWordsOnCreateLabel.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; addWordsOnCreateLabel.style.fontSize = "12px"; addWordsOnCreateLabel.style.marginLeft = "-2px"; addWordsOnCreateLabel.style.marginTop = "6px"; const addWordsContainer = document.createElement("div"); addWordsContainer.style.display = "flex"; addWordsContainer.append(addWordsOnCreateCheckbox, addWordsOnCreateLabel); const yourWordsHeader = document.createElement("h3"); yourWordsHeader.textContent = "Настройки yourWords"; yourWordsHeader.style.margin = "0"; yourWordsHeader.style.color = "white"; yourWordsHeader.style.position = "relative"; yourWordsHeader.style.top = "-5px"; yourWordsHeader.style.display = "inline-block"; yourWordsHeader.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; yourWordsHeader.style.fontWeight = "bold"; // Чекбокс "Игнорировать список хайда" const ignoreHideListCheckbox = document.createElement("input"); ignoreHideListCheckbox.type = "checkbox"; ignoreHideListCheckbox.checked = ignoreHideList; ignoreHideListCheckbox.id = "ignoreHideListCheckbox"; ignoreHideListCheckbox.style.marginTop = "2px"; const ignoreHideListLabel = document.createElement("label"); ignoreHideListLabel.textContent = "Игнорировать список хайда (вставлять только yourWords без хайда)"; ignoreHideListLabel.setAttribute("for", "ignoreHideListCheckbox"); ignoreHideListLabel.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; ignoreHideListLabel.style.fontSize = "12px"; ignoreHideListLabel.style.marginLeft = "-2px"; ignoreHideListLabel.style.position = "relative"; // Поле для ввода "yourwords" const yourWordsInput = document.createElement("input"); yourWordsInput.classList.add("textCtrl"); yourWordsInput.placeholder = "Ваши слова, перенос через <br>"; yourWordsInput.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; yourWordsInput.style.width = "100%"; yourWordsInput.style.marginBottom = "5px"; yourWordsInput.value = yourWords; // Чекбокс для капитализации первой буквы const capitalizeFirstLetterCheckbox = document.createElement("input"); capitalizeFirstLetterCheckbox.type = "checkbox"; capitalizeFirstLetterCheckbox.checked = capitalizeFirstLetter; capitalizeFirstLetterCheckbox.id = "capitalizeFirstLetterCheckbox"; capitalizeFirstLetterCheckbox.style.marginTop = "2px"; const capitalizeFirstLetterLabel = document.createElement("label"); capitalizeFirstLetterLabel.textContent = "Авто-заглавная буква (работает отдельно)"; capitalizeFirstLetterLabel.setAttribute("for", "capitalizeFirstLetterCheckbox"); capitalizeFirstLetterLabel.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Open Sans', HelveticaNeue, sans-serif"; capitalizeFirstLetterLabel.style.fontSize = "12px"; capitalizeFirstLetterLabel.style.marginLeft = "-2px"; // Выбор положения yourWords const wordsPositionSelect = document.createElement("select"); wordsPositionSelect.classList.add("textCtrl", "Lzt-PrettySelect"); wordsPositionSelect.id = "wordsPositionSelect"; wordsPositionSelect.style.marginBottom = "0px"; const wordsPositionOptions = availableWordsPositions.map((wordsPositionItem) => { const option = document.createElement("option"); option.value = wordsPositionItem; option.textContent = wordsPositionPhrases[wordsPositionItem]; option.selected = wordsPositionItem === wordsPosition; return option; }); const wordsPositionGroup = document.createElement("optgroup"); wordsPositionGroup.label = "Положение слов"; wordsPositionGroup.append(...wordsPositionOptions); wordsPositionSelect.append(wordsPositionGroup); wordsPositionContainer.append( yourWordsHeader, yourWordsInput, wordsPositionSelect, addWordsContainer ); // Добавляем чекбоксы и кнопки в меню настроек settingsMenu.appendChild(userIdInput); settingsMenu.appendChild(document.createElement("br")); settingsMenu.appendChild(hideOnEnterCheckbox); settingsMenu.appendChild(hideOnEnterLabel); settingsMenu.appendChild(document.createElement("br")); settingsMenu.appendChild(hideOnButtonCheckbox); settingsMenu.appendChild(hideOnButtonLabel); settingsMenu.appendChild(document.createElement("br")); settingsMenu.appendChild(hideOnCreateCheckbox); settingsMenu.appendChild(hideOnCreateLabel); settingsMenu.appendChild(document.createElement("br")); settingsMenu.appendChild(capitalizeFirstLetterCheckbox); settingsMenu.appendChild(capitalizeFirstLetterLabel); settingsMenu.appendChild(document.createElement("br")); settingsMenu.appendChild(wordsPositionContainer); settingsMenu.appendChild(ignoreHideListCheckbox); settingsMenu.appendChild(ignoreHideListLabel); settingsMenu.appendChild(document.createElement("br")); settingsMenu.appendChild(buttonsContainer); // Добавляем кнопки в контейнер buttonsContainer.appendChild(saveButton); buttonsContainer.appendChild(cancelButton); document.body.appendChild(settingsMenu); const $wordsPositionSelect = $(wordsPositionSelect); magicChosen($wordsPositionSelect); function closeSettingsMenu() { settingsMenu.style.opacity = 0; settingsMenu.style.transform = "translateY(-10px)"; setTimeout(() => { settingsMenu.style.visibility = "hidden"; }, 300); } // Автор копирования айди по кнопке в профиле https://lolz.live/el9in/ const followContainer = document.querySelector("div.followContainer") || document.querySelector("a.button.full.followContainer.OverlayTrigger"); if (followContainer) { const idContainer = document.createElement("div"); idContainer.className = "idContainer"; const idButton = document.createElement("a"); idButton.className = "idButton button block OverlayTrigger"; idButton.setAttribute("title", ""); idButton.setAttribute("id", ""); idButton.setAttribute("data-cacheoverlay", "false"); idButton.textContent = "Скопировать ID"; idContainer.appendChild(idButton); followContainer.insertAdjacentElement("afterend", idContainer); idButton.addEventListener("click", function () { const userContentLinks = document.querySelector("div.userContentLinks"); const firstLink = userContentLinks.querySelector("a.button:nth-child(2)"); const href = firstLink.getAttribute("href"); const hrefText = href.match(/\/(\d+)\//)[1]; if ((hrefText | 0) != 0) { const userId = hrefText | 0; navigator.clipboard .writeText(userId) .then(() => { // Уведомление об успешном копировании xfAlert("ID успешно скопирован: " + userId); }) .catch((err) => { // Обработка ошибок копирования console.error("Ошибка копирования: ", err); xfAlert("Ошибка копирования ID. Попробуйте еще раз."); }); } }); } })();