Как программно скопировать асинхронный зависимый контент в буфер обмена после щелчка?

Я пытаюсь программно использовать execCommand в Chrome (сборка 43), чтобы скопировать результат асинхронного запроса JSONP в буфер обмена. Вот фрагмент логики:

loadContent()

function loadContent(callback) {
  $.getJSON('http://www.randomtext.me/api/lorem/p-5/10-20?&callback=myFunc',function(result){
    console.log('result=',result.text_out);
    $("#container").html(result.text_out);
    if (callback) {
      callback();
    }
  });
}

function copyAjax() {

 loadContent(copy);

}

function copy() {
  var copyDivText = $('#container').text();
  console.log('copyDivText=',copyDivText);
  executeCopy(copyDivText);
}

document.addEventListener("DOMContentLoaded", function(){
      document.getElementById("copy").onclick = copy;
    });


document.addEventListener("DOMContentLoaded", function(){
      document.getElementById("copyAjax").onclick = copyAjax;
    });


// Copy text as text
function executeCopy(text) {
    var input = document.createElement('textarea');
    document.body.appendChild(input);
    input.value = text;
    input.focus();
    input.select();
    document.execCommand('Copy');
    input.remove();
}

Я знаю, что, начиная со сборки 43 Chrome, вы используете execCommand с буфером обмена. Однако проблема заключается в том, что вам нужно сделать это во время выполнения пользовательского события (в котором права доступа повышены). Это аналогичное ограничение есть у решения на основе ZeroClipboard на основе флэш-памяти. За исключением получения ответа, что это невозможно (о чем я сейчас думаю), это другие варианты, которые я думал сделать в крайнем случае (предупреждение, все они Проходы Богородицы):

  1. Поскольку JSONP не может быть синхронным, превратите его во что-то, что использует обычный вызов AJAX, и убедитесь, что вызов AJAX синхронен в контексте выполнения пользовательского события. Это противоречит моему глубоко укоренившемуся убеждению, что мы не должны выполнять синхронные вызовы XHR, поскольку это ухудшает пользовательский опыт.
  2. Когда пользователь приближается с мышью к кнопке копирования, мы предварительно отправляем запрос к серверу и надеемся, что он будет достаточно быстрым, прежде чем пользователь нажмет кнопку. Это очевидное состояние гонки, которое может отсутствовать часть времени и не будет работать наверняка, когда пользователь хочет выполнить Ctrl/Command-C вместо нажатия кнопки копирования.
  3. Выполните двухэтапный процесс. Один щелчок, чтобы инициировать вызов, когда контент доступен, показать сообщение о доступности контента и нажать еще один щелчок в области сообщения, чтобы скопировать в буфер обмена. Это не похоже на лучшее UX-взаимодействие. Я создал этот пример с этой альтернативой. Инициация щелчка программным способом не является событием проблем пользователя. .
  4. Может быть способ создать простое расширение Chrome и позволить пользователю установить для этого расширения разрешение на копирование в буфер обмена. Это предполагает, что конечный пользователь должен установить и расширить и изменить настройки локального браузера. Не уверен, что многие пользователи смогут/захотят это сделать.

Я уже рассматривал вопросы Stackoverflow, такие как это, но они не относятся к асинхронному сценарию. Пожалуйста, дайте мне знать, если вы можете найти какое-либо другое работоспособное решение (или настроить существующее).


person Gabriel Kohen    schedule 08.06.2015    source источник
comment
Вы придумали какие-либо дополнительные идеи для этого? У меня есть точная ситуация, когда пользователь запрашивает копирование, и мне нужно совершить обратный путь к серверу, чтобы получить данные из БД. Использование вашего 3-го предложения кажется лучшим из 4-х зол :( ....   -  person pythonator    schedule 08.07.2016
comment
› 2. Выполните двухэтапный процесс. Я недавно реализовал это. Базовый UX заключается в том, что когда пользователь нажимает кнопку «Получить ссылку», вы делаете запрос ajax и отображаете счетчик. После завершения запроса вы отображаете текстовый ввод вместе с небольшой кнопкой копирования рядом с ним (например, значок ввода в начале загрузки css). Убедитесь, что текст автоматически выделяется во входных данных. Щелчок по значку должен скопировать в буфер обмена пользователя. Вы можете настроить взаимодействие, чтобы сделать его как можно более приятным с учетом ограничений (например, я сделал ввод, выбирая весь текст при focusIn).   -  person les2    schedule 21.11.2016


Ответы (1)


Это рабочий подход тайм-аута, основанный на вашем фрагменте:

HTML:

<div id="container">
Enter Text To Copy</br>
<textarea id="clipboard"></textarea>
</div>
<input type="button" value="Copy" id="copy"/>

JS:

var timeout = 600; // timeout based on ajax response time
var loaded = false;

function loadContent() {
  loaded = false;
  $.getJSON('http://codepen.io/gkohen/pen/QbvoQW.js',function(result){
    document.getElementById("clipboard").value = result.lorem;
    loaded = true;
  });
}

// Copy text as text
function copy() {
  clipboard = document.getElementById("clipboard");
  if (!loaded || clipboard.value.length == 0) {
    alert("Ajax timeout! TIP: Try to increase timeout value.");
    return;
  }

  clipboard.focus();
  clipboard.select();

  if (document.execCommand('Copy'))
    alert("Successfuly coppied to clipboard!");

  // set defaults
  clipboard.value = "";
  loaded = false;
}

document.addEventListener("DOMContentLoaded", function(){
  document.getElementById("copy").onmousedown = loadContent;
  document.getElementById("copy").onclick = function() {
    setTimeout(copy, timeout); // wait for ajax
  }
});

Основная проблема заключается в спецификации execCommand. Существуют некоторые ограничения в отношении безопасности и доверенных действия. Таким образом, вы должны сделать копию вызова события и вызов ajax. Это можно сделать грязным способом - фиксированным тайм-аутом (код выше) или правильным способом - прерываемым сном. Новая функция сна упоминается здесь и, возможно, может быть изменена на разрушаемый вариант. через clearTimeout, но я не пробовал.

person bigless    schedule 27.11.2016
comment
Возможно, вы могли бы сделать то, что я упомянул здесь: РЕШЕНО: копия execCommand документа не работает с AJAX - person Nishanth Matha; 13.04.2017