简体   繁体   English

JavaScript execCommand('copy') 不起作用

[英]JavaScript execCommand('copy') not working

I am unable to use the execCommand('copy'), trying to copy value which is selected in multi-select option.我无法使用 execCommand('copy'),试图复制在多选选项中选择的值。 iam getting value in "temp" but the value which is getting in temp not copying or getting in clipboard.我在“temp”中获取值,但在 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>

I understand that your intention is the following: you want to copy the values of the selected options to the clipboard as soon as you select it.我了解您的意图如下:您希望在选择后立即将所选选项的值复制到剪贴板。

When you use document.execCommand('copy') , you copy whatever is selected on the page (such as content in a paragraph or in an input field itself).当您使用document.execCommand('copy') ,您复制页面上选择的任何内容(例如段落中的内容或输入字段本身中的内容)。

The catch is however that selecting options in <select> is not considered to be selected text.然而,问题是在<select>中选择选项不被认为是选定的文本。 Worse yet, if you would like to trigger selecting text via javascript, there are some restrictions: you can only call .select() on an <input> or a <textarea> element.更糟糕的是,如果您想通过 javascript 触发选择文本,则有一些限制:您只能在<input><textarea>元素上调用.select()

Here is what I would do: copy the selected options to a separate (not visible) input-field, select it and copy the content from that.这是我要做的:将选定的选项复制到一个单独的(不可见的)输入字段,选择它并从中复制内容。

Here is a fiddle that can serve as a demo: https://jsfiddle.net/Zomry/metcfvcq/13/这是一个可以作为演示的小提琴: https : //jsfiddle.net/Zomry/metcfvcq/13/

I wil break it down here:我将在这里分解它:

First, add this element to the page.首先,将此元素添加到页面。 This is the input-field where we will copy the content from to the clipboard.这是我们将内容复制到剪贴板的输入字段。 Note that I have added tabindex -1 so you cannot reach it via tab key.请注意,我添加了 tabindex -1,因此您无法通过 Tab 键访问它。 I also included aria-hidden so screenreaders know it should ignore this.我还包括了 aria-hidden 以便屏幕阅读器知道它应该忽略这一点。

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

Then make the input field invisible by putting it off screen (did not work if I tried display: none; or other tricks)然后通过将其移出屏幕使输入字段不可见(如果我尝试 display: none; 或其他技巧,则不起作用)

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

Then copy the value to the input field, select it and copy it.然后将值复制到输入字段,选择它并复制它。

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: https://stackoverflow.com/questions/5866169/how-to-get-all-selected-values-of-a-multiple-select-box
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;
}

In 2021, when compatibility with Internet Explorer is finally (almost) irrelevant, the simplest possible solution is: 2021 年,当与 Internet Explorer 的兼容性最终(几乎)无关紧要时,最简单的可能解决方案是:

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

Not directly related but seems like a good place to say this.没有直接关系,但似乎是说这个的好地方。 When using the document.execCommand(), the element that is being used to supply the "text" must be visible on the page.使用 document.execCommand() 时,用于提供“文本”的元素必须在页面上可见。 So using display: none;所以使用 display: none; will cause this to fail also trying to make the element height: 0;将导致此失败也试图使元素高度:0; width: 0;宽度:0; also breaks this function.也打破了这个功能。 I got round this but positioning the element absolute and moving it far off the screen.我解决了这个问题,但是将元素绝对定位并将其移离屏幕很远。

Hope this helps someone :-)希望这对某人有所帮助:-)

I had other case of "copy" command not working.我还有其他“复制”命令不起作用的情况。 ExecCommand returned true, but the value was not copied. ExecCommand 返回 true,但未复制该值。 In my case the problem was the function which executed the command (a Promise, to be exact).在我的情况下,问题是执行命令的函数(准确地说是 Promise)。 Maybe a small sample (using the function from Zomry's answer):也许是一个小样本(使用 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'*/
  );
}

If I interpret correctly, command has to be invoked in the same script execution iteration that was invoked by a human.如果我解释正确,则必须在人类调用的同一脚本执行迭代中调用命令。 Since Promise's callback is in other iteration, browser denies it (although it says it doesn't).由于 Promise 的回调在其他迭代中,浏览器拒绝它(尽管它说它没有)。 I do not know if this is true, but the code works for me, which is fine ;)我不知道这是否属实,但代码对我有用,这很好;)

ok, my approach is a little bit easier:好的,我的方法稍微简单一点:

  1. create an extra input with type 'text'创建一个类型为 'text' 的额外输入
  2. on your function call copy the value of the selected option to the extra field在您的函数调用中,将所选选项的值复制到额外的字段
  3. give extra field position absolute and left -9999 so it exists in dom but not in the visible viewport!给额外的字段位置绝对和左 -9999 所以它存在于 dom 但不在可见视口中!
  4. do the rest!做剩下的!

here's an example:这是一个例子:

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();
  }

Try this:尝试这个:

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

thanks to @Zomry I adapted your response to Typescript on Angular 9 and here is:感谢@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>

I was trying to hidde the input but it doesn´t work until i found this solution in your CSS positioning.我试图隐藏输入,但在我在您的 CSS 定位中找到此解决方案之前它不起作用。 I hope someone find it usefull.我希望有人觉得它有用。

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

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