文档execCommand复制与AJAX不起作用

7

我无法直接复制生成的链接(不使用ctrl+C)。

我正在使用document.execCommand('copy'),但它似乎没有效果。

如果代码没有 AJAX,则其工作完美。

这是

HTML:

<div class="permalink-control"> </div>

JQUERY:

    $(".permalink-control")
          .append(
            '<div class="input-group">' +
            '    <span class="input-group-btn"><button type="button" class="btn btn-default" title="Get Permalink"><span class="glyphicon glyphicon-link"></span></button></span>' +
            '    <input type="text" class="form-control">' +
            '</div>'
          );
        $(".permalink-control input")
          .hide()
          .focus(function () {
            // Workaround for broken selection: https://dev59.com/9G025IYBdhLWcg3wyZEn
            var $this = $(this);
            $this.select()
              .mouseup(function () {
                $this.unbind("mouseup");
                return false;
              });
          });
        $(".permalink-control button")
          .click(function () {
            var $this = $(this);
            $.ajax({
              url: "https://api-ssl.bitly.com/shorten",
              dataType: "jsonp",
              data: {
                longUrl: window.location.href,
                access_token: "your access token",
                format: "json"
              },
              success: function (response) {
                var longUrl = Object.keys(response.results)[0];
                var shortUrl = response.results[longUrl].shortUrl;
                if (shortUrl.indexOf(":") === 4) {
                  shortUrl = "https" + shortUrl.substring(4);
                }
                $this.parents(".permalink-control")
                  .find("input")
                  .show()
                  .val(shortUrl)
                  .focus();
              },
              async:false
            });
          });

更新:

如何在JavaScript中复制到剪贴板?

不是回答我的问题,因为如果没有使用 AJAX,我的代码也可以复制而无需使用 ctrl+C。 然而,当我使用 AJAX 时,document.execCommand('copy') 不起作用。


@AndreiGheorghiu 复制是有效的,只是当您点击按钮时无效。 - A. L
我的代码也是直接复制链接。但是当我使用AJAX时,链接没有被复制。 - Hemant
1
@AndreiGheorghiu 您找到了一个无关的答案。当您直接点击输入时,复制操作可以正常工作,但是当您点击其他内容(如按钮)时,则无法正常工作。更不用说这些答案现在非常陈旧且不相关了。 - A. L
@AndreiGheorghiu 我已经知道那个答案了,请仔细阅读我的问题。 - Hemant
1
你唯一的选择是在用户点击之前填充输入值。在你的使用情况下,这是否可行?如果你不想在每次页面加载时触发$.ajax()调用,请设置一个更大的不可见元素围绕按钮,并在鼠标进入不可见元素时触发ajax。虽然不是万无一失,但总比没有好。一个好的技巧可能是将按钮放在下拉菜单、抽屉、弹出窗口、模态框或工具提示中。当用户打开它时,在它打开之前获取响应。并在ajax返回之前禁用按钮。 - tao
显示剩余4条评论
2个回答

7
这是因为在W3规范中已经明确说明:

仅当脚本API触发的剪切和复制命令由用户触发并被信任的事件分派,或者如果实现被配置允许,则只会影响真实剪贴板的内容。

但是,既然如此我们可以尝试通过复制文本when a user does some interaction来欺骗浏览器。

在这种情况下,因为您正在寻找click事件,我假设您的用户正在与mouse交互

那么,如果我在解析ajax之后附加$(window).blur()$(document).click()事件呢?

没错,因为用户必须在某个时候blur才能使用复制选择,用户将启动一个blur() or click() (depending on your need),我们就可以将文本复制到剪贴板上。

这里有一个HACKY DEMO

$(document).ready(function(){
    var shortUrl;
    $(".permalink-control")
      .append(
        '<div class="input-group">' +
        '    <span class="input-group-btn"><button type="button" class="btn btn-default" title="Get Permalink"><span class="glyphicon glyphicon-link"></span></button></span>' +
        '    <input type="text" class="form-control">' +
        '</div>'
      );
     $(".permalink-control input")
      .hide()
      .focus(function () {
        // Workaround for broken selection: https://dev59.com/9G025IYBdhLWcg3wyZEn
        var $this = $(this);
        $this.select();
        document.execCommand('copy');
          $this.mouseup(function () {
            $this.unbind("mouseup");
            return false;
          });
      });
    $(".permalink-control button")
      .click(function () {
        var shortUrl ="";
        var $this = $(this);
        $.ajax({
          url: "https://api-ssl.bitly.com/shorten",
          dataType: "jsonp",
          data: {
            longUrl: window.location.href,
            access_token: "48ecf90304d70f30729abe82dfea1dd8a11c4584",
            format: "json"
          },
          success: function (response) {
             var longUrl = Object.keys(response.results)[0];
            shortUrl = response.results[longUrl].shortUrl;
            if (shortUrl.indexOf(":") === 4) {
              shortUrl = "https" + shortUrl.substring(4);
            }
              $this.parents(".permalink-control")
              .find("input")
              .show()
              .val(shortUrl)
              .focus();
            } 
       }).done(function(){
            $(window).blur(function(){
       document.execCommand('copy');
              $(window).off('blur');// make sure we don't copy anything else from the document when window is foucussed out
            });
       })
    });
})
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="permalink-control"></div> 
<div class"log"></div>

注: 这已在 Chrome 中进行了测试。


{btsdaf} - ploopploop
在IE 11中有效,但在Chrome 63.x和Firefox 57.x中无效。 - Dairo

4
我曾经遇到过同样的问题。我采用了比较原始的办法来解决:在单击事件的处理程序内,可以运行一个间隔器来检查ajax将在响应服务器后插入值的变量。在接收到答案后,我们停止间隔器并开始使用剪贴板。没有问题,因为用户自己在单击后启动间隔器,而无需任何回调。
简单的 jQuery 示例:
var ajaxResponse;

function copyText(copiedText){
  $('<textarea class="copied-text">' + copiedText + '</textarea>').appendTo('body');

  if ( navigator.userAgent.match(/ipad|iphone/i) ) {
    var range = document.createRange(),
        textArea = $('.copied-text')[0];
    range.selectNodeContents(textArea);
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
    textArea.setSelectionRange(0, 999999);
  } else {
    $('.copied-text').select();
  }

  document.execCommand('copy');
  $('.copied-text').remove();
};

function myAjaxFunc(){
  $.ajax({
    type: 'POST',
    url: yourUrl,
    data: yourData,
    success: function(data){
      ajaxResponse = data;
    }
  });
};

$('.your-button').on('click', function(){
  myAjaxFunc();
  var ajaxCheckTimer = setInterval(function(){
    if ( ajaxResponse ) {
      copyText(ajaxResponse);
      clearInterval(ajaxCheckTimer);
    };
  }, 100);
});

在此示例中,单击按钮时,我们向服务器发送一些数据,并开始间隔检查 ajaxResponse 变量的值。
在接收到服务器响应后,将服务器响应写入此变量,然后间隔中的条件变为 true 并调用文本复制函数,并指定服务器响应变量作为参数:copyText(ajaxResponse);。间隔停止。 copyText 函数在页面上创建一个具有 ajaxResponse 变量值的文本区域,将该值从字段复制到剪贴板,并从页面中删除该字段。


更新 01.07.19

为了确保在 iOS 上正确复制到剪贴板,请向文本字段添加属性 contenteditable,值为 true
$('<textarea class="copied-text" contenteditable="true">' + copiedText + '</textarea>').appendTo('body');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接