JavaScript execCommand('copy') 不工作

JavaScript execCommand('copy') not working

我无法使用 execCommand('copy'),试图复制在 multi-select 选项中 selected 的值。我正在 "temp" 中获取值,但临时获取的值未复制或获取到剪贴板中。

{
        $propArr=array_unique($properties);
        echo "<div class='table-responsive'>";
            echo "<table class='bordered'>";
            foreach($propArr as $keyProp =>$val){
                echo "<tr>";
                    echo "<td>$val</td><td>";
                    echo "<select name='propval' id='propval' onclick='showpropval(this.value);' class='form-control' multiple>";
                    foreach($values as $k => $v){
                        if($val==$k){
                            foreach($v as $kv =>$fval){
                                echo "<option value='$fval'>$fval</option>";
                            }
                        }
                    }
                    echo "</select>";
                    echo"</td>";
                echo "</tr>";
            }
            echo "</table>";
        echo "</div>";
        }

<script>
        function showpropval(val)
        {
            var temp = val;
            temp.execCommand("copy");

        }
    </script>

试试这个:

function showpropval(val) {
    var temp = val;
    document.execCommand("copy",false,val);
}

我了解到您的意图如下:您想在 select 后立即将 selected 选项的值复制到剪贴板。

当您使用 document.execCommand('copy') 时,您可以复制页面上 select 编辑的任何内容(例如段落中的内容或输入字段本身中的内容)。

然而,selecting <select> 中的选项不被视为 selected 文本。更糟糕的是,如果您想通过 javascript 触发 selecting 文本,则有一些限制:您只能在 <input> 或 [=16= 上调用 .select() ]元素。

我会这样做:将 selected 选项复制到一个单独的(不可见的)输入字段,select 它并从中复制内容。

这里有一个可以作为演示的fiddle:https://jsfiddle.net/Zomry/metcfvcq/13/

我会在这里分解它:

首先,将此元素添加到页面中。这是我们将从中复制内容到剪贴板的输入字段。请注意,我添加了 tabindex -1,因此您无法通过 tab 键访问它。我还包含了 aria-hidden,因此屏幕阅读器知道它应该忽略它。

<input class='copyfrom' tabindex='-1' aria-hidden='true'>

然后通过将输入字段从屏幕上移开使其不可见(如果我尝试显示:none;或其他技巧则无效)

<style>
    .copyfrom {
        position: absolute;
        left: -9999px;
    }
</style>

然后将值复制到输入字段,select它并复制它。

var input = document.querySelector("input.copyfrom"); // select the input field

function showpropval(val) {
    var selectedValues = getSelectValues(this); // get selected values
    input.value = test.join(','); // join them in a comma separated list
    input.select(); // select offscreen inputs text
    document.execCommand("copy"); // copy it
    this.focus(); // focus back on original, so we don't see any glitches
} 

// credits to: 
function getSelectValues(select) {
    var result = [];
    var options = select && select.options;
    var opt;

    for (var i=0, iLen=options.length; i<iLen; i++) {
        opt = options[i];

        if (opt.selected) {
          result.push(opt.value || opt.text);
        }
    }
  return result;
}

我遇到过其他 "copy" 命令不起作用的情况。 ExecCommand 返回 true,但未复制该值。在我的例子中,问题是执行命令的函数(准确地说是一个 Promise)。也许是一个小样本(使用 Zomry 的回答中的函数):

function copyToClipboardButtonHandler_Working() {
  //copy logic executed directly here works
  showpropval('this works');
}

function copyToClipboardButtonHandler_NotWorking() {
  //copy logic executed directly here works
  myService.doSomeLogicAndReturnPromiseWithAString().then(text =>
     showpropval(text) /*this does NOT work'*/
  );
}

如果我解释正确,命令必须在人类调用的同一脚本执行迭代中调用。由于 Promise 的回调在其他迭代中,浏览器拒绝它(尽管它说它没有)。我不知道这是不是真的,但代码对我有用,这很好 ;)

好的,我的方法稍微简单一点:

  1. 创建类型为 'text'
  2. 的额外输入
  3. 在您的函数调用中,将所选选项的值复制到 额外字段
  4. 给出额外的字段绝对位置并留下 -9999 所以它存在于 dom 但不在可见视口中!
  5. 做剩下的事!

这是一个例子:

function copyUserName() {

    //just_for_copy is my invisible extra field
    document.getElementById('just_for_copy').value = document.getElementById('user_phone').value;

    var justForCopy = document.getElementById('just_for_copy');

    justForCopy.select();

    document.execCommand("copy");
}
  function CopyToClipboard(element) {
      var $temp = $("<input>");
      $("body").append($temp);
      $temp.val($(element).text()).select();
      document.execCommand("copy", false, $temp.val());
      $temp.remove();
  }

没有直接关系,但似乎是说这个的好地方。使用 document.execCommand() 时,用于提供 "text" 的元素必须在页面上可见。所以使用 display: none;将导致此失败也尝试使元素高度:0;宽度:0;也打破了这个功能。我解决了这个问题,但将元素定位为绝对位置并将其移离屏幕。

希望这对某人有所帮助:-)

感谢@Zomry,我在 Angular 9 上调整了你对 Typescript 的回复,这里是:

copyColor(colorCode: string) {
    // funcion que copia al clipboard
    const colorClicked = this.findColorObject(colorCode);
    const copyText = document.getElementById(`${colorClicked.id}`) as               HTMLInputElement;
    copyText.select();
    document.execCommand('copy');
  }
.input-color{
  /* visibility: hidden;
  height: 0px; */
  position: absolute;
  left: -9999px;
}
 <div *ngFor="let color of ColorList" class="col-4 p-0">
    <div (click)="copyColor(color.color)">
        <p>{{color.name}}</p>
        <input class="input-color" id="{{color.id}}" value="{{color.color}}" type="text" tabindex='-1' aria-hidden='true'/>
        <p>{{color.color}}</p>
      </div>
  </div>

我试图隐藏输入,但直到我在您的 CSS 定位中找到这个解决方案,它才起作用。我希望有人觉得它有用。

2021 年,当与 Internet Explorer 的兼容性最终(几乎)无关紧要时,可能的最简单 解决方案是:

function copyToClipboard(value) {
  navigator.clipboard.writeText(value)
}