Як додати додаткову інформацію до скопійованого веб-тексту


103

Деякі веб-сайти зараз використовують службу JavaScript від Tynt, яка додає текст до скопійованого вмісту.

Якщо ви скопіюєте текст з сайту за допомогою цього, а потім вставте, ви отримаєте посилання на оригінальний вміст у нижній частині тексту.

Tynt також відстежує це, як це відбувається. Це добре зроблений трюк.

Їх сценарій для цього є вражаючим - замість того, щоб намагатися маніпулювати буфером обміну (що лише старіші версії IE дозволяють їм робити за замовчуванням і які завжди слід вимкнути) вони маніпулюють фактичним вибором.

Отже, коли ви вибираєте блок тексту, додатковий вміст додається як прихований, <div>включений у ваш вибір. Коли ви вставляєте додатковий стиль, ігнорується і з'являється додаткове посилання.

Це насправді досить просто зробити з простими блоками тексту, але кошмар, коли ви враховуєте всі можливі виділення для складного HTML у різних браузерах.

Я розробляю веб-додаток - я не хочу, щоб хтось міг відслідковувати скопійований вміст, і я хотів би, щоб додаткова інформація містила щось контекстне, а не просто посилання. Сервіс Tynt в цьому випадку не дуже підходить.

Хтось знає про бібліотеку JavaScript з відкритим кодом (можливо, модуль jQuery або подібне), що забезпечує подібні функціональні можливості, але не відкриває внутрішні дані додатків?


1
Подивіться на мою відповідь на сайті stackoverflow.com/questions/6344588/… . Робиться це дуже аналогічно тому, як ви запропонували
Ніклас

1
Дивіться також stackoverflow.com/questions/1203082 / ...
Gnubie

48
Будь ласка, не робіть цього. БУДЬ ЛАСКА, БУДЬ ЛАСКА.
couchand

5
@couchand чому б і ні? Я розумію, як це дратує на спам-сайтах, але це для програми, яка може використовуватися для цитат і де внутрішні дані є чутливими. Тому я не хотів використовувати Tynt.
Кіт

4
Ви впевнені, що хочете це зробити? Як користувач, я ненавиджу це, і я буду гнівати цей гнів у вашому продукті: Не торкайтесь мого буфера обміну!
aloisdg переходить на codidact.com

Відповіді:


138

Оновлення 2020 року

Рішення, яке працює у всіх останніх браузерах.

document.addEventListener('copy', (event) => {
  const pagelink = `\n\nRead more at: ${document.location.href}`;
  event.clipboardData.setData('text', document.getSelection() + pagelink);
  event.preventDefault();
});
Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br/>
<textarea name="textarea" rows="7" cols="50" placeholder="paste your copied text here"></textarea>


[Старіший пост - до оновлення до 2020 року]

Є два основні способи додавання додаткової інформації до скопійованого веб-тексту.

1. Маніпулювання вибором

Ідея полягає в тому, щоб переглянути copy event, а потім додати прихований контейнер з нашою додатковою інформацією до domі розширити вибір до нього.
Цей метод адаптований з цієї статті по c.bavota . Перевірте також Jitbit версію «s для більш складного випадку.

  • Сумісність браузера : Усі основні браузери, IE> 8.
  • Демо : jsFiddle демо .
  • Код Javascript :

    function addLink() {
        //Get the selected text and append the extra info
        var selection = window.getSelection(),
            pagelink = '<br /><br /> Read more at: ' + document.location.href,
            copytext = selection + pagelink,
            newdiv = document.createElement('div');

        //hide the newly created container
        newdiv.style.position = 'absolute';
        newdiv.style.left = '-99999px';

        //insert the container, fill it with the extended text, and define the new selection
        document.body.appendChild(newdiv);
        newdiv.innerHTML = copytext;
        selection.selectAllChildren(newdiv);

        window.setTimeout(function () {
            document.body.removeChild(newdiv);
        }, 100);
    }

    document.addEventListener('copy', addLink);

2. Маніпулювання буфером обміну

Ідея полягає у перегляді copy eventта прямому зміні даних буфера обміну. Це можливо за допомогою clipboardDataвласності. Зауважте, що ця властивість доступна у всіх основних браузерах у read-only; setDataметод доступний тільки в IE.

  • Сумісність браузера : IE> 4.
  • Демо : jsFiddle демо .
  • Код Javascript :

    function addLink(event) {
        event.preventDefault();

        var pagelink = '\n\n Read more at: ' + document.location.href,
            copytext =  window.getSelection() + pagelink;

        if (window.clipboardData) {
            window.clipboardData.setData('Text', copytext);
        }
    }

    document.addEventListener('copy', addLink);

1
Ура! На жаль, нам це потрібно в IE, але це не поганий початок.
Кіт

2
Там повинно бути обхідний шлях для «<попередньо>» тегів, більш гладка версія цього сценарію тут
Alex

15
Зауважте, що "Маніпуляція з буфером обміну" найкраще працює у FireFox, Chrome та Safari, якщо ви перейдете window.clipboardDataна event.clipboardData. IE (v11 теж) не підтримують event.clipboardData jsfiddle.net/m56af0je/8
MEMS

3
Якщо ви використовуєте Google Analytics тощо, ви навіть можете закрити подію, щоб зареєструвати, що користувачі копіюють з вашого сайту. Цікаво
geedubb

2
Перший варіант ігнорує нові символи рядка скопійованого тексту.
soham

7

Це рішення ванільного javascript з модифікованого рішення вище, але підтримує більше браузерів (метод перехресного браузера)

function addLink(e) {
    e.preventDefault();
    var pagelink = '\nRead more: ' + document.location.href,
    copytext =  window.getSelection() + pagelink;
    clipdata = e.clipboardData || window.clipboardData;
    if (clipdata) {
        clipdata.setData('Text', copytext);
    }
}
document.addEventListener('copy', addLink);

3

Найкоротша версія для jQuery, яку я тестував і працює, це:

jQuery(document).on('copy', function(e)
{
  var sel = window.getSelection();
  var copyFooter = 
        "<br /><br /> Source: <a href='" + document.location.href + "'>" + document.location.href + "</a><br />© YourSite";
  var copyHolder = $('<div>', {html: sel+copyFooter, style: {position: 'absolute', left: '-99999px'}});
  $('body').append(copyHolder);
  sel.selectAllChildren( copyHolder[0] );
  window.setTimeout(function() {
      copyHolder.remove();
  },0);
});

де код, який фактично копіює результат у буфер обміну?
vsync

@vsync Я вважаю, що це просто додає функціональність перед початком копіювання (що робиться системою, коли користувач ініціює її).
TerranRich

@vsync - як сказав TerraRich, я намагався відповісти на запитання, яке стосувалося додавання додаткової інформації в скопійований текст, тому рішення охоплює лише цю частину.
користувач2276146

3

Ось плагін у jquery для цього https://github.com/niklasvh/jquery.plugin.clipboard В проекті readme "Цей скрипт змінює вміст виділення до виклику події копіювання, в результаті чого скопійований вибір відрізняється від обраного користувачем.

Це дозволяє додавати / додавати вміст до вибору, наприклад, інформацію про авторські права чи інший вміст.

Випущено під ліцензією MIT "


1
Це виглядає дуже перспективно. Він використовує вбудовані стилі, які ми не допускаємо з нашою CSP, але це потенційно може бути адаптоване. Ура!
Кіт

3

Удосконалюючи відповідь, відновіть вибір після внесення змін, щоб запобігти випадковим виборам після копіювання.

function addLink() {
    //Get the selected text and append the extra info
    var selection = window.getSelection(),
        pagelink = '<br /><br /> Read more at: ' + document.location.href,
        copytext = selection + pagelink,
        newdiv = document.createElement('div');
    var range = selection.getRangeAt(0); // edited according to @Vokiel's comment

    //hide the newly created container
    newdiv.style.position = 'absolute';
    newdiv.style.left = '-99999px';

    //insert the container, fill it with the extended text, and define the new selection
    document.body.appendChild(newdiv);
    newdiv.innerHTML = copytext;
    selection.selectAllChildren(newdiv);

    window.setTimeout(function () {
        document.body.removeChild(newdiv);
        selection.removeAllRanges();
        selection.addRange(range);
    }, 100);
}

document.addEventListener('copy', addLink);

@TsukimotoMitsumasa Там повинно бутиvar range = selection.getRangeAt(0);
Vokiel

Відновлення вибору тексту - хороша ідея, інакше воно порушує поведінку браузера за замовчуванням.
Сергій

2

Покращення на 2018 рік

document.addEventListener('copy', function (e) {
    var selection = window.getSelection();
    e.clipboardData.setData('text/plain', $('<div/>').html(selection + "").text() + "\n\n" + 'Source: ' + document.location.href);
    e.clipboardData.setData('text/html', selection + '<br /><br />Source: <a href="' + document.location.href + '">' + document.title + '</a>');
    e.preventDefault();
});

1
Під час копіювання-вставки ви втрачаєте форматування ( <a> , <img> , <b> та інші теги). Краще отримати HTML-код вибраного тексту. Використовуйте функцію getSelectionHtml () з цієї відповіді: [ stackoverflow.com/a/4177234/4177020] А тепер ви можете замінити цей рядок var selection = window.getSelection();цим:var selection = getSelectionHtml();
Дмитро Кулахін

0

Також трохи коротше рішення:

jQuery( document ).ready( function( $ )
    {
    function addLink()
    {
    var sel = window.getSelection();
    var pagelink = "<br /><br /> Source: <a href='" + document.location.href + "'>" + document.location.href + "</a><br />© text is here";
    var div = $( '<div>', {style: {position: 'absolute', left: '-99999px'}, html: sel + pagelink} );
    $( 'body' ).append( div );
    sel.selectAllChildren( div[0] );
    div.remove();
    }



document.oncopy = addLink;
} );

0

Це компіляція із 2 відповідей вище + сумісність з Microsoft Edge.

Я також додав відновлення початкового вибору в кінці, як очікується за замовчуванням у будь-якому браузері.

function addCopyrightInfo() {
    //Get the selected text and append the extra info
    var selection, selectedNode, html;
    if (window.getSelection) {
        var selection = window.getSelection();
        if (selection.rangeCount) {
            selectedNode = selection.getRangeAt(0).startContainer.parentNode;
            var container = document.createElement("div");
            container.appendChild(selection.getRangeAt(0).cloneContents());
            html = container.innerHTML;
        }
    }
    else {
        console.debug("The text [selection] not found.")
        return;
    }

    // Save current selection to resore it back later.
    var range = selection.getRangeAt(0);

    if (!html)
        html = '' + selection;

    html += "<br/><br/><small><span>Source: </span><a target='_blank' title='" + document.title + "' href='" + document.location.href + "'>" + document.title + "</a></small><br/>";
    var newdiv = document.createElement('div');

    //hide the newly created container
    newdiv.style.position = 'absolute';
    newdiv.style.left = '-99999px';

    // Insert the container, fill it with the extended text, and define the new selection.
    selectedNode.appendChild(newdiv); // *For the Microsoft Edge browser so that the page wouldn't scroll to the bottom.

    newdiv.innerHTML = html;
    selection.selectAllChildren(newdiv);

    window.setTimeout(function () {
        selectedNode.removeChild(newdiv);
        selection.removeAllRanges();
        selection.addRange(range); // Restore original selection.
    }, 5); // Timeout is reduced to 10 msc for Microsoft Edge's sake so that it does not blink very noticeably.  
}

document.addEventListener('copy', addCopyrightInfo);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.