// ==UserScript== // @name 超星粘贴助手 (Chaoxing Paste Helper) V2 // @namespace https://github.com/iPycc/chaoxing-paste-helper/ // @version 2.0 // @description 强制启用超星网站的粘贴功能,支持UEditor富文本编辑器和所有输入元素 // @author iPycc // @match *://*.chaoxing.com/* // @grant none // @run-at document-start // @license AGPL-3.0-or-later // @copyright iPycc All Rights Reserved // ==/UserScript== (function() { 'use strict'; function removeElementRestrictions(element) { if (!element) return; const events = ['paste', 'contextmenu', 'keydown', 'selectstart', 'dragstart', 'copy', 'cut']; events.forEach(event => { element[`on${event}`] = null; element.removeAttribute(`on${event}`); }); element.removeAttribute('readonly'); element.removeAttribute('disabled'); const styleProps = ['userSelect', 'webkitUserSelect', 'mozUserSelect', 'msUserSelect', 'pointerEvents']; const styleValues = ['text', 'text', 'text', 'text', 'auto']; styleProps.forEach((prop, index) => { element.style[prop] = styleValues[index]; }); } function insertImage(doc, dataUrl) { if (!doc || !dataUrl) return false; const img = doc.createElement('img'); img.src = dataUrl; img.alt = '粘贴图片'; const selection = doc.getSelection?.() || doc.defaultView?.getSelection?.(); if (selection?.rangeCount > 0) { const range = selection.getRangeAt(0); range.deleteContents(); range.insertNode(img); range.setStartAfter(img); range.collapse(true); selection.removeAllRanges(); selection.addRange(range); return true; } return false; } function insertText(doc, text) { if (!doc || !text) return false; if (doc.execCommand?.('insertText', false, text)) { return true; } const selection = doc.getSelection?.() || doc.defaultView?.getSelection?.(); if (selection?.rangeCount > 0) { const range = selection.getRangeAt(0); range.deleteContents(); const textNode = doc.createTextNode(text); range.insertNode(textNode); range.setStartAfter(textNode); range.collapse(true); selection.removeAllRanges(); selection.addRange(range); return true; } return false; } function getClipboardText(e) { if (e.clipboardData?.getData) { return e.clipboardData.getData('text/plain'); } if (window.clipboardData?.getData) { return window.clipboardData.getData('Text'); } return ''; } function getClipboardImage(e) { if (!e.clipboardData) return null; const items = Array.from(e.clipboardData.items || []); const files = Array.from(e.clipboardData.files || []); const imageItem = items.find(item => item.type?.startsWith('image/')); const imageFile = files.find(file => file.type?.startsWith('image/')); if (imageItem?.getAsFile) { return imageItem.getAsFile(); } return imageFile || null; } function handlePaste(e, instanceId) { e.preventDefault(); e.stopPropagation(); console.log(`[Chaoxing Paste Helper V2] 处理粘贴功能 ${instanceId}`); const doc = e.target.ownerDocument || document; const imageBlob = getClipboardImage(e); if (imageBlob) { const reader = new FileReader(); reader.onload = () => { if (!insertImage(doc, reader.result)) { const img = doc.createElement('img'); img.src = reader.result; img.alt = '粘贴图片'; doc.body?.appendChild(img); } }; reader.readAsDataURL(imageBlob); return; } const text = getClipboardText(e); if (text && !insertText(doc, text)) { const textNode = doc.createTextNode(text); doc.body?.appendChild(textNode); } } function processUEditorInstance(instance, instanceId) { if (!instance || typeof instance !== 'object') return; if (instance.options) { instance.options.pasteplain = true; instance.options.readonly = false; instance.options.disabled = false; } if (instance.setEnabled && typeof instance.setEnabled === 'function') { const hasContent = instance.body || (instance.iframe?.contentDocument); if (hasContent) instance.setEnabled(true); } if (instance.body && !instance.body.__cxPlainPasteAttached) { removeElementRestrictions(instance.body); instance.body.addEventListener('paste', (e) => handlePaste(e, instanceId), true); instance.body.__cxPlainPasteAttached = true; } const iframeDoc = instance.iframe?.contentDocument; if (iframeDoc && !iframeDoc.__cxPlainPasteAttached) { removeElementRestrictions(iframeDoc.body); iframeDoc.addEventListener('paste', (e) => handlePaste(e, `iframe_${instanceId}`), true); iframeDoc.__cxPlainPasteAttached = true; } } function monitorUEditor() { let attempts = 0; const maxAttempts = 20; const checkUEditor = () => { attempts++; // 处理主窗口UEditor if (typeof UE !== 'undefined' && UE.instants) { Object.keys(UE.instants).forEach(instanceId => { processUEditorInstance(UE.instants[instanceId], instanceId); }); } // 处理iframe中的UEditor document.querySelectorAll('iframe').forEach((iframe, index) => { try { // 检查是否同源 const iframeWindow = iframe.contentWindow; if (iframeWindow && iframeWindow.location.origin === window.location.origin) { if (iframeWindow.UE?.instants) { Object.keys(iframeWindow.UE.instants).forEach(instanceId => { processUEditorInstance(iframeWindow.UE.instants[instanceId], `iframe${index}_${instanceId}`); }); } } } catch (error) { // 跨域iframe,静默忽略 } }); if (attempts < maxAttempts) { setTimeout(checkUEditor, 500); } }; checkUEditor(); } function initialize() { // 移除全局限制 const globalEvents = ['paste', 'contextmenu', 'selectstart', 'dragstart', 'copy', 'cut', 'keydown']; globalEvents.forEach(event => { document[`on${event}`] = null; }); if (document.body) { removeElementRestrictions(document.body); } // 添加全局样式 const style = document.createElement('style'); style.textContent = ` * { -webkit-user-select: text !important; -moz-user-select: text !important; -ms-user-select: text !important; user-select: text !important; } input, textarea, [contenteditable] { user-select: text !important; pointer-events: auto !important; } `; document.head.appendChild(style); // 处理现有元素 const inputSelectors = ['input[type="text"]', 'input[type="password"]', 'textarea', '[contenteditable]']; inputSelectors.forEach(selector => { document.querySelectorAll(selector).forEach(removeElementRestrictions); }); monitorUEditor(); // 监控动态内容 new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeType !== 1) return; if (node.matches?.('input, textarea, [contenteditable]')) { removeElementRestrictions(node); } if (node.tagName === 'IFRAME') { setTimeout(() => { try { const iframeDoc = node.contentDocument; if (iframeDoc) { iframeDoc.querySelectorAll('input, textarea, [contenteditable]').forEach(removeElementRestrictions); } } catch (error) { // 跨域iframe,忽略 } }, 500); } node.querySelectorAll?.('input, textarea, [contenteditable]').forEach(removeElementRestrictions); }); }); }).observe(document.body, { childList: true, subtree: true }); } // 启动 if (document.readyState === 'loading') { window.addEventListener('DOMContentLoaded', initialize); } else { initialize(); } })();