execCommand ('copy') не работает в обратном вызове Ajax / XHR?

(протестировано с помощью Chrome 44)

желаемое поведение: сделайте запрос XHR, поместите результат в текстовую область, выберите текст и скопируйте в буфер обмена.

фактическое поведение: при успешном запросе XHR помещает результат в текстовую область и выбирает его, но не может скопировать результат в буфер обмена. Но если я инициирую копию вне обратного вызова XHR, она работает.

пример html страница:

var selectAndCopy = function() {
  // Select text
  var cutTextarea = document.querySelector('#textarea');
  cutTextarea.select();
  // Execute copy
  var successful = document.execCommand('copy');
  var msg = successful ? 'successful' : 'unsuccessful';
  console.log('Cutting text command was ' + msg);
};

var fetchCopyButton = document.querySelector('#fetch_copy');
fetchCopyButton.addEventListener('click', function(event) {
  var xhr = new XMLHttpRequest();
  xhr.open('get', 'http://httpbin.org/ip');
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        // Set text
        var textarea = document.querySelector('#textarea');
        textarea.value = xhr.responseText;

        selectAndCopy();
      }
    }
  };
  xhr.send();
});

var copyButton = document.querySelector('#copy');
copyButton.addEventListener('click', function(event) {
  selectAndCopy();
});
<html>

<head>
</head>

<body>
  <p>
    <textarea id="textarea">Hello, I'm some text!</textarea>
  </p>
  <p>
    <button id="fetch_copy">Fetch Data and Copy Textarea</button>
    <button id="copy">Copy Textarea</button>
  </p>
</body>

</html>

Если вы нажмете кнопку" Fetch Data and Copy Textarea", данные будут успешно извлечены, но не скопированы. При нажатии на кнопку "Копировать Textarea" текст копируется, как и ожидалось. Я пробовал много комбинаций запроса / копирования, чтобы попытаться заставить его работать, но безрезультатно (включая программное нажатие кнопки копирования после извлечения данных). Кто-нибудь знает, что здесь происходит? Это функция безопасности или что-то?

Я не хочу, чтобы пользователю приходилось нажимать две кнопки для извлечения и копирования, если это возможно.

2 ответов


вы можете вызвать копию в системный буфер обмена только в ответ на действие доверенного пользователя, например click событие.

Spec:http://www.w3.org/TR/clipboard-apis/#integration-with-rich-text-editing-apis


если вы сделаете XMLHttpRequest синхронным, это будет работать. Вам просто нужно добавить false в качестве третьего параметра xhr.open(...):

var selectAndCopy = function() {
  // Select text
  var cutTextarea = document.querySelector('#textarea');
  cutTextarea.select();
  // Execute copy
  var successful = document.execCommand('copy');
  var msg = successful ? 'successful' : 'unsuccessful';
  console.log('Cutting text command was ' + msg);
};

var fetchCopyButton = document.querySelector('#fetch_copy');
fetchCopyButton.addEventListener('click', function(event) {
  var xhr = new XMLHttpRequest();
  xhr.open('get', 'http://httpbin.org/ip', false);
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        // Set text
        var textarea = document.querySelector('#textarea');
        textarea.value = xhr.responseText;

        selectAndCopy();
      }
    }
  };
  xhr.send();
});

var copyButton = document.querySelector('#copy');
copyButton.addEventListener('click', function(event) {
  selectAndCopy();
});
<html>

<head>
</head>

<body>
  <p>
    <textarea id="textarea">Hello, I'm some text!</textarea>
  </p>
  <p>
    <button id="fetch_copy">Fetch Data and Copy Textarea</button>
    <button id="copy">Copy Textarea</button>
  </p>
</body>

</html>