Модификация текста для копирования

Если нужно, чтобы клиенты могли копировать к примеру e-mail, а не переходить по ссылке, быстрое копирование может вам помочь

Modifications

  1. Создаём Zero Block на странице.
  2. Добавляем текст/кнопку/ссылку — элемент, по которому будем копировать.
  3. Задаём этому элементу CSS-класс aw_copy (Zero Block → правый клик по элементу → Add CSS Class Name → aw_copy. Можно обернуть в контейнер и выровнять через flex (для дизайна), но это не обязательно для работы. Класс aw_copy ставим на кликаемый элемент. )
  4. Копируем код модификации и вставляем его в блок T123 → «Перед </body>» на этой же странице. Опубликовываем страницу.
Текст
Пример №1
Кнопка
Пример №2
<!--https://mods.authweb.ru/modifikaciya-kopirovaniya-->
<!--Для работы корректной работы модификации, используйте класс aw_copy-->
<style>
    /* Базовый вид clickable-элемента */
    .aw_copy {
      cursor: pointer;
      display: flex !important;
      align-items: center;
    }
    
    /* Маленькая иконка копии (добавляется скриптом) */
    .aw_copy__icon {
      display: inline-block;
      width: 1em;
      height: 1em;
      vertical-align: -0.15em;
      margin-left: 0.35em;
      opacity: 0.7;
    }
    .aw_copy__icon svg { width: 1em; height: 1em; display: block; }
    
    /* Тост рядом с элементом */
    #awcopy__toast {
      position: absolute; /* позиционируем относительно окна, но ставим рядом с элементом через координаты */
      z-index: 99999;
      background: rgba(24,24,24,0.92);
      color: #fff;
      font: 14px/1.35 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
      padding: 8px 10px;
      border-radius: 8px;
      pointer-events: none;
      transform: translateY(6px);           /* начальное смещение для slide */
      opacity: 0;
      transition: transform 0.1s ease, opacity 0.1s ease; /* slide 0.2s */
      box-shadow: 0 6px 18px rgba(0,0,0,0.18);
      white-space: nowrap;
    }
    
    /* Показ тоста */
    #awcopy__toast.is-visible {
      opacity: 1;
      transform: translateY(0);
    }
    
    /* Небольшой треугольник-указатель */
    #awcopy__toast::after {
      content: "";
      position: absolute;
      top: -6px;
      left: 12px;
      border: 6px solid transparent;
      border-bottom-color: rgba(24,24,24,0.92);
    }

</style>

<script>
    (function () {
      'use strict';
    
      // ====== Настройки по умолчанию ======
      const DEFAULTS = {
        feedback: 'Скопировано',
        toast: true,
        behavior: 'copy-only',
        durationMs: 1000,
      };
    
      // ====== Метрики (опционально) ======
      function trackCopy(value) {
        try {
          if (Array.isArray(window.dataLayer)) {
            window.dataLayer.push({ event: 'awcopy_success', awcopy_value: value });
          }
          if (typeof window.gtag === 'function') {
            window.gtag('event', 'awcopy_success', { value });
          }
          if (typeof window.ym === 'function' && window.AW_YM_ID) {
            window.ym(window.AW_YM_ID, 'reachGoal', 'awcopy_success', { value });
          }
        } catch (_) {}
      }
    
      // ====== Clipboard ======
      async function copyToClipboard(text) {
        if (!text) throw new Error('Empty copy value');
        if (navigator.clipboard && navigator.clipboard.writeText) {
          await navigator.clipboard.writeText(text);
          return true;
        }
        const ta = document.createElement('textarea');
        ta.value = text;
        ta.setAttribute('readonly', '');
        ta.style.position = 'fixed';
        ta.style.top = '-9999px';
        document.body.appendChild(ta);
        ta.select();
        try {
          document.execCommand('copy');
          document.body.removeChild(ta);
          return true;
        } catch (e) {
          document.body.removeChild(ta);
          throw e;
        }
      }
    
      // ====== Toast (singleton) ======
      let toastEl = null;
      let toastTimer = null;
    
      function ensureToast() {
        if (toastEl && document.body.contains(toastEl)) return toastEl;
        toastEl = document.createElement('div');
        toastEl.id = 'awcopy__toast';
        toastEl.setAttribute('role', 'status');
        toastEl.setAttribute('aria-live', 'polite');
        document.body.appendChild(toastEl);
        return toastEl;
      }
    
      function showToastNear(targetEl, text, durationMs) {
        const toast = ensureToast();
        toast.textContent = text || DEFAULTS.feedback;
    
        const rect = targetEl.getBoundingClientRect();
        const scrollX = window.scrollX || window.pageXOffset;
        const scrollY = window.scrollY || window.pageYOffset;
    
        const margin = 10;
        const top = rect.bottom + scrollY + margin;
        let left = rect.left + scrollX;
    
        toast.classList.remove('is-visible');
        toast.style.top = top + 'px';
        toast.style.left = left + 'px';
    
        requestAnimationFrame(() => {
          const tRect = toast.getBoundingClientRect();
          const overflowRight = (tRect.right > document.documentElement.clientWidth - 8);
          if (overflowRight) {
            const delta = tRect.right - document.documentElement.clientWidth + 8;
            left = Math.max(8, left - delta);
            toast.style.left = left + 'px';
          }
          requestAnimationFrame(() => {
            toast.classList.add('is-visible');
            clearTimeout(toastTimer);
            toastTimer = setTimeout(() => {
              toast.classList.remove('is-visible');
            }, Math.max(500, durationMs || DEFAULTS.durationMs));
          });
        });
      }
    
      // ====== Helpers ======
      function getMailtoAnchor(el) {
        if (!el) return null;
        if (el.tagName === 'A' && /^mailto:/i.test(el.getAttribute('href') || '')) return el;
        return el.closest && el.closest('a[href^="mailto:"]');
      }
      function getCopyValueFrom(triggerEl) {
        const data = triggerEl.getAttribute('data-copy');
        if (data && data.trim()) return data.trim();
    
        const anchor = getMailtoAnchor(triggerEl);
        if (anchor) {
          const email = (anchor.getAttribute('href') || '').replace(/^mailto:/i, '').trim();
          if (email) return email;
        }
        const txtTrigger = (triggerEl.textContent || '').trim();
        if (txtTrigger) return txtTrigger;
    
        if (anchor) {
          const txtA = (anchor.textContent || '').trim();
          if (txtA) return txtA;
        }
        return '';
      }
      function getBehavior(el) {
        return (el.getAttribute('data-behavior') || DEFAULTS.behavior).toLowerCase();
      }
      function getFeedback(el) {
        return el.getAttribute('data-feedback') || DEFAULTS.feedback;
      }
      function shouldShowToast(el) {
        const attr = el.getAttribute('data-toast');
        return attr == null ? DEFAULTS.toast : String(attr).toLowerCase() !== 'false';
      }
      function makeAccessible(el) {
        const isInteractive = /^(A|BUTTON|INPUT|TEXTAREA)$/i.test(el.tagName);
        if (!isInteractive) {
          el.setAttribute('role', 'button');
          if (!el.hasAttribute('tabindex')) el.setAttribute('tabindex', '0');
        }
        if (!el.hasAttribute('aria-label')) {
          el.setAttribute('aria-label', 'Скопировать в буфер обмена');
        }
      }
      function injectCopyIcon(el) {
        if (el.querySelector('.aw_copy__icon')) return;
        const span = document.createElement('span');
        span.className = 'aw_copy__icon';
        span.innerHTML = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M16 1H4a2 2 0 0 0-2 2v12h2V3h12V1zm3 4H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2zm0 16H8V7h11v14z"/></svg>';
        el.appendChild(span);
      }
    
      function initAwCopy(root = document) {
        const nodes = root.querySelectorAll('.aw_copy');
        nodes.forEach(el => {
          makeAccessible(el);
          injectCopyIcon(el);
        });
      }
    
      // ====== Guard от двойной инициализации ======
      if (window.__awcopy_bound) return;
      window.__awcopy_bound = true;
    
      // Первичная инициализация
      document.addEventListener('DOMContentLoaded', () => initAwCopy());
      document.addEventListener('tilda:load', () => initAwCopy());
      document.addEventListener('tilda:changed', () => initAwCopy());
    
      // ====== ЕДИНСТВЕННЫЙ перехватчик кликов (делегирование) ======
      document.addEventListener('click', async (e) => {
        const trigger = e.target.closest && e.target.closest('.aw_copy');
        if (!trigger) return;
    
        const behavior = getBehavior(trigger);
        const anchor = getMailtoAnchor(trigger);
    
        // если есть mailto и режим copy-only — жёстко глушим навигацию ДО обработки другими слушателями
        if (anchor && behavior === 'copy-only') {
          e.preventDefault();
          if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation();
          e.stopPropagation();
        }
    
        const value = getCopyValueFrom(trigger);
        try {
          await copyToClipboard(value);
          trigger.dispatchEvent(new CustomEvent('awcopy:success', { bubbles: true, detail: { value } }));
          trackCopy(value);
          if (shouldShowToast(trigger)) showToastNear(trigger, getFeedback(trigger), DEFAULTS.durationMs);
        } catch (err) {
          trigger.dispatchEvent(new CustomEvent('awcopy:error', { bubbles: true, detail: { reason: String(err) } }));
          if (shouldShowToast(trigger)) showToastNear(trigger, 'Нажмите Ctrl+C / ⌘C', DEFAULTS.durationMs);
        }
      }, { passive: false, capture: true }); // ВАЖНО: capture=true
    
      // Поддержка клавиатуры
      document.addEventListener('keydown', async (e) => {
        if (e.key !== 'Enter' && e.key !== ' ') return;
        const el = document.activeElement;
        if (!el || !el.classList || !el.classList.contains('aw_copy')) return;
    
        e.preventDefault();
        const behavior = getBehavior(el);
        // если это <a href="mailto:">, навигацию не запускаем (режим copy-only)
        const value = getCopyValueFrom(el);
        try {
          await copyToClipboard(value);
          el.dispatchEvent(new CustomEvent('awcopy:success', { bubbles: true, detail: { value } }));
          trackCopy(value);
          if (shouldShowToast(el)) showToastNear(el, getFeedback(el), DEFAULTS.durationMs);
        } catch (err) {
          el.dispatchEvent(new CustomEvent('awcopy:error', { bubbles: true, detail: { reason: String(err) } }));
          if (shouldShowToast(el)) showToastNear(el, 'Нажмите Ctrl+C / ⌘C', DEFAULTS.durationMs);
        }
      });
    })();
</script>
Made on
Tilda