MediaWiki:Common.js: Difference between revisions

From ChronoRo WIKI
Jump to navigation Jump to search
Created page with "Any JavaScript here will be loaded for all users on every page load.: document.addEventListener('click', function (e) { var el = e.target.closest('.wiki-copy-btn'); if (!el) return; var text = el.getAttribute('data-copy'); if (!text) return; navigator.clipboard.writeText(text); el.classList.add('copied'); setTimeout(() => el.classList.remove('copied'), 1000); });"
 
No edit summary
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
/* Any JavaScript here will be loaded for all users on every page load. */
(function () {
document.addEventListener('click', function (e) {
  function copyText(text) {
     var el = e.target.closest('.wiki-copy-btn');
    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;
     if (!el) return;


Line 7: Line 76:
     if (!text) return;
     if (!text) return;


     navigator.clipboard.writeText(text);
     e.preventDefault();


     el.classList.add('copied');
     copyText(text).then(function () {
     setTimeout(() => el.classList.remove('copied'), 1000);
      showTip(el, 'Copied!');
});
     }).catch(function () {
      showTip(el, 'Copy failed');
    });
  }, true);
})();

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);
})();