您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
快速填写预设文本到输入框,适用于所有https网站。
// ==UserScript== // @name 剪贴板 FillText // @namespace http://tampermonkey.net/ // @version 1.13 // @description 快速填写预设文本到输入框,适用于所有https网站。 // @author Unitiny // @match https://*/* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @grant GM_addValueChangeListener // @license MIT // ==/UserScript== let Global = {}; let GlobalDoms = {}; const GlobalKey = "fillTextGlobal"; const CSS = { flex: { bs: "space-between", start: "flex-start", end: "flex-end", center: "center", column: "column", row: "row" }, }; (function () { Global = getGlobal() Global.renderStatus = 1 loadResource() initStyle() setInputDom() operationBoard() Global.renderStatus = 0 getGlobalHook() })(); /** * 初始化 */ //设置input节点 function setInputDom() { let t = setInterval(() => { let downingKeys = []; let editKey = ""; let inputDoms = document.querySelectorAll('input'); inputDoms.forEach(function (dom, i) { dom.setAttribute(Global.attributeName, i) dom.addEventListener("click", function (event) { let d = event.target Global.curInputDom = d.getAttribute(Global.attributeName) if (Global.order === 1) { d.value = getSpanText(Global.curSpan) } }) dom.addEventListener("keydown", function (event) { //快捷键模式,按下Alt开始 if (event.key === "Alt") { downingKeys = [] downingKeys.push(event.key) editKey = event.key return } if (downingKeys.length > 0) { if (downingKeys.indexOf(event.key) !== -1) return; downingKeys.push(event.key) editKey += "+" + event.key getCurCateVal().spans.map(v => { if (editKey === v.key) { dom.value = getSpanText(v.index) || dom.value event.preventDefault() downingKeys = [] editKey = "" } }) return; } //编辑模式 let str = dom.value + event.key getCurCateVal().spans.map(v => { if (str === v.key.split("+").join("")) { dom.value = getSpanText(v.index) || dom.value event.preventDefault() //阻止写入该字符 } }) }) dom.addEventListener("keyup", function (event) { let i = downingKeys.indexOf(event.key) i !== -1 ? downingKeys.splice(i, 1) : null if (event.key === "Alt") { downingKeys = [] editKey = "" } }) }) GlobalDoms.inputDoms = inputDoms //有拿到inputDoms if (inputDoms.length > 0) { clearInterval(t) } }, 1000) } /** * 工具函数 */ function isOnline() { return !window.location.host.includes("localhost") && !window.location.host.includes("127.0.0.1") } //添加前缀来防止与原页面id重复 function prefixStr(str) { return `${Global.prefix}-${str}` } function getLink() { let link = document.createElement("link"); link.rel = "stylesheet"; link.href = "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0"; return link } function loadResource() { document.head.appendChild(getLink()); } function containKeys(a, b) { const aKeys = Object.keys(a); const bKeys = Object.keys(b); return aKeys.length >= bKeys.length && bKeys.every(key => aKeys.includes(key)); } function domCtl(showDoms, hiddenDoms) { showDoms?.forEach(v => { showDom(v) }) hiddenDoms?.forEach(v => { hiddenDom(v) }) } function emptyFunc() { } function getCloseSpan() { let close = document.createElement("span") close.style = CSS.iconStyle close.style.cssText += ` position: absolute; right: -9px; top: -14px;` close.innerText = "×" return close } /** * 样式区 */ function initStyle() { CSS.parentBoardStyle = ` ${flexStyle({jc: CSS.flex.start})} position: absolute; left: 0px; top: 0px; width: auto; overflow: auto; z-index:999;` CSS.boardStyle = ` ${flexStyle({jc: CSS.flex.bs, fd: CSS.flex.column})} position: relative; left: 0px; top: 0px; width: 330px; height: 400px; margin: 10px; background: white; border: 5px solid ${themeColor()}; border-radius: 5px; overflow: auto; z-index:999;` CSS.rightBoardStyle = ` ${flexStyle({jc: CSS.flex.end, fd: CSS.flex.column})} position: relative; left: 0px; top: 0px; width: 330px; height: 400px; margin: 10px; background: white; border: 5px solid ${themeColor()}; border-radius: 5px; overflow: auto; z-index:999;` CSS.hiddenBoardStyle = ` ${flexStyle({})} position: absolute; left: 0px; top: 0px; width: 40px; height: 40px; margin: 10px; border: 5px solid skyblue; border-radius: 50%; overflow: auto; color: white; background: skyblue; z-index:999; display: none;` CSS.divStyle = ` ${flexStyle({fd: CSS.flex.column})} width: 300px; height: 400px; margin: 10px; border: 1px solid skyblue; border-radius: 5px; overflow: auto` CSS.cateSpanStyle = ` margin: 3px; padding: 5px 12px; width: auto; height: 35px; border: 1px solid ${themeColor()}; border-radius: 5px; background: white; font-size: 16px; text-align: center; line-height: 33px; margin-right: 10px;` CSS.spanStyle = ` ${flexStyle({jc: CSS.flex.center, ai: CSS.flex.start, fd: CSS.flex.column})} flex-grow: 0; flex-shrink: 0; min-width: 250px; max-width: 250px; min-height: 100px; max-height: 100px; margin: 10px 20px; border: 1px solid ${themeColor()}; border-radius: 7px; height: 70px; padding: 0 10px 0 10px;` CSS.pStyle = ` word-break: break-all; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;` CSS.operationStyle = ` padding: 0 12px 0 12px; margin: 5px; width: auto; height: 35px; border-radius: 5px; background: #4bb84b; color: white; font-size: 16px; text-align: center; line-height: 33px; margin-right: 10px;` CSS.textArea = ` border: 1px solid ${themeColor()}; border-radius: 5px; flex-grow: 0; flex-shrink: 0; min-width: 90%; max-width: 90%; min-height: 100px; max-height: 100px; margin: 10px 5px 10px 5px;` CSS.iconStyle = ` font-family: 'Material Symbols Outlined'; font-weight: normal; font-style: normal; font-size: 24px; line-height: 1; letter-spacing: normal; text-transform: none; display: inline-block; white-space: nowrap; word-wrap: normal; direction: ltr; -webkit-font-feature-settings: 'liga'; -webkit-font-smoothing: antialiased;` CSS.spanSettingStyle = ` width: 100%; ${flexStyle({jc: CSS.flex.end})} ` CSS.displayNone = "display: none;" CSS.displayFlex = "display: flex;" CSS.borderRed = "border: 1px solid red;" CSS.borderSkyblue = "border: 1px solid skyblue;" } function themeColor() { return Global.theme ? "skyblue" : "black" } function isShow(show) { return show ? "" : CSS.displayNone } function showDom(dom, add = CSS.displayFlex) { dom.style.cssText = dom.style.cssText.replace(isShow(false), "") dom.style.cssText += add } function hiddenDom(dom) { dom.style.cssText += isShow(false) } function replaceStyle(dom, key, value) { let list = dom.style.cssText.split(";"); for (let i = 0; i < list.length; i++) { if (list[i].includes(key + ":")) { list[i] = `${key}:${value}` break } } dom.style.cssText = list.join(";") } function flexStyle({jc = CSS.flex.center, ai = CSS.flex.center, fd = CSS.flex.row}) { return `display: flex; justify-content: ${jc}; align-items: ${ai}; flex-direction: ${fd};` } /** * Global */ function defaultGlobal() { return { id: 0, version: Date.now(), renderStatus: 0, //1渲染中 order: 0, style: {}, parentShow: 0, show: 0, theme: true, curSpan: 0, curInputDom: 0, prefix: "fillText", attributeName: "data-fillText", hiddenKey: "Alt+q", inputDoms: [], boardChildNodes: 3, curCate: "default", category: [ { name: "default", setting: {}, spans: randSpans() }, { name: "常用", setting: {}, spans: [] } ] } } function checkGlobal(data) { return data && JSON.stringify(data) !== "{}" && containKeys(data, defaultGlobal()) } function saveGlobalInterval() { setInterval(function () { saveGlobal() }, 1000 * 30) } function getGlobalHook() { if (!isOnline()) { return } GM_addValueChangeListener(GlobalKey, function(name, old_value, new_value, remote) { console.log(name, old_value, new_value, remote) if(remote) { Global = getGlobal() Global.renderStatus = 1 //重新渲染 document.body.removeChild(GlobalDoms.parentBoard) document.body.removeChild(GlobalDoms.hiddenBoard) loadResource() initStyle() setInputDom() operationBoard() Global.renderStatus = 0 } }) } function saveGlobal(g = Global) { if (!isOnline() || Global.renderStatus === 1) { return false } console.log("saveGlobal", g) let lastG = GM_getValue(GlobalKey) if (!checkGlobal(lastG)) { g.version = Date.now() GM_setValue(GlobalKey, g) return true } if (checkGlobal(g)) { g.version = Date.now() GM_setValue(GlobalKey, g) return true } return false } function getGlobal() { if (!isOnline()) { return defaultGlobal(); } let data = GM_getValue(GlobalKey) if (!checkGlobal(data)) { saveGlobal(defaultGlobal()) return defaultGlobal() } return data } /** * 分类 */ function getCurCateVal() { for (const v of Global.category) { if (v.name === Global.curCate) { return v } } return Global.category[0] } function showCateInput() { let divDom = GlobalDoms.categoryAreaDom.getElementsByTagName("div")[0]; if (divDom.getElementsByClassName("cateInput").length > 0) { return } let el = document.createElement("input"); el.className = "cateInput" el.placeholder = "请输入内容,按回车添加" el.style.cssText = CSS.textArea replaceStyle(el, "border", `1px solid ${themeColor()}`) el.addEventListener("keydown", function (event) { if (event.key === "Enter") { if (addCategory(event.target.value)) { renderCateSpan() renderBoard(renderSpan()) // alert("添加分类成功!") event.stopImmediatePropagation() } } }) divDom.insertBefore(el, divDom.childNodes[0]) } function addCategory(name) { if (name.length > 10) { alert("分类名过长") return false } let has = false Global.category.forEach((v, i) => { if (v.name === name) { alert("已存在该分类") has = true return } }) if (has) return Global.category.push({ name: name, spansText: [], setting: {}, spans: [] }) Global.curCate = name saveGlobal() changeCurCateText() return true } function delCategory(name) { if (Global.category.length <= 1) { alert("必须有一个分类存在") return false } let index = 0 Global.category.map((v, i) => { if (v.name === name) { index = i } }) Global.category.splice(index, 1) if (name === Global.curCate) { Global.curCate = Global.category[0].name } saveGlobal() changeCurCateText() return true } function categoryList() { let divDom = GlobalDoms.categoryAreaDom.getElementsByTagName("div")[0]; if (divDom.getElementsByClassName(prefixStr("categoryList")).length > 0) { return } let list = [] for (let i = 0; i < Global.category.length; i++) { list.push(getCategorySpan(i, Global.category[i])) } let div = document.createElement("div") div.className = prefixStr("categoryList") div.setAttribute("id", prefixStr("categoryList")) div.style.cssText = `${flexStyle({jc: CSS.flex.start})}flex-flow:row wrap;width:80%; margin: 0 20px 10px 0px;` div.append(...list) divDom.insertBefore(div, divDom.childNodes[0]) toBottom() } function getCategorySpan(i, cate) { let close = getCloseSpan() close.addEventListener("click", function (event) { let curCate = Global.curCate if (delCategory(cate.name)) { if (cate.name === curCate) { renderBoard(renderSpan()) } renderCateSpan() event.stopImmediatePropagation() } }) let span = document.createElement("span") span.innerText = cate.name span.style.cssText = CSS.cateSpanStyle span.style.cssText += `position: relative;` span.addEventListener("click", function (event) { Global.curSpan = 0 Global.curCate = cate.name renderBoard(renderSpan()) changeCurCateText() }) span.appendChild(close) return span } function changeCurCateText() { document.getElementById(prefixStr("curCate")).innerText = `当前分类:${Global.curCate}` } function renderCateSpan() { let list = [] for (let i = 0; i < Global.category.length; i++) { list.push(getCategorySpan(i, Global.category[i])) } let div = document.getElementById(prefixStr("categoryList")) div.innerHTML = "" div.append(...list) return div } /** * 文本栏 */ //输入栏添加span function showInput() { // if (GlobalDoms.board.childNodes.length > GlobalDoms.boardChildNodes + 1) { // return // } let el = document.createElement("input"); el.placeholder = "请输入内容,按回车添加" el.style.cssText = CSS.textArea replaceStyle(el, "border", `1px solid ${themeColor()}`) el.addEventListener("keydown", function (event) { if (event.key === "Enter") { addSpan(event.target.value, {index: getCurCateVal().spans.length}) renderBoard(renderSpan()) toBottom() saveGlobal() } }) let divDom = GlobalDoms.textAreaDom.getElementsByTagName("div")[0]; divDom.insertBefore(el, divDom.childNodes[0]) toBottom() } function addSpan(text, { cancel = false, editKey = "", finish = false, index = 0, input = false, key = "", set = false, show = false }) { let s = createSpanData(text, getCurCateVal().spans.length) s.show = show s.input = input s.set = set s.finish = finish s.cancel = cancel s.index = index s.key = key s.editKey = editKey getCurCateVal().spans.push(s) } function createSpanData(text, i = 0) { return { text: text, cancel: false, editKey: "", finish: false, index: i, input: false, key: "", set: false, show: false, } } function randSpans() { if (isOnline()) { return [ createSpanData("账号: 123456"), createSpanData("密码: 123456"), createSpanData("点击输入框,再点击任意文本即可自动填写。也可设置快捷键填写。") ] } let list = [] for (let i = 0; i < Math.round(Math.random() * 10 + 3); i++) { let s = "" for (let j = 0; j < Math.round(Math.random() * 50 + 10); j++) { s += Math.round(Math.random() * 10).toString() } list.push(createSpanData(s, i)) } return list } function getSpanText(index) { return getCurCateVal().spans[index].text } function getSpans() { let list = [] for (let i = 0; i < getCurCateVal().spans.length; i++) { list.push(getSpan(i, getSpanText(i))) } return list } function getSpan(i, text) { let span = document.createElement("span") span.tabIndex = 0 span.innerHTML = ` <p style="${CSS.pStyle}">${text}</p> <div style="${CSS.spanSettingStyle}${isShow(getSpanData(i).show)}"> <input id="settingInput${i}" style="width: 80%; height: 30px;${isShow(getSpanData(i).input)}" type="text" placeholder="请按键设置" readonly> <span style="${CSS.iconStyle}${isShow(getSpanData(i).set)}">settings</span> <span style="${CSS.iconStyle}${isShow(getSpanData(i).finish)}">done</span> <span style="${CSS.iconStyle}${isShow(getSpanData(i).cancel)}">close</span> </div> ` span.style.cssText = CSS.spanStyle replaceStyle(span, "border", `1px solid ${themeColor()}`) span.addEventListener("click", function (event) { selectSpan(i) span.removeEventListener("keydown", moveSpan) span.addEventListener("keydown", moveSpan) if (Global.order === 0) { let target = `${Global.attributeName}="${Global.curInputDom}"` let element = document.querySelector(`input[${target}]`); element.value = text } }) let childSpan = span.getElementsByTagName("span") childSpan[0].addEventListener("click", function () { settingCtl({input: true, set: false, finish: true, cancel: true, index: i}) }) childSpan[1].addEventListener("click", function () { saveKey(i) }) childSpan[2].addEventListener("click", function () { cancel(i) }) return span } function selectSpan(i = Global.curSpan) { let spanList = getCurCateVal().spanList if (spanList.length === 0 || spanList.childNodes.length === 0) { return } let spanNodes = spanList.childNodes replaceStyle(spanNodes[Global.curSpan], "border", `1px solid ${themeColor()}`) Global.curSpan = i replaceStyle(spanNodes[Global.curSpan], "border", "1px solid red") } function moveSpan(event) { if (event.altKey) { let arrow = 0 if (event.key === 'ArrowDown') { if (Global.curSpan >= getCurCateVal().spans.length - 1) { return } arrow = 1 } else if (event.key === 'ArrowUp') { if (Global.curSpan <= 0) { return } arrow = -1 } if (arrow !== 0) { let target = Global.curSpan + arrow let s = getCurCateVal().spans[Global.curSpan] getCurCateVal().spans.splice(Global.curSpan, 1) getCurCateVal().spans.splice(target, 0, s) exchangeSpanText(Global.curSpan, target) selectSpan(target) Global.curSpan = target // moveSpan无法多次触发问题,好bug,找了好久 // 由于之前selectSpan()写法会先移除moveSpan事件,导致当前执行的moveSpan直接return了, // 无法触发后面添加moveSpan逻辑。 } } } function exchangeSpanText(i, j) { let spanNodes = getCurCateVal().spanList.childNodes let a = spanNodes[i].getElementsByTagName("p")[0] let b = spanNodes[j].getElementsByTagName("p")[0] let t = a.innerText a.innerText = b.innerText b.innerText = t } function delSpan() { getCurCateVal().spans.splice(Global.curSpan, 1) Global.curSpan = 0 renderBoard(renderSpan()) saveGlobal() } function delAllSpan() { getCurCateVal().spans = [] renderBoard(renderSpan()) saveGlobal() } function renderSpan() { let div = document.createElement("div"); div.setAttribute("id", "textSpanList") div.style.cssText = flexStyle({fd: CSS.flex.column}) div.append(...getSpans()) getCurCateVal().spanList = div return div } function getSpanData(index) { return index >= 0 ? getCurCateVal().spans[index] : getCurCateVal().setting } /** * 快捷键 */ function changeOrder() { let d = document.getElementById(prefixStr("orderOperation")) d.innerText = d.innerText === "先填后选" ? "先选后填" : "先填后选" Global.order = Global.order ? 0 : 1 saveGlobal() } function editKey() { settingCtl({show: !getCurCateVal().setting.show, set: !getCurCateVal().setting.set}) } function settingCtl({show = true, input = false, set = true, finish = false, cancel = false, index = -1}) { if (index !== -1) { //单span控制 let span = getCurCateVal().spans[index] getCurCateVal().spans[index].show = show getCurCateVal().spans[index].input = input getCurCateVal().spans[index].set = set getCurCateVal().spans[index].finish = finish getCurCateVal().spans[index].cancel = cancel } else { //全局控制 getCurCateVal().setting.show = show getCurCateVal().setting.input = input getCurCateVal().setting.set = set getCurCateVal().setting.finish = finish getCurCateVal().setting.cancel = cancel getCurCateVal().spans.map(v => { v.show = show v.input = input v.set = set v.finish = finish v.cancel = cancel }) } renderBoard(renderSpan()) if (input) { listenKey(index) } //阻止冒泡 let event = window.event || arguments.callee.caller.arguments[0]; event.stopPropagation() } function listenKey(index) { let ss = getSpanData(index) let input = document.getElementById("settingInput" + index); input.focus() input.value = ss.key ss.editKey = ss.key let downingKeys = [] //按下未松开的keys input.addEventListener("keydown", function (event) { if (event.key === "Backspace") { //如果存在,则移除按下中的key let i = downingKeys.indexOf(event.key) i !== -1 ? downingKeys.splice(i, 1) : null let arr = ss.editKey.split("+") arr.pop() ss.editKey = arr.join("+") } else if (!downingKeys.includes(event.key)) { if (ss.editKey === "") { ss.editKey += event.key } else { ss.editKey += "+" + event.key } downingKeys.push(event.key) } input.value = ss.editKey }); input.addEventListener("keyup", function (event) { if (event.key !== "Backspace") { let i = downingKeys.indexOf(event.key) i !== -1 ? downingKeys.splice(i, 1) : null } }); let event = window.event || arguments.callee.caller.arguments[0]; event.stopPropagation() } function saveKey(index) { let ss = getSpanData(index) let has = false getCurCateVal().spans.map(v => { if (v.key === ss.editKey && v.index !== ss.index) { alert(`文本 ${getSpanText(v.index)} 已设置该快捷键`) has = true } }) if (!has) { ss.key = ss.editKey ss.editKey = "" settingCtl({index: index}) } saveGlobal() } function cancel(index) { let ss = getSpanData(index) ss.editKey = "" settingCtl({index: index}) } /** * 右侧操作面板 */ function rightOperateBoard() { let b = document.createElement("div"); b.style.cssText = CSS.rightBoardStyle b.setAttribute("id", "fillTextOperateBoard") GlobalDoms.textAreaDom = textArea() GlobalDoms.categoryAreaDom = categoryArea() GlobalDoms.settingAreaDom = settingArea() domCtl([], [GlobalDoms.textAreaDom, GlobalDoms.categoryAreaDom, GlobalDoms.settingAreaDom]) b.appendChild(GlobalDoms.textAreaDom) b.appendChild(GlobalDoms.categoryAreaDom) b.appendChild(GlobalDoms.settingAreaDom) GlobalDoms.rightBoard = b return b } function textArea() { let operation = document.createElement("div") operation.style.width = "100%" operation.style.cssText += flexStyle({}) operation.innerHTML = ` <div id="${prefixStr("bottomOperation")}"> <div style="${flexStyle({jc: CSS.flex.start})}margin: 0 20px 10px 0px;flex-flow:row wrap;"> <span style="${CSS.operationStyle}" >快捷键</span> <span style="${CSS.operationStyle}">添加</span> <span style="${CSS.operationStyle}background: #ea5c5c;">删除</span> <span style="${CSS.operationStyle}margin-right: 0px;background: #ea5c5c;">清空</span> </div> <div style="${flexStyle({jc: CSS.flex.start})}flex-flow:row wrap;"> <span style="${CSS.operationStyle}">隐藏</span> </div> </div>` let list = [editKey, showInput, delSpan, delAllSpan, domCtl] list.forEach((v, i) => { if (v.name === "domCtl") { operation.getElementsByTagName("span")[i].addEventListener("click", function () { v([], [GlobalDoms.rightBoard]) }) return } operation.getElementsByTagName("span")[i].addEventListener("click", v) }) return operation } function categoryArea() { let operation = document.createElement("div") operation.style.width = "100%" operation.style.cssText += flexStyle({}) operation.style.cssText += "flex-flow:row wrap;" operation.innerHTML = ` <div id="${prefixStr("bottomOperation")}"> <div style="${flexStyle({jc: CSS.flex.start})}margin: 0 20px 10px 0px;flex-flow:row wrap;"> <span style="${CSS.operationStyle}">添加分类</span> <span style="${CSS.operationStyle}margin-right: 0px;">分类列表</span> <span id="${prefixStr("curCate")}" style="${CSS.operationStyle}">当前分类:${Global.curCate}</span> </div> <div style="${flexStyle({jc: CSS.flex.start})}flex-flow:row wrap;"> <span style="${CSS.operationStyle}">隐藏</span> </div> </div>` let list = [showCateInput, categoryList, emptyFunc, domCtl] list.forEach((v, i) => { if (v.name === "domCtl") { operation.getElementsByTagName("span")[i].addEventListener("click", function () { v([], [GlobalDoms.rightBoard]) }) return } operation.getElementsByTagName("span")[i].addEventListener("click", v) }) return operation } function settingArea() { let operation = document.createElement("div") operation.style.width = "100%" operation.style.cssText += flexStyle({}) operation.style.cssText += "flex-flow:row wrap;" operation.innerHTML = ` <div id="${prefixStr("bottomOperation")}"> <div style="${flexStyle({jc: CSS.flex.start})}margin: 0 20px 10px 0px;flex-flow:row wrap;"> <span style="${CSS.operationStyle}">⬆</span> <span style="${CSS.operationStyle}">⬇</span> <span style="${CSS.operationStyle}">说明</span> <span id="${prefixStr("orderOperation")}" style="${CSS.operationStyle}">先填后选</span> <span id="${prefixStr("orderOperation")}" style="${CSS.operationStyle}margin-right: 0px;">编辑隐藏快捷键</span> </div> <div style="${flexStyle({jc: CSS.flex.start})}flex-flow:row wrap;"> <span style="${CSS.operationStyle}">隐藏</span> </div> </div>` let list = [changeBoardHeight, changeBoardHeight, doc, changeOrder, showEditKeyInput, domCtl] list.forEach((v, i) => { if (v.name === "changeBoardHeight") { operation.getElementsByTagName("span")[i].addEventListener("click", function () { i % 2 === 0 ? v(40) : v(-40) }) } else if (v.name === "domCtl") { operation.getElementsByTagName("span")[i].addEventListener("click", function () { v([], [GlobalDoms.rightBoard]) }) } else if (v.name === "showEditKeyInput") { operation.getElementsByTagName("span")[i].addEventListener("click", v) } else { operation.getElementsByTagName("span")[i].addEventListener("click", v) } }) return operation } function showEditKeyInput() { let divDom = GlobalDoms.settingAreaDom.getElementsByTagName("div")[0]; if (divDom.getElementsByClassName("editKeyInput").length > 0) { return } let inputDom = document.createElement("div"); inputDom.className = "editKeyInput" inputDom.innerHTML = ` <input id="editKeyInput" style="width: 80%; height: 30px;" type="text" value="${Global.hiddenKey}" placeholder="请按键设置" readOnly> ` divDom.insertBefore(inputDom, divDom.childNodes[0]) listenHiddenKey() } function listenHiddenKey() { let input = GlobalDoms.settingAreaDom.getElementsByTagName("input")[0] input.focus() input.value = Global.hiddenKey let editKey = "" let downingKeys = [] //按下未松开的keys input.addEventListener("keydown", function (event) { if (event.key === "Backspace") { //如果存在,则移除按下中的key let i = downingKeys.indexOf(event.key) i !== -1 ? downingKeys.splice(i, 1) : null let arr = editKey.split("+") arr.pop() editKey = arr.join("+") } else if(event.key === "Enter") { let arr = editKey.split("+") if(arr.length === 2 && arr[0] === "Alt" && arr[1] !== "Alt") { Global.hiddenKey = editKey let divDom = GlobalDoms.settingAreaDom.getElementsByTagName("div")[0] divDom.removeChild(divDom.getElementsByTagName("div")[0]) saveGlobal() } else { alert("只能设置为Alt+任意键,长度为2") } } else if (!downingKeys.includes(event.key)) { if (editKey === "") { editKey += event.key } else { editKey += "+" + event.key } downingKeys.push(event.key) } input.value = editKey }); input.addEventListener("keyup", function (event) { if (event.key !== "Backspace") { let i = downingKeys.indexOf(event.key) i !== -1 ? downingKeys.splice(i, 1) : null } }); let event = window.event || arguments.callee.caller.arguments[0]; event.stopPropagation() } /** * 控制面板 */ function changeBoardHeight(h) { GlobalDoms.board.style.height = parseInt(GlobalDoms.board.style.height) + h + "px" } function renderBoard(spanListDom) { GlobalDoms.board.replaceChild(spanListDom, GlobalDoms.board.childNodes[1]) let l = GlobalDoms.board.childNodes.length if (l > GlobalDoms.boardChildNodes) { for (let i = GlobalDoms.boardChildNodes; i < l; i++) { GlobalDoms.board.removeChild(GlobalDoms.board.lastChild) } } selectSpan() } function modeCtl() { if (Global.theme) { Global.theme = false replaceStyle(GlobalDoms.board, "border", `5px solid ${themeColor()}`) getCurCateVal().spanList.childNodes.forEach(v => { replaceStyle(v, "border", `1px solid ${themeColor()}`) }) return } Global.theme = true replaceStyle(GlobalDoms.board, "border", `5px solid ${themeColor()}`) getCurCateVal().spanList.childNodes.forEach(v => { replaceStyle(v, "border", `1px solid ${themeColor()}`) }) saveGlobal() } function topOperation() { let operation = document.createElement("div") operation.style.width = "100%" operation.innerHTML = ` <div id="${prefixStr("topOperation")}" style="${flexStyle({jc: CSS.flex.end})}margin: 0 20px 10px 0px;"> <span style="${CSS.iconStyle}font-size: 20px;">light_mode</span> <span style="${CSS.iconStyle}">expand_more</span> <span style="${CSS.iconStyle}">remove</span> </div>` let childSpan = operation.getElementsByTagName("span") childSpan[0].addEventListener("click", modeCtl) childSpan[1].addEventListener("click", toBottom) childSpan[2].addEventListener("click", function () { parentBoardCtl(1) }) return operation } function bottomOperation() { let operation = document.createElement("div") operation.style.width = "100%" operation.innerHTML = ` <div id="${prefixStr("bottomOperation")}"> <div style="${flexStyle({jc: CSS.flex.end})}margin: 0 20px 10px 0px;"> <span style="${CSS.operationStyle}" >快捷键</span> <span style="${CSS.operationStyle}">添加</span> <span style="${CSS.operationStyle}background: #ea5c5c;">删除</span> <span style="${CSS.operationStyle}margin-right: 0px;background: #ea5c5c;">清空</span> </div> <div style="${flexStyle({jc: CSS.flex.end})}margin: 0 20px 10px 0px;"> <span style="${CSS.operationStyle}">说明</span> <span style="${CSS.operationStyle}">保存配置</span> <span id="${prefixStr("orderOperation")}" style="${CSS.operationStyle}margin-right: 0px;">先填后选</span> </div> <div style="${flexStyle({jc: CSS.flex.end})}margin: 0 20px 10px 0px;"> <span style="${CSS.operationStyle}">⬆</span> <span style="${CSS.operationStyle}">⬇</span> <span style="${CSS.operationStyle}">添加分类</span> <span style="${CSS.operationStyle}margin-right: 0px;">分类列表</span> </div> <div style="${flexStyle({jc: CSS.flex.end})}margin: 0 20px 10px 0px;"> <span id="${prefixStr("curCate")}" style="${CSS.operationStyle}margin-right: 0px;">当前分类:${Global.curCate}</span> </div> </div>` let list = [editKey, showInput, delSpan, delAllSpan, doc, saveGlobal, changeOrder, changeBoardHeight, changeBoardHeight, showCateInput, categoryList] list.forEach((v, i) => { if (v.name === "changeBoardHeight") { operation.getElementsByTagName("span")[i].addEventListener("click", function () { i % 2 === 0 ? v(40) : v(-40) }) } else if (v.name === "saveGlobal") { operation.getElementsByTagName("span")[i].addEventListener("click", function () { if (saveGlobal()) { alert(`保存成功!`) } else { alert(`配置数据太旧,无法保存。请刷新页面后再编辑保存`) } }) } else { operation.getElementsByTagName("span")[i].addEventListener("click", v) } }) return operation } function bottomOperationV2() { let operation = document.createElement("div") operation.style.width = "100%" operation.innerHTML = ` <div id="${prefixStr("bottomOperationV2")}"> <div style="${flexStyle({jc: CSS.flex.end})}margin: 0 20px 10px 0px;"> <span style="${CSS.operationStyle}" >文本</span> <span style="${CSS.operationStyle}">分类</span> <span style="${CSS.operationStyle}margin-right: 0px;">设置</span> </div> </div>` let list = [domCtl, domCtl, domCtl] list.forEach((v, i) => { if (i === 0) { operation.getElementsByTagName("span")[i].addEventListener("click", function () { v([GlobalDoms.rightBoard], []) v([GlobalDoms.textAreaDom], [GlobalDoms.categoryAreaDom, GlobalDoms.settingAreaDom]) }) } else if (i === 1) { operation.getElementsByTagName("span")[i].addEventListener("click", function () { v([GlobalDoms.rightBoard], []) v([GlobalDoms.categoryAreaDom], [GlobalDoms.textAreaDom, GlobalDoms.settingAreaDom]) }) } else if (i === 2) { operation.getElementsByTagName("span")[i].addEventListener("click", function () { v([GlobalDoms.rightBoard], []) v([GlobalDoms.settingAreaDom], [GlobalDoms.textAreaDom, GlobalDoms.categoryAreaDom]) }) } }) return operation } function board() { let b = document.createElement("div"); b.style.cssText = CSS.boardStyle b.setAttribute("id", "fillTextBoard") b.appendChild(topOperation()) b.appendChild(renderSpan()) b.appendChild(bottomOperationV2()) GlobalDoms.board = b return b } function hiddenBoard() { let hb = document.createElement("div") hb.style.cssText = CSS.hiddenBoardStyle hb.setAttribute("id", "fillTextHiddenBoard") hb.innerHTML = `<span style="${CSS.iconStyle}font-size:30px;pointer-events: none;">add</span>` hb.addEventListener("click", function () { parentBoardCtl(0) }) GlobalDoms.hiddenBoard = hb return hb } // 两个boardCtl优化为domCtl方法 function boardCtl(show) { if (show === 0) { hiddenDom(GlobalDoms.hiddenBoard) showDom(GlobalDoms.board) } else if (show === 1) { hiddenDom(GlobalDoms.board) showDom(GlobalDoms.hiddenBoard) } else if (show === -1) { hiddenDom(GlobalDoms.board) hiddenDom(GlobalDoms.hiddenBoard) } Global.show = show saveGlobal() } function parentBoardCtl(show) { if (show === 0) { hiddenDom(GlobalDoms.hiddenBoard) showDom(GlobalDoms.parentBoard) } else if (show === 1) { hiddenDom(GlobalDoms.parentBoard) showDom(GlobalDoms.hiddenBoard) } else if (show === -1) { hiddenDom(GlobalDoms.parentBoard) hiddenDom(GlobalDoms.hiddenBoard) } Global.parentShow = show saveGlobal() } function parentBoard() { let b = document.createElement("div"); b.style.cssText = CSS.parentBoardStyle b.setAttribute("id", "fillTextParentBoard") b.appendChild(board()) b.appendChild(rightOperateBoard()) GlobalDoms.parentBoard = b return b } //操作面板 function operationBoard() { document.body.appendChild(parentBoard()) document.body.appendChild(hiddenBoard()) document.body.removeEventListener("keydown", listenBodyKey) document.body.addEventListener("keydown", listenBodyKey) parentBoardCtl(Global.parentShow) moveDom(GlobalDoms.parentBoard) domCtl([GlobalDoms.board], [GlobalDoms.rightBoard]) } /** * 响应事件区 */ function listenBodyKey (event) { if (event.altKey) { if ("Alt+" + event.key === Global.hiddenKey) { Global.parentShow === -1 ? parentBoardCtl(0) : parentBoardCtl(-1) } } } function toBottom() { GlobalDoms.board.scrollTop = GlobalDoms.board.scrollHeight } function moveDom(dom) { let isDragging = false; let x, y; dom.addEventListener("mousedown", function (event) { isDragging = true; x = event.x; y = event.y; }); dom.addEventListener("mousemove", function (event) { if (isDragging) { let offsetX = event.x - x; let offsetY = event.y - y; dom.style.left = parseInt(dom.style.left) + offsetX + "px"; dom.style.top = parseInt(dom.style.top) + offsetY + "px"; x = event.x y = event.y } }); dom.addEventListener("mouseup", function () { isDragging = false; }); } function doc() { alert("面板隐藏快捷键默认为Alt+q,可自行更改(只能设置为Alt+任意键,修改后按下Enter保存)\n快捷键建议Alt开头或纯字母数字,如:Alt+1、qq、11\n") }