繁体   English   中英

剪贴板复制在 jquery ajax 成功方法中不起作用

[英]clipboard copy does not work in jquery ajax success method

我想将卡号复制到剪贴板,以便我可以将其粘贴到记事本中。 如果在浏览器的开发人员工具栏中尝试,我从互联网上获得的代码效果很好。 但是,如果我将该代码添加到我的 Javascript 文件中并运行该项目,则它不起作用。 以下是代码:

$.ajax({
  type: "POST",
  url: '@Url.Action("CopyToClipboard", "MyAccountSurface")',
  data: {
    controlId: controlId
  },
  dataType: 'json',
  success: function(data) {
    var $temp = $("<input>");
    $("body").append($temp);
    $temp.val(data.CardNumber).select();
    document.execCommand("copy");
    $temp.remove();
    alert('copied successfully');
  }
});

更新:

用户交互是执行document.execCommand所必需的。 因此,在您的情况下,无法从 AJAX 响应中复制文本。 It is the security measure that browsers agreed upon.

参考W3C API

通过脚本 API 触发的复制和剪切命令只会影响真实剪贴板的内容,前提是该事件是从用户信任和触发的事件中分派的,或者如果实现配置为允许这样做。


用户交互的解决方法

添加的步骤:

  • 使用相对位置将文本框放置在远离网页的位置。
  • 添加处于禁用状态的按钮。 一旦数据可用,重新启用按钮。
  • 单击按钮时,您将能够执行document.execCommand因为您直接与浏览器交互( Hence no security issue as mentioned in API

 $(document).ready(function() { $.ajax({ url: 'https://jsonplaceholder.typicode.com' + '/posts/1', method: 'GET' }).then(function(data) { console.log(data); $('#toBeCopied').val(data.title); $("#copyIt").attr('disabled', null); }); }); function copyToClipboard(){ var $temp = $("<input />"); $("body").append($temp); $temp.val($("#toBeCopied").val()).select(); var result = false; try { result = document.execCommand("copy"); } catch (err) { console.log("Copy error: " + err); } $temp.remove(); }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <input type="text" value="dummy" id="toBeCopied" style="display:none; position: relative; left: -1000px;"> <b>Below button will be enabled once the data is available from AJAX</b> <button id="copyIt" onclick="copyToClipboard()" disabled>Copy To Clipboard</button>

如果您想通过 Ajax 单击复制到剪贴板

您将要单击的元素几乎没有事件: mousedownclick 它们按此顺序触发。 这意味着您可以在第一个发送 ajax 请求并在最后一个处理结果,在这种情况下您不会有安全问题。

让我分享工作示例:

  $link.on("mousedown", function() {
    var url = $(this).data("url");
    var $temp = $("<input id='copy_container' style='position:fixed;left:-200px;'>");

    $.ajax({
      url: url,
      dataType: "json",
      success: function (data) {
        $("body").append($temp);
        $temp.val(data.text);
      }
    })
  })

  $link.on("click", function() {
    setTimeout(function() {
      var $input = $("input#copy_container");
      if ($input.length && $input.val().length > 0) {
        $input.select();
        document.execCommand("copy");
        $input.remove();
      }
    }, 100)
  })

您需要此超时时间为 100 毫秒以等待 ajax 响应。 它可以像你想要的那样改进。

固定和负位置 - 我想你知道我们为什么需要它。

好吧,你在复制什么? document.execCommand("copy"); 首先需要选择(突出显示)某些内容。

我认为在你的例子中, select跟随 .val()。 但是为了让它起作用,你需要选择一个元素,而不是它的价值。

$temp.val(data.CardNumber);
$temp.select();

copied = document.execCommand("copy");
$temp.remove();

if(copied){
    alert('copied successfully');
}else{
    alert('something went wrong');
}
var response;

// recursively using setTimeout to wait for response 
var recCopy = function (){
    if(response){
        copy(response); 
        return;
    }     
    else {
        setTimeout(recCopy,2000); // for e.g. 2ms
    }
}

function copy(value) {
    var tempInput = document.createElement("input");
    tempInput.style = "position: absolute; left: -1000px; top: -1000px";
    tempInput.value = value;
    document.body.appendChild(tempInput);
    tempInput.select();
    try {
            var successful = document.execCommand('copy',false,null);
            var msg = successful ? 'successful' : 'unsuccessful';
            console.log('Copying text command was ' + msg);
        } catch (err) {
            alert('Oops, unable to copy to clipboard');
        }
    document.body.removeChild(tempInput);
}

$('.copyToClipboard').on('mousedown',function (e){
        $.ajax({
          url: "https://www.example.com/xyz",
          data: {
             formData :formData
          },
          type : 'post',
          success: function (data) {     
            response = data;  // on success, update the response
          } 
        }) 
});

$('.copyToClipboard').on('click',function (e){
    recCopy();
});

ajax 调用和复制响应需要分开处理(例如这里已经处理了 click 和 mousedown 事件)。
setTimeout 可以递归地用于检查响应。 收到响应后,可以执行复制到剪贴板。

由于这不是用户交互,因此不会起作用。

我们可以实现的解决方法是,只要鼠标进入用户想要复制数据的区域,就从 ajax 调用中获取数据,并将数据放置在某个文本区域或输入框中。

并且,在点击事件中,我们可以复制剪贴板中的数据。

//按钮的鼠标输入事件

$("#jq-copy-txt").on('mouseenter', function() {
    $.ajax({
      url: 'url',
      method: 'GET'
    }).then(function(data) {
       let copyFrom = document.getElementById("jq-cpy-txt-area"); 
        document.body.appendChild(copyFrom);
        copyFrom .textContent = data.title;
    });
});

// 用户触发的点击事件

$("#jq-copy-txt").on('click', function() {

   var fn = function() {
      let copyFrom = document.getElementsByTagName("textarea")[0];
      copyFrom.select();
      document.execCommand("copy");
    };
    setTimeout(fn, 1000);});

@Anton 说的很好,但这都是不好的做法,因为您依赖服务器在给定的时间给您一个响应,这是不好的,您可以在所有具有复杂后端的大型网站中看到他们只是将其放入一个 HTML 对象,因此用户可以通过 ctrl+c 或通过单击按钮来复制它,我的做法与 Antons 的方式略有不同

$('#btn').on('click', function(e){

    var url = 'Your-link.com';
    var $temp = $("<input id='copy_container' 
        style='position:fixed;left:-200px;'>");
    $.ajax({
      type: "POST",
      url: url,
      success: function(res) {
        $("body").append($temp);
        $temp.val(res);
      },
      error: function() {
         //handle error and do something
      }
    });
    setTimeout(function() {
        var $input = $("input#copy_container");
        if ($input.length && $input.val().length > 0) {
            $input.select();
            document.execCommand("copy");
            $input.remove();
        }
    }, 500)
});   

这样您就不需要重用事件侦听器,但就像我之前所说的那样,它远非完美。 最好把它放在显示给用户的 HTML 元素中。

这是我如何做到的。 您可以将值从 ajax 调用返回成功设置到剪贴板(第一个按钮),或者在需要时将文本从 textarea 复制到剪贴板(第二个按钮)。

<div>
        <div>
            <label>Content</label>
        </div>
        <div>
            <button type="button" onclick="fnGenerate()">Retrieve and Copy To Clipboard</button>
        </div>
        <div>
            <button type="button" onclick="fnCopy()">Copy To Clipboard</button>
        </div>
        <div>
            <div>
                <textarea cols="50" rows="8" id="Content"></textarea>
            </div>
        </div>
    </div>

对于 js 部分

function fnGenerate() {
        $.ajax({                
            type: 'POST',
            dataType: 'json',
            ............
            ............
            url: 'someUrl',                  
            success: function (data, textStatus, xhr) {
                $('#Content').val(data);
                $('#Content').select();
                document.execCommand('copy');
            },
            error: function (xhr) {
                //Do Something to handle error
                var error = xhr.responseText;
            }
        });
    }

    function fnCopy() {
        $("#Content").select();
        document.execCommand('copy');
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM