Gadget-CopyTextTool.js:修订间差异
来自卡厄思梦境WIKI
无编辑摘要 |
无编辑摘要 |
||
| 第1行: | 第1行: | ||
/** | /** | ||
* 文本复制工具 - | * 文本复制工具 - 浮动窗口版本 | ||
* 适配 Foreground 皮肤 | |||
*/ | */ | ||
(function($, mw) { | (function($, mw) { | ||
'use strict'; | 'use strict'; | ||
// ===== 自定义配置 ===== | |||
var config = { | var config = { | ||
'蓝色': '{{文本|蓝|', | '蓝色': '{{文本|蓝|', | ||
| 第16行: | 第15行: | ||
}; | }; | ||
// | // 默认位置配置 | ||
var defaultPosition = { | |||
top: '100px', | |||
right: '20px' | |||
}; | |||
// ==================== | |||
var toolPanel = null; | |||
var floatButton = null; | |||
var isVisible = false; | |||
var isMinimized = false; | |||
// 页面加载完成后初始化 | |||
$(function() { | $(function() { | ||
// 从本地存储读取用户偏好 | |||
var savedState = localStorage.getItem('copyTextTool_visible'); | |||
isVisible = savedState === 'true'; | |||
createFloatButton(); | |||
createToolPanel(); | |||
if ( | if (isVisible) { | ||
showTool(); | |||
} | } | ||
}); | }); | ||
// 创建浮动按钮 | |||
function createFloatButton() { | |||
floatButton = $('<div>') | |||
.attr('id', 'copy-tool-fab') | |||
.attr('title', '文本复制工具') | |||
.html('📋') | |||
.css({ | |||
position: 'fixed', | |||
bottom: '30px', | |||
right: '30px', | |||
width: '56px', | |||
height: '56px', | |||
borderRadius: '50%', | |||
background: 'linear-gradient(135deg, #2196F3 0%, #1976D2 100%)', | |||
color: 'white', | |||
fontSize: '24px', | |||
display: 'flex', | |||
alignItems: 'center', | |||
justifyContent: 'center', | |||
cursor: 'pointer', | |||
boxShadow: '0 4px 12px rgba(33, 150, 243, 0.4)', | |||
zIndex: 9998, | |||
transition: 'all 0.3s ease', | |||
userSelect: 'none' | |||
}) | |||
.on('click', toggleTool) | |||
.hover( | |||
function() { | |||
$(this).css({ | |||
transform: 'scale(1.1)', | |||
boxShadow: '0 6px 16px rgba(33, 150, 243, 0.6)' | |||
}); | |||
}, | |||
function() { | |||
$(this).css({ | |||
transform: 'scale(1)', | |||
boxShadow: '0 4px 12px rgba(33, 150, 243, 0.4)' | |||
}); | |||
} | |||
) | |||
.appendTo('body'); | |||
} | |||
// 创建工具面板 | // 创建工具面板 | ||
function | function createToolPanel() { | ||
// 读取保存的位置 | |||
var savedPos = localStorage.getItem('copyTextTool_position'); | |||
var position = savedPos ? JSON.parse(savedPos) : defaultPosition; | |||
toolPanel = $('<div>') | |||
.attr('id', 'copy-text-tool') | .attr('id', 'copy-text-tool') | ||
.css({ | .css({ | ||
position: 'fixed', | position: 'fixed', | ||
top: | top: position.top, | ||
right: ' | right: position.right, | ||
width: ' | left: position.left || 'auto', | ||
width: '320px', | |||
background: 'white', | background: 'white', | ||
border: '2px solid #2196F3', | border: '2px solid #2196F3', | ||
borderRadius: ' | borderRadius: '12px', | ||
boxShadow: '0 | boxShadow: '0 8px 24px rgba(0,0,0,0.15)', | ||
zIndex: 9999, | zIndex: 9999, | ||
display: 'none', | |||
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' | |||
}); | }); | ||
// 创建标题栏 | |||
var header = $('<div>') | |||
.attr('id', 'tool-header') | |||
.css({ | |||
background: 'linear-gradient(135deg, #2196F3 0%, #1976D2 100%)', | |||
color: 'white', | |||
padding: '12px 15px', | |||
borderRadius: '10px 10px 0 0', | |||
cursor: 'move', | |||
display: 'flex', | |||
justifyContent: 'space-between', | |||
alignItems: 'center', | |||
userSelect: 'none' | |||
}) | |||
.appendTo(toolPanel); | |||
// 标题 | // 标题 | ||
$('<div>') | $('<div>') | ||
.css({ | .css({ | ||
background: ' | fontWeight: 'bold', | ||
fontSize: '15px', | |||
display: 'flex', | |||
alignItems: 'center', | |||
gap: '8px' | |||
}) | |||
.html('<span style="font-size: 18px">📋</span> 文本复制工具') | |||
.appendTo(header); | |||
// 控制按钮组 | |||
var controls = $('<div>') | |||
.css({ | |||
display: 'flex', | |||
gap: '8px' | |||
}) | |||
.appendTo(header); | |||
// 最小化按钮 | |||
$('<button>') | |||
.attr('title', '最小化') | |||
.html('−') | |||
.css({ | |||
background: 'rgba(255,255,255,0.2)', | |||
border: 'none', | |||
color: 'white', | |||
width: '24px', | |||
height: '24px', | |||
borderRadius: '4px', | |||
cursor: 'pointer', | |||
fontSize: '16px', | |||
display: 'flex', | |||
alignItems: 'center', | |||
justifyContent: 'center' | |||
}) | |||
.on('click', minimizeTool) | |||
.hover( | |||
function() { $(this).css('background', 'rgba(255,255,255,0.3)'); }, | |||
function() { $(this).css('background', 'rgba(255,255,255,0.2)'); } | |||
) | |||
.appendTo(controls); | |||
// 关闭按钮 | |||
$('<button>') | |||
.attr('title', '关闭') | |||
.html('×') | |||
.css({ | |||
background: 'rgba(255,255,255,0.2)', | |||
border: 'none', | |||
color: 'white', | color: 'white', | ||
width: '24px', | |||
height: '24px', | |||
borderRadius: '4px', | |||
cursor: 'pointer', | |||
fontSize: '20px', | |||
display: 'flex', | |||
alignItems: 'center', | |||
justifyContent: 'center' | |||
}) | |||
.on('click', hideTool) | |||
.hover( | |||
function() { $(this).css('background', 'rgba(255,255,255,0.3)'); }, | |||
function() { $(this).css('background', 'rgba(255,255,255,0.2)'); } | |||
) | |||
.appendTo(controls); | |||
// 内容区域 | |||
var body = $('<div>') | |||
.attr('id', 'tool-body') | |||
.css({ | |||
padding: '15px' | |||
}) | |||
.appendTo(toolPanel); | |||
// 置顶开关 | |||
var pinnedState = localStorage.getItem('copyTextTool_pinned') !== 'false'; | |||
var pinControl = $('<div>') | |||
.css({ | |||
display: 'flex', | |||
alignItems: 'center', | |||
gap: '8px', | |||
padding: '10px', | padding: '10px', | ||
marginBottom: ' | background: '#f5f5f5', | ||
borderRadius: '6px', | |||
marginBottom: '12px' | |||
}) | |||
.appendTo(body); | |||
var pinCheckbox = $('<input>') | |||
.attr({ | |||
type: 'checkbox', | |||
id: 'pin-checkbox', | |||
checked: pinnedState | |||
}) | |||
.css({ | |||
width: '18px', | |||
height: '18px', | |||
cursor: 'pointer' | |||
}) | |||
.on('change', function() { | |||
var isPinned = $(this).is(':checked'); | |||
toolPanel.css('position', isPinned ? 'fixed' : 'absolute'); | |||
localStorage.setItem('copyTextTool_pinned', isPinned); | |||
}) | |||
.appendTo(pinControl); | |||
$('<label>') | |||
.attr('for', 'pin-checkbox') | |||
.text('窗口置顶') | |||
.css({ | |||
cursor: 'pointer', | |||
fontSize: '13px', | |||
userSelect: 'none' | |||
}) | }) | ||
. | .appendTo(pinControl); | ||
// 按钮容器 | |||
var buttonContainer = $('<div>') | |||
.css({ | |||
display: 'flex', | |||
flexDirection: 'column', | |||
gap: '8px' | |||
}) | |||
.appendTo(body); | |||
.appendTo( | |||
// | // 添加复制按钮 | ||
$.each(config, function(name, text) { | $.each(config, function(name, text) { | ||
$('<button>') | $('<button>') | ||
| 第104行: | 第257行: | ||
width: '100%', | width: '100%', | ||
padding: '12px', | padding: '12px', | ||
background: '#2196F3', | background: '#2196F3', | ||
color: 'white', | color: 'white', | ||
border: 'none', | border: 'none', | ||
borderRadius: ' | borderRadius: '6px', | ||
cursor: 'pointer', | cursor: 'pointer', | ||
fontSize: '14px' | fontSize: '14px', | ||
fontWeight: '500', | |||
transition: 'all 0.2s ease' | |||
}) | }) | ||
.on('click', function() { | .on('click', function() { | ||
| 第116行: | 第270行: | ||
}) | }) | ||
.hover( | .hover( | ||
function() { $(this).css(' | function() { | ||
function() { $(this).css(' | $(this).css({ | ||
background: '#1976D2', | |||
transform: 'translateY(-1px)', | |||
boxShadow: '0 2px 8px rgba(33, 150, 243, 0.3)' | |||
}); | |||
}, | |||
function() { | |||
$(this).css({ | |||
background: '#2196F3', | |||
transform: 'translateY(0)', | |||
boxShadow: 'none' | |||
}); | |||
} | |||
) | ) | ||
.appendTo( | .appendTo(buttonContainer); | ||
}); | }); | ||
// 状态栏 | // 状态栏 | ||
$('<div>') | |||
.attr('id', 'copy-status') | .attr('id', 'copy-status') | ||
.css({ | .css({ | ||
textAlign: 'center', | textAlign: 'center', | ||
color: '#666', | color: '#666', | ||
padding: ' | padding: '10px', | ||
fontSize: ' | fontSize: '13px', | ||
marginTop: ' | marginTop: '8px', | ||
minHeight: '20px' | |||
}) | }) | ||
.text('准备就绪') | .text('准备就绪') | ||
.appendTo( | .appendTo(body); | ||
toolPanel.appendTo('body'); | |||
// | // 使工具面板可拖动 | ||
makeDraggable( | makeDraggable(toolPanel[0], header[0]); | ||
} | } | ||
// 复制文本 | // 复制文本 | ||
function copyText(text, name) { | function copyText(text, name) { | ||
// 尝试使用现代剪贴板API | |||
if (navigator.clipboard && navigator.clipboard.writeText) { | |||
navigator.clipboard.writeText(text).then(function() { | |||
showStatus('✓ 已复制: ' + name, true); | |||
}).catch(function() { | |||
fallbackCopy(text, name); | |||
}); | |||
} else { | |||
fallbackCopy(text, name); | |||
} | |||
} | |||
// 备用复制方法 | |||
function fallbackCopy(text, name) { | |||
var $temp = $('<textarea>') | var $temp = $('<textarea>') | ||
.val(text) | .val(text) | ||
.css({ | .css({ | ||
position: 'fixed', | position: 'fixed', | ||
opacity: 0 | opacity: 0, | ||
top: '-9999px' | |||
}) | }) | ||
.appendTo('body'); | .appendTo('body'); | ||
$temp[0].select(); | $temp[0].select(); | ||
$temp[0].setSelectionRange(0, 99999); | |||
try { | try { | ||
document.execCommand('copy'); | document.execCommand('copy'); | ||
showStatus('✓ 已复制: ' + name, true); | |||
} catch(err) { | } catch(err) { | ||
showStatus('❌ 复制失败', false); | |||
} | } | ||
| 第171行: | 第346行: | ||
} | } | ||
// | // 显示状态 | ||
function makeDraggable(element) { | function showStatus(message, success) { | ||
$('#copy-status') | |||
.text(message) | |||
.css({ | |||
color: success ? '#2196F3' : '#f44336', | |||
fontWeight: success ? 'bold' : 'normal' | |||
}); | |||
} | |||
// 切换工具显示 | |||
function toggleTool() { | |||
if (isVisible) { | |||
hideTool(); | |||
} else { | |||
showTool(); | |||
} | |||
} | |||
// 显示工具 | |||
function showTool() { | |||
if (isMinimized) { | |||
isMinimized = false; | |||
$('#tool-body').show(); | |||
toolPanel.css('width', '320px'); | |||
} | |||
toolPanel.fadeIn(200); | |||
isVisible = true; | |||
localStorage.setItem('copyTextTool_visible', 'true'); | |||
} | |||
// 隐藏工具 | |||
function hideTool() { | |||
toolPanel.fadeOut(200); | |||
isVisible = false; | |||
localStorage.setItem('copyTextTool_visible', 'false'); | |||
} | |||
// 最小化工具 | |||
function minimizeTool() { | |||
if (isMinimized) { | |||
$('#tool-body').slideDown(200); | |||
toolPanel.css('width', '320px'); | |||
isMinimized = false; | |||
} else { | |||
$('#tool-body').slideUp(200); | |||
toolPanel.css('width', 'auto'); | |||
isMinimized = true; | |||
} | |||
} | |||
// 拖动功能 | |||
function makeDraggable(element, handle) { | |||
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; | var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; | ||
handle.onmousedown = dragMouseDown; | |||
function dragMouseDown(e) { | function dragMouseDown(e) { | ||
| 第183行: | 第410行: | ||
document.onmouseup = closeDragElement; | document.onmouseup = closeDragElement; | ||
document.onmousemove = elementDrag; | document.onmousemove = elementDrag; | ||
$(element).css('transition', 'none'); | |||
} | } | ||
| 第192行: | 第420行: | ||
pos3 = e.clientX; | pos3 = e.clientX; | ||
pos4 = e.clientY; | pos4 = e.clientY; | ||
element. | |||
element.style.left = | var newTop = (element.offsetTop - pos2); | ||
var newLeft = (element.offsetLeft - pos1); | |||
element.style.top = newTop + "px"; | |||
element.style.left = newLeft + "px"; | |||
element.style.right = "auto"; | element.style.right = "auto"; | ||
} | } | ||
| 第200行: | 第432行: | ||
document.onmouseup = null; | document.onmouseup = null; | ||
document.onmousemove = null; | document.onmousemove = null; | ||
// 保存位置 | |||
var position = { | |||
top: element.style.top, | |||
left: element.style.left | |||
}; | |||
localStorage.setItem('copyTextTool_position', JSON.stringify(position)); | |||
} | } | ||
} | } | ||
})(jQuery, mediaWiki); | })(jQuery, mediaWiki); | ||
2025年10月3日 (五) 20:45的版本
/**
* 文本复制工具 - 浮动窗口版本
* 适配 Foreground 皮肤
*/
(function($, mw) {
'use strict';
// ===== 自定义配置 =====
var config = {
'蓝色': '{{文本|蓝|',
'绿色': '{{文本|绿|',
'蓝色下划线': '{{文本|蓝|下划线|',
'绿色描边': '{{描边|绿|',
'词典': '{{词典|'
};
// 默认位置配置
var defaultPosition = {
top: '100px',
right: '20px'
};
// ====================
var toolPanel = null;
var floatButton = null;
var isVisible = false;
var isMinimized = false;
// 页面加载完成后初始化
$(function() {
// 从本地存储读取用户偏好
var savedState = localStorage.getItem('copyTextTool_visible');
isVisible = savedState === 'true';
createFloatButton();
createToolPanel();
if (isVisible) {
showTool();
}
});
// 创建浮动按钮
function createFloatButton() {
floatButton = $('<div>')
.attr('id', 'copy-tool-fab')
.attr('title', '文本复制工具')
.html('📋')
.css({
position: 'fixed',
bottom: '30px',
right: '30px',
width: '56px',
height: '56px',
borderRadius: '50%',
background: 'linear-gradient(135deg, #2196F3 0%, #1976D2 100%)',
color: 'white',
fontSize: '24px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
boxShadow: '0 4px 12px rgba(33, 150, 243, 0.4)',
zIndex: 9998,
transition: 'all 0.3s ease',
userSelect: 'none'
})
.on('click', toggleTool)
.hover(
function() {
$(this).css({
transform: 'scale(1.1)',
boxShadow: '0 6px 16px rgba(33, 150, 243, 0.6)'
});
},
function() {
$(this).css({
transform: 'scale(1)',
boxShadow: '0 4px 12px rgba(33, 150, 243, 0.4)'
});
}
)
.appendTo('body');
}
// 创建工具面板
function createToolPanel() {
// 读取保存的位置
var savedPos = localStorage.getItem('copyTextTool_position');
var position = savedPos ? JSON.parse(savedPos) : defaultPosition;
toolPanel = $('<div>')
.attr('id', 'copy-text-tool')
.css({
position: 'fixed',
top: position.top,
right: position.right,
left: position.left || 'auto',
width: '320px',
background: 'white',
border: '2px solid #2196F3',
borderRadius: '12px',
boxShadow: '0 8px 24px rgba(0,0,0,0.15)',
zIndex: 9999,
display: 'none',
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
});
// 创建标题栏
var header = $('<div>')
.attr('id', 'tool-header')
.css({
background: 'linear-gradient(135deg, #2196F3 0%, #1976D2 100%)',
color: 'white',
padding: '12px 15px',
borderRadius: '10px 10px 0 0',
cursor: 'move',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
userSelect: 'none'
})
.appendTo(toolPanel);
// 标题
$('<div>')
.css({
fontWeight: 'bold',
fontSize: '15px',
display: 'flex',
alignItems: 'center',
gap: '8px'
})
.html('<span style="font-size: 18px">📋</span> 文本复制工具')
.appendTo(header);
// 控制按钮组
var controls = $('<div>')
.css({
display: 'flex',
gap: '8px'
})
.appendTo(header);
// 最小化按钮
$('<button>')
.attr('title', '最小化')
.html('−')
.css({
background: 'rgba(255,255,255,0.2)',
border: 'none',
color: 'white',
width: '24px',
height: '24px',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '16px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
})
.on('click', minimizeTool)
.hover(
function() { $(this).css('background', 'rgba(255,255,255,0.3)'); },
function() { $(this).css('background', 'rgba(255,255,255,0.2)'); }
)
.appendTo(controls);
// 关闭按钮
$('<button>')
.attr('title', '关闭')
.html('×')
.css({
background: 'rgba(255,255,255,0.2)',
border: 'none',
color: 'white',
width: '24px',
height: '24px',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '20px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
})
.on('click', hideTool)
.hover(
function() { $(this).css('background', 'rgba(255,255,255,0.3)'); },
function() { $(this).css('background', 'rgba(255,255,255,0.2)'); }
)
.appendTo(controls);
// 内容区域
var body = $('<div>')
.attr('id', 'tool-body')
.css({
padding: '15px'
})
.appendTo(toolPanel);
// 置顶开关
var pinnedState = localStorage.getItem('copyTextTool_pinned') !== 'false';
var pinControl = $('<div>')
.css({
display: 'flex',
alignItems: 'center',
gap: '8px',
padding: '10px',
background: '#f5f5f5',
borderRadius: '6px',
marginBottom: '12px'
})
.appendTo(body);
var pinCheckbox = $('<input>')
.attr({
type: 'checkbox',
id: 'pin-checkbox',
checked: pinnedState
})
.css({
width: '18px',
height: '18px',
cursor: 'pointer'
})
.on('change', function() {
var isPinned = $(this).is(':checked');
toolPanel.css('position', isPinned ? 'fixed' : 'absolute');
localStorage.setItem('copyTextTool_pinned', isPinned);
})
.appendTo(pinControl);
$('<label>')
.attr('for', 'pin-checkbox')
.text('窗口置顶')
.css({
cursor: 'pointer',
fontSize: '13px',
userSelect: 'none'
})
.appendTo(pinControl);
// 按钮容器
var buttonContainer = $('<div>')
.css({
display: 'flex',
flexDirection: 'column',
gap: '8px'
})
.appendTo(body);
// 添加复制按钮
$.each(config, function(name, text) {
$('<button>')
.text(name)
.css({
width: '100%',
padding: '12px',
background: '#2196F3',
color: 'white',
border: 'none',
borderRadius: '6px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '500',
transition: 'all 0.2s ease'
})
.on('click', function() {
copyText(text, name);
})
.hover(
function() {
$(this).css({
background: '#1976D2',
transform: 'translateY(-1px)',
boxShadow: '0 2px 8px rgba(33, 150, 243, 0.3)'
});
},
function() {
$(this).css({
background: '#2196F3',
transform: 'translateY(0)',
boxShadow: 'none'
});
}
)
.appendTo(buttonContainer);
});
// 状态栏
$('<div>')
.attr('id', 'copy-status')
.css({
textAlign: 'center',
color: '#666',
padding: '10px',
fontSize: '13px',
marginTop: '8px',
minHeight: '20px'
})
.text('准备就绪')
.appendTo(body);
toolPanel.appendTo('body');
// 使工具面板可拖动
makeDraggable(toolPanel[0], header[0]);
}
// 复制文本
function copyText(text, name) {
// 尝试使用现代剪贴板API
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(function() {
showStatus('✓ 已复制: ' + name, true);
}).catch(function() {
fallbackCopy(text, name);
});
} else {
fallbackCopy(text, name);
}
}
// 备用复制方法
function fallbackCopy(text, name) {
var $temp = $('<textarea>')
.val(text)
.css({
position: 'fixed',
opacity: 0,
top: '-9999px'
})
.appendTo('body');
$temp[0].select();
$temp[0].setSelectionRange(0, 99999);
try {
document.execCommand('copy');
showStatus('✓ 已复制: ' + name, true);
} catch(err) {
showStatus('❌ 复制失败', false);
}
$temp.remove();
}
// 显示状态
function showStatus(message, success) {
$('#copy-status')
.text(message)
.css({
color: success ? '#2196F3' : '#f44336',
fontWeight: success ? 'bold' : 'normal'
});
}
// 切换工具显示
function toggleTool() {
if (isVisible) {
hideTool();
} else {
showTool();
}
}
// 显示工具
function showTool() {
if (isMinimized) {
isMinimized = false;
$('#tool-body').show();
toolPanel.css('width', '320px');
}
toolPanel.fadeIn(200);
isVisible = true;
localStorage.setItem('copyTextTool_visible', 'true');
}
// 隐藏工具
function hideTool() {
toolPanel.fadeOut(200);
isVisible = false;
localStorage.setItem('copyTextTool_visible', 'false');
}
// 最小化工具
function minimizeTool() {
if (isMinimized) {
$('#tool-body').slideDown(200);
toolPanel.css('width', '320px');
isMinimized = false;
} else {
$('#tool-body').slideUp(200);
toolPanel.css('width', 'auto');
isMinimized = true;
}
}
// 拖动功能
function makeDraggable(element, handle) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
handle.onmousedown = dragMouseDown;
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
$(element).css('transition', 'none');
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
var newTop = (element.offsetTop - pos2);
var newLeft = (element.offsetLeft - pos1);
element.style.top = newTop + "px";
element.style.left = newLeft + "px";
element.style.right = "auto";
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
// 保存位置
var position = {
top: element.style.top,
left: element.style.left
};
localStorage.setItem('copyTextTool_position', JSON.stringify(position));
}
}
})(jQuery, mediaWiki);