您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
tweaks layout of the chat
当前为
// ==UserScript== // @name Camamba Chat Tweaks // @namespace dannysaurus.camamba // @version 0.1 // @description tweaks layout of the chat // @license MIT License // @include https://www.camamba.com/chat/ // @include https://www.de.camamba.com/chat/ // @grant GM.getValue // @grant GM.setValue // ==/UserScript== /* jslint esnext: true */ (function() { 'use strict'; // --- initial sizes --- const SIZES = { FONT_EM: { userList: 1.2, chatBox: 1.8, }, WIDTH_EM: { sidebarLeft: 10, sidebarRight: 14, }, }; // --- HTML Selector Helpers --- const containers = (() => { const SELECTORS = { ID: { userList: 'userList', chatBox: 'chatBox', chatWindow: 'chatWindow', mediaContainer1 : 'mediaContainer1', mediaContainer2 : 'mediaContainer2', mediaContainer3 : 'mediaContainer3', mediaContainer4 : 'mediaContainer4', mediaContainer5 : 'mediaContainer5', mediaContainer6 : 'mediaContainer6', mediaContainer7 : 'mediaContainer7', mediaContainer8 : 'mediaContainer8', }, CLASS: { noTextSelect: 'noTextSelect', borderBox: 'borderBox', camBox: 'camBox' } }; let userList, chatBox, sidebars, camslots; return { get userList() { if (typeof userList === "undefined") { userList = document.getElementById(SELECTORS.ID.userList); } return userList; }, get chatBox() { if (typeof chatBox === "undefined") { chatBox = document.getElementById(SELECTORS.ID.chatBox); } return chatBox; }, get sidebars() { if (typeof sidebars === "undefined") { sidebars = document.getElementById(SELECTORS.ID.chatWindow).querySelectorAll(`.${SELECTORS.CLASS.noTextSelect}`); } return sidebars; }, get sidebarLeft() { return this.sidebars[0]; }, get sidebarTop() { return this.sidebars[1]; }, get sidebarRight() { return this.sidebars[2]; }, get camslots() { if (typeof camslots === "undefined") { const parentContainers = [ SELECTORS.ID.mediaContainer1, SELECTORS.ID.mediaContainer2, SELECTORS.ID.mediaContainer3, SELECTORS.ID.mediaContainer4, SELECTORS.ID.mediaContainer5, SELECTORS.ID.mediaContainer6, SELECTORS.ID.mediaContainer7, SELECTORS.ID.mediaContainer8, ] .map(id => document.getElementById(id)) .filter(el => el !== null) .map(el => el.parentNode); camslots = [ ...new Set(parentContainers)]; } return camslots; } }; })(); // --- HTML Create Element Helpers --- const addNewInput = ({ parentElement, type, id, initialValue, labelText }) => { const div = parentElement.appendChild(document.createElement('div')); const input = document.createElement('input'); input.type = type; input.id = id; input.style.backgroundColor = 'rgba(39,62,77,1)'; const label = document.createElement('label'); label.htmlFor = id; label.appendChild(document.createTextNode(labelText)); div.appendChild(input); div.appendChild(label); return input; }; const addNewInputPersistent = ({ parentElement, type, id, initialValue, labelText }) => { const input = addNewInput({ parentElement, type, id, initialValue, labelText }); input.updateValue = () => GM.getValue(input.id, initialValue).then(value => { input.value = value; }); input.addEventListener('input', () => { GM.setValue(input.id, input.value); }); return input; }; const addNewCheckbox = ({ parentElement, id, initialChecked, labelText }) => { const checkbox = addNewInput({ parentElement, type:'checkbox', id, initialValue: '', labelText }); checkbox.updateValue = () => GM.getValue(checkbox.id, !!initialChecked).then(isChecked => { checkbox.checked = !!isChecked; }); checkbox.addEventListener('click', () => { GM.setValue(checkbox.id, checkbox.checked); }); return checkbox; }; const addNewSpinner = ({ parentElement, id, initialValue, min, max, step, labelText }) => { const spinner = addNewInputPersistent({ parentElement, type:'number', id, initialValue, labelText }); spinner.min = min; spinner.max = max; spinner.step = step; return spinner; }; // --- Main --- const layoutPatcher = new class { constructor() { this.historyCamslotsRemoved = []; } initControls() { const sidebarLeftCenter = containers.sidebarLeft.children[1]; sidebarLeftCenter.innerHTML = ""; const container = sidebarLeftCenter.appendChild(document.createElement('div')); // checkbox camslots on/off const cbCamslots = addNewCheckbox({ parentElement: container, id: 'cb-camslots', initialChecked: true, labelText: 'camslots' }); const updateCbCamslots = () => { if (cbCamslots.checked) { this.showCamslots(); } else { this.hideCamslots(); } }; cbCamslots.addEventListener('click', () => updateCbCamslots()); cbCamslots.updateValue().then(() => updateCbCamslots()); // spinner userlist font const spinnerUserlistFont = addNewSpinner({ parentElement: container, id: 'spinner-userlist-font', initialValue: SIZES.FONT_EM.userList, min: 1.0, max: 2.2, step: 0.1, labelText: 'users' }); const updateSpinnerUserlistFont = () => { const fontSize = `${spinnerUserlistFont.value}em`; this.setFontSizeOfUserList(fontSize); }; spinnerUserlistFont.addEventListener('input', () => updateSpinnerUserlistFont()); spinnerUserlistFont.updateValue().then(() => updateSpinnerUserlistFont()); // spinner chat font const spinnerChatFont = addNewSpinner({ parentElement: container, id: 'spinner-chat-font', initialValue: SIZES.FONT_EM.chatBox, min: 1.0, max: 2.2, step: 0.1, labelText: 'chat' }); const updateSpinnerChatFont = () => { const fontSize = `${spinnerChatFont.value}em`; this.setFontSizeOfChat(fontSize); }; spinnerChatFont.addEventListener('input', () => updateSpinnerChatFont()); spinnerChatFont.updateValue().then(() => updateSpinnerChatFont()); } patchSizes() { // this.setWidthOfSidebarLeft(`${SIZES.WIDTH_EM.sidebarLeft}em`); this.setWidthOfSidebarRight(`${SIZES.WIDTH_EM.sidebarRight}em`); return this; } setFontSizeOfUserList(fontSize) { containers.userList.style.fontSize = fontSize; return this; } setFontSizeOfChat(fontSize) { containers.chatBox.style.fontSize = fontSize; return this; } setWidthOfSidebarLeft(width) { containers.sidebarLeft.style.width = width; return this; } setWidthOfSidebarRight(width) { containers.sidebarLeft.style.width = width; return this; } showCamslots() { for (let i = 0; i < this.historyCamslotsRemoved.length; i++) { const { parent, index, element } = this.historyCamslotsRemoved.pop(); parent.insertBefore(element, parent.children[index]); } return this; } hideCamslots() { for (let element of containers.camslots) { const parent = element.parentNode; if (parent) { let index = Array.from(parent.children).indexOf(element); parent.removeChild(element); this.historyCamslotsRemoved.push({ parent, index, element }); } } return this; } }(); const hookIntoInitSettings = (onInitSettings, timeOutRetryMillis) => { if (typeof initSettings === "undefined") { setTimeout(() => { hookIntoInitSettings(); }, timeOutRetryMillis); } /* eslint-disable no-undef */ const originalInitSettings = initSettings; initSettings = () => { /* eslint-enable no-undef */ originalInitSettings(); onInitSettings(); }; }; hookIntoInitSettings(() => { layoutPatcher.patchSizes(); }, 350); layoutPatcher.patchSizes(); layoutPatcher.initControls(); })();