MediaWiki:Common.js: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
(function () { | (function () { | ||
function copyText(text) { | function copyText(text) { | ||
| Line 20: | Line 19: | ||
function showTip(targetEl, msg) { | function showTip(targetEl, msg) { | ||
var rect = targetEl.getBoundingClientRect(); | var rect = targetEl.getBoundingClientRect(); | ||
var tip = document.createElement('div'); | var tip = document.createElement('div'); | ||
tip.textContent = msg || 'Copied!'; | tip.textContent = msg || 'Copied!'; | ||
document.body.appendChild(tip); | |||
// базовые стили прямо тут (не зависят от CSS) | |||
tip.style.position = 'absolute'; | |||
tip.style.zIndex = '999999'; | |||
tip.style.background = '#2b2b2b'; | |||
tip.style.color = '#fff'; | |||
tip.style.fontSize = '12px'; | |||
tip.style.padding = '4px 8px'; | |||
tip.style.borderRadius = '4px'; | |||
tip.style.whiteSpace = 'nowrap'; | |||
tip.style.pointerEvents = 'none'; | |||
// делаем видимым сразу | |||
tip.style.opacity = '1'; | |||
tip.style.transition = 'opacity 200ms ease, transform 200ms ease'; | |||
tip.style.transform = 'translateY(4px)'; | |||
// | // позиционирование (после того как tip появился) | ||
var tipRect = tip.getBoundingClientRect(); | var tipRect = tip.getBoundingClientRect(); | ||
var top = window.scrollY + rect.top - tipRect.height - 8; | var top = window.scrollY + rect.top - tipRect.height - 8; | ||
var left = window.scrollX + rect.left + (rect.width / 2) - (tipRect.width / 2); | var left = window.scrollX + rect.left + (rect.width / 2) - (tipRect.width / 2); | ||
// не даём улететь за края | |||
top = Math.max(window.scrollY + 8, top); | |||
left = Math.max(window.scrollX + 8, left); | |||
tip.style.top = top + 'px'; | |||
tip.style.left = left + 'px'; | |||
// небольшая "вспышка" вверх | |||
requestAnimationFrame(function () { | |||
tip.style.transform = 'translateY(0)'; | |||
}); | |||
// fade out | |||
setTimeout(function () { | |||
tip.style.opacity = '0'; | |||
tip.style.transform = 'translateY(-4px)'; | |||
}, 800); | |||
setTimeout(function () { | setTimeout(function () { | ||
| Line 52: | Line 79: | ||
copyText(text).then(function () { | copyText(text).then(function () { | ||
showTip(el, 'Copied!'); | showTip(el, 'Copied!'); | ||
}).catch(function () { | }).catch(function () { | ||
showTip(el, 'Copy failed'); | showTip(el, 'Copy failed'); | ||
Latest revision as of 15:23, 21 January 2026
(function () {
function copyText(text) {
if (navigator.clipboard && navigator.clipboard.writeText) {
return navigator.clipboard.writeText(text);
}
return new Promise(function (resolve) {
var ta = document.createElement('textarea');
ta.value = text;
ta.setAttribute('readonly', '');
ta.style.position = 'fixed';
ta.style.left = '-9999px';
document.body.appendChild(ta);
ta.select();
try { document.execCommand('copy'); } catch (e) {}
document.body.removeChild(ta);
resolve();
});
}
function showTip(targetEl, msg) {
var rect = targetEl.getBoundingClientRect();
var tip = document.createElement('div');
tip.textContent = msg || 'Copied!';
document.body.appendChild(tip);
// базовые стили прямо тут (не зависят от CSS)
tip.style.position = 'absolute';
tip.style.zIndex = '999999';
tip.style.background = '#2b2b2b';
tip.style.color = '#fff';
tip.style.fontSize = '12px';
tip.style.padding = '4px 8px';
tip.style.borderRadius = '4px';
tip.style.whiteSpace = 'nowrap';
tip.style.pointerEvents = 'none';
// делаем видимым сразу
tip.style.opacity = '1';
tip.style.transition = 'opacity 200ms ease, transform 200ms ease';
tip.style.transform = 'translateY(4px)';
// позиционирование (после того как tip появился)
var tipRect = tip.getBoundingClientRect();
var top = window.scrollY + rect.top - tipRect.height - 8;
var left = window.scrollX + rect.left + (rect.width / 2) - (tipRect.width / 2);
// не даём улететь за края
top = Math.max(window.scrollY + 8, top);
left = Math.max(window.scrollX + 8, left);
tip.style.top = top + 'px';
tip.style.left = left + 'px';
// небольшая "вспышка" вверх
requestAnimationFrame(function () {
tip.style.transform = 'translateY(0)';
});
// fade out
setTimeout(function () {
tip.style.opacity = '0';
tip.style.transform = 'translateY(-4px)';
}, 800);
setTimeout(function () {
if (tip && tip.parentNode) tip.remove();
}, 1100);
}
document.addEventListener('click', function (e) {
var el = e.target.closest ? e.target.closest('.wiki-copy-btn') : null;
if (!el) return;
var text = el.getAttribute('data-copy');
if (!text) return;
e.preventDefault();
copyText(text).then(function () {
showTip(el, 'Copied!');
}).catch(function () {
showTip(el, 'Copy failed');
});
}, true);
})();