Javascript + браузер копировать в буфер обмена не удается с данными, превышающими ~ 150 КБ с использованием document.execCommand ('copy') - PullRequest
0 голосов
/ 18 мая 2018

Копировать в буфер обмена с помощью document.execCommand ('copy') (а-ля https://stackoverflow.com/a/30810322/3160967) отлично работает с небольшими объемами данных, а также работает, если вы переходите с помощью отладчика, но не работает, когда размер данных достигает примерно150k (и вы не переходите с помощью отладчика).

Кроме того, кажется, что работает, если код, начинающийся с window.getSelection (), выполняется асинхронно. Почему? И является ли асинхронное решение стабильным, илиэто просто маскировка, но не решение проблемы?

Использование Chrome версии 66.0.3359.139

Чтобы воспроизвести эту проблему, откройте DevTools и выполните следующее:

function doclick() { 
  copyTest(); 
}

document.addEventListener('click', doclick);

function copyTest() {
    var data = [];
    var n = 20000; // works if n is smaller e.g. < ~6000

    for(var i = 0; i < n; i++)
      data[i] = String(Math.random());

    var textarea = document.createElement('textarea');
    textarea.value = data.join('\t')

    document.body.appendChild(textarea);

    var sel = window.getSelection(); // works if debugger breaks here or earlier
    sel.removeAllRanges();

    var r = document.createRange();
    r.selectNode(textarea);
    sel.addRange(r);

    document.execCommand('copy');
    document.body.removeChild(textarea);
    alert('copied ' + textarea.value.length);
}

ПослеЯ запускаю это в DevTools, нажимаю на страницу, чтобы запустить doCopy (), но буфер обмена остается неизменным. Однако, если n <6000 или около того, он будет успешным. Кроме того, он будет работать, если я установлю точку останова на указанномна строчку выше, а затем продолжите выполнение кода после его разрыва. </p>

Более того, кажется, что ниже работает:

function copyTest() {
    var data = [];
    var n = 20000; // works only if n is smaller e.g. < ~6000

    for(var i = 0; i < n; i++)
      data[i] = String(Math.random());

    var textarea = document.createElement('textarea');
    textarea.value = data.join('\t')

    document.body.appendChild(textarea);

    function copy() {
        var sel = window.getSelection(); // works if debugger breaks here or earlier
        sel.removeAllRanges();

        var r = document.createRange();
        r.selectNode(textarea);
        sel.addRange(r);

        document.execCommand('copy');
        document.body.removeChild(textarea);
        alert('copied ' + textarea.value.length);
    }
    window.setTimeout(copy); // this works
}

Однако я не уверен, почему этот должен работа. ЯПохоже, что когда window.getSelection вызывается сразу после document.body.appendChild, когда добавляемый дочерний элемент имеет достаточный объем данных, window.getSelection завершается ошибкой, возможно, потому что для document.body.appendChild требуется еще один асинхронный цикл?В любом случае, каково «правильное» решение этой проблемы - в чистом JS?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...