您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
向网页中插入一个侧边按钮和一个弹窗
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/473443/1237616/popup-inject.js
// @name popup-inject // @description 向网页中插入一个侧边按钮和一个弹窗 // @version 1.0.5 // @author paso ;(function () { 'use strict' const _injectHtml = (config, resolve) => { document.head.insertAdjacentHTML( 'beforeend', ` <style> .${config.namespace} { color: black; } .${config.namespace} * { box-sizing: border-box; } .${config.namespace} *::-webkit-scrollbar { width: 8px; height: 8px; } .${config.namespace} *::-webkit-scrollbar-thumb { border-radius: 4px; background-color: rgba(0, 0, 0, 0.5); } .${config.namespace} *::-webkit-scrollbar-track { border-radius: 4px; background-color: transparent; } .${config.namespace} .flex { display: flex; flex-direction: row; align-items: stretch; justify-content: flex-start; } .${config.namespace} .flex.col { flex-direction: column; } .${config.namespace} .sticky-bar { position: fixed; top: ${config.location}; left: 0; transform: translateX(calc(12px - ${config.collapse})); z-index: 99999999; background: #3D7FFF; color: white; padding: 2px 10px 2px 4px; cursor: pointer; user-select: none; border-radius: 0 12px 12px 0; box-shadow: 0 2px 4px 1px #0006; transition: transform 0.5s ease; } .${config.namespace} .sticky-bar:hover { transform: none; } .${config.namespace} .mask { position: fixed; inset: 0; padding: 24px; overflow: auto; z-index: 99999999; background-color: rgba(0, 0, 0, 0.4); display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity .6s; } .${config.namespace}.open .mask { opacity: 1; pointer-events: all; } .${config.namespace} .popup { position: relative; margin: auto; padding: 16px; background: #f0f2f5; border-radius: 2px; box-shadow: 0 1px 12px 2px rgba(0, 0, 0, 0.4); transform: scale(0); transition: transform .3s; } .${config.namespace}.open .popup { transform: scale(1); } .${config.namespace} label { margin-top: .5em; margin-bottom: 0; user-select: none; } .${config.namespace} .monospace { font-family: v-mono, Consolas, SFMono-Regular, Menlo, Courier, v-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif, monospace, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; } .${config.namespace} .button { user-select: none; min-width: unset; min-height: unset; margin: unset; padding: 4px 16px; color: #fff; border: 1px solid #3D7FFF; border-radius: 2px; background: #3D7FFF; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12); box-shadow: 0 2px 0 rgba(0, 0, 0, 0.05); } .${config.namespace} textarea { background: white; resize: vertical; } .${config.namespace} .input, .${config.namespace} .button { height: 32px; transition: all 0.3s, height 0s; } .${config.namespace} .button:before, .${config.namespace} .button:after { content: none; } .${config.namespace} .button:hover, .${config.namespace} .button:focus { border-color: #669eff; background: #669eff; } .${config.namespace} .button:active { border-color: #295ed9; background: #295ed9; } .${config.namespace} .input { padding: 4px 8px; background: white; border: 1px solid #d9d9d9; border-radius: 2px; } .${config.namespace} .input:hover { border-color: #669eff; outline: 0; } .${config.namespace} .input:focus { border-color: #669eff; box-shadow: 0 0 0 2px rgba(61, 127, 255, 0.2); border-right-width: 1px; outline: 0; } ${config.style.replaceAll(/<\/?style>/g, '')} </style>` ) const container = createElement('div', { class: config.namespace }) const stickyBar = createElement('div', { class: 'sticky-bar' }, config.actionName) const mask = createElement('div', { class: 'mask' }) const popup = createElement('div', { class: 'popup flex col' }, config.content) container.append(stickyBar, mask) mask.append(popup) mask.onclick = () => { container.classList.remove('open') config.onPopHide && config.onPopHide() } popup.onclick = (e) => e.stopPropagation() const _data = { stickyBarHeight: 0, innerOffset: 0, stickyBarClick: false } const stickyMouseMove = (e) => { _data.stickyBarClick = false requestAnimationFrame(() => { let height = document.documentElement.clientHeight - _data.stickyBarHeight let newTop = e.pageY - _data.innerOffset if (newTop >= 0 && newTop <= height) { stickyBar.style.top = `${newTop}px` } }) } const stickyMouseUp = leftKey(() => { document.removeEventListener('mousemove', stickyMouseMove) document.removeEventListener('mouseup', stickyMouseUp) }) stickyBar.onmousedown = leftKey((e) => { _data.stickyBarClick = true const stickyBarStyle = window.getComputedStyle(stickyBar) _data.innerOffset = e.pageY - getNumber(stickyBarStyle.top) _data.stickyBarHeight = stickyBar.clientHeight + getNumber(stickyBarStyle.borderTopWidth) + getNumber(stickyBarStyle.borderBottomWidth) document.addEventListener('mousemove', stickyMouseMove) document.addEventListener('mouseup', stickyMouseUp) }) stickyBar.onmouseup = leftKey((e) => { if (_data.stickyBarClick) { _data.stickyBarClick = false container.classList.add('open') config.onPopShow && config.onPopShow() } stickyMouseUp() e.stopPropagation() }) document.body.append(container) // ---- other code resolve && resolve({ container, stickyBar, mask, popup }) } function createElement(tag, attrs, children) { const el = document.createElement(tag) if (attrs) { Object.entries(attrs).forEach(([k, v]) => { el.setAttribute(k, v) }) } if (children instanceof HTMLElement) { el.append(children) } else if (typeof children === 'string') { el.innerHTML = children } return el } function leftKey(fn) { return (...args) => { let key = args && args[0] && args[0].button if (key === 0 || key === void 0) { fn.apply(this, args) } } } function getNumber(str) { if (str) { let mArr = str.match(/\d+(\.\d*)?|\.\d+/) if (mArr && mArr.length) { return parseFloat(mArr[0]) } } return void 0 } function _checkConfig(config) { if (!config) throw new Error('config is required. you should call window.paso.injectPopup(config)') if (!config.namespace) throw new Error('config.namespace is required and it cannot be empty.') if (!/^[-\w]+$/.test(config.namespace)) throw new Error('config.namespace must match the regex /^[-\\w]+$/.') } if (!window.paso || !(window.paso instanceof Object)) window.paso = {} window.paso.injectPopup = (config) => { _checkConfig(config) const _config = Object.assign( {}, { namespace: '', actionName: 'Action', collapse: '100%', location: '25%', content: '<label>Hello World</label>', style: '', onPopShow() {}, onPopHide() {} }, config ) return new Promise((resolve) => { _injectHtml(_config, resolve) }) } })()
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址