Рендеринг SVG-изображения в браузере: скопировать имена элементов в буфер обмена - PullRequest
5 голосов
/ 06 ноября 2019

На этой веб-странице: http://viz -js.com / мы видим график, отображаемый из текстового файла.

Если навести указатель мыши на один из элементов графика,его ярлык появляется во всплывающем окне. (в этом примере 'start')

enter image description here

Вопрос: есть ли в любом случае возможность сделать метку доступной для выбора или добавить немного JavaScript, чтобы разрешитьтекст всплывающего окна, которое будет скопировано в буфер обмена?

Моя реализация этого имеет длинные имена узлов (до 44 символов), которые я бы хотел как-то скопировать.

Спасибо.

Редактировать: Действия, предпринятые до сих пор.

Используя опцию Chrome 'inspect', я вижу, что узлы в SVG, похоже, имеютимя класса 'node, поэтому я попробовал следующий JavaScript, но он не дал никакого эффекта:

$('.big').hover(function () {
    // will not work, no user action
  $('input').select();
    document.execCommand('copy');
});

$('.big').mousedown(function () {
    //works
  document.execCommand('copy');
});

, и я не могу использовать какой-либо стиль CSS, чтобы повлиять на внешний вид графика.

1 Ответ

4 голосов
/ 08 ноября 2019

Взглянув на SVG, вы можете увидеть, что текст карты наведения находится из элемента <title> DOM каждой соответствующей фигуры группы. Вы можете сказать, отредактировав DOM и изменив одно из названий: вы увидите новый текст при наведении курсора на фигуру.

Итак, нам просто нужно взять текст оттуда и отправить его в буфер обмена .

РЕДАКТИРОВАТЬ: Теперь это должно быть намного проще для запуска. Просто нужно подождать, пока элемент g.graph SVG будет загружен на страницу, а не каждый раз, когда он рендерится.

(function addListener() {
  // This time, add the listener to the graph itself
  document.querySelector('.graph').addEventListener('click', event => {
    let str = ""
    // Grab all the siblings of the element that was actually clicked on
    for (const sibling of event.target.parentElement.children) {
      // Check if they're the title
      if (sibling.nodeName != 'title') continue;
      str = sibling.innerHTML;
      break;
    }

    const ta = document.createElement('textarea');
    ta.value = str;
    ta.setAttribute('readonly', '');
    ta.style = { position: 'absolute', left: '-9999px' };
    document.body.appendChild(ta);
    ta.select();
    document.execCommand('copy');
    document.body.removeChild(ta);

    if (str == "") console.log('Nothing found to copy!');
    else console.log(`"${str}" copied to clipboard!`);
  });
})();

Если вы хотите поместить это в исходный код страницы,вместо вставки в консоль Chrome избавьтесь от объявления функции и вытащите его из скобок. Он будет запускаться при загрузке файла.


Исходное решение:

// Function wrapped in brackets and called immediately after declaration
// (so that it can be run from the Chrome console):
(function addListeners() {
  // Grab every SVG 'group' in the 'graph' group:
  for (const el of document.querySelectorAll('.graph g')) {
    // Tell each group to listen for a click on itself:
    el.addEventListener('click', event => {
      // Create an empty string variable to store the title in
      let str = "";
      // Loop through all the elements in the group for one called 'title'
      for (const child of el.children) {
        if (child.nodeName != 'title') continue;
        // Store that title
        str = child.innerHTML;
      }

      // Copy the string to the clipboard (see link above)
      const ta = document.createElement('textarea');
      ta.value = str;
      ta.setAttribute('readonly', '');
      ta.style = { position: 'absolute', left: '-9999px' };
      document.body.appendChild(ta);
      ta.select();
      document.execCommand('copy');
      document.body.removeChild(ta);

      console.log(`"${str}" copied to clipboard!`);
    });
  }
})();

Я проверял это в консоли разработчика Chrome страницы. Вы связались, и он работает нормально.

...