サイトアイコン たくましゅくじょ

非表示のinput要素ではクリップボードへのコピーが行われなかった

Webアプリを製作していて、hidden(隠し)タイプのinput要素のValueをクリップボードにコピーする処理を作っていました。
ソースは以下です。

<button onclick="hogeCopy();">コピー</button> <!-- これをクリックで隠しinput要素の値をクリップボードにコピー -->
<input type="text" id="hideInput" value="hoge" />

<script type="text/javascript">
function hogeCopy(){

  // input要素を選択して全文セレクト
  const hideInput = document.getElementById("hideInput");
  hideInput.focus();
  hideInput.setSelectionRange(0, hideInput.value.length);

  // 選択範囲をコピー
  document.execCommand('copy');
  window.getSelection().collapse(document.body, 0);

  // 選択を解除
  const active_element = document.activeElement;
  if(active_element){
    active_element.blur();
  }
}
</script>

これをボタンをおして実行してみたところ、コピーできない…!
ですが type=”hidden” を type=”text” にするとコピーできるんですよね…
おそらくこの辺は仕様でそうなっているんだと思います。
ではこれをどう解決するか。

①CSSで見えなくする(おすすめ度:低)

input要素を type=”text” にし、CSSで隠してしまう方法。
あまりおすすめではない。
なぜならせっかくこれで見えなくしても他のcssファイルを読み込んだら変なふうに表示されてしまうということもあるから。
それでも実装したいとしたらこんなところ。

hideInput {
  border: none !important;
  background-color: inherit !important;
  box-shadow: none !important;
  color: rgba(0, 0, 0, 0) !important;
}

!important の嵐である…。
これは、他のライブラリとかでcssの定義がされていた際にも強制的に見えなくするためです。
ちなみに、以下の方法では隠せても挙動が type=”hidden” と変わらずボタンを押してもコピーされませんでした。

上記の通り、ブラウザで見えていないとダメっぽい…ので色を背景と合わせたり文字を透明にして対処しています(苦しい)。

②JavaScriptでどうにかしてしまう(おすすめ度:高)

ボタンをクリックしてJavaScriptを実行した時だけDOMの要素を作り、そのDOMに値を埋め込んでコピーしてしまう方法です。
これなら他のcssファイルに影響を受けることなく実行できますね。
その場合のJavaScriptのソースコードは以下のようになります。


function hogeCopy(){

  // 元のinput要素を取得
  const hideInput = document.getElementById("hideInput");

  // その場限りのinput要素を作る
  const newInput = document.createElement("input");
  newInput.type = "text";

  // 処理は一瞬で見えないけど、一応画面外に追い出す…
  newInput.style.position = "absolute";
  newInput.style.marginLeft = "200vw";
  hideInput.parentNode.insertBefore(newInput, hideInput.nextSibling);
  newInput.value = hideInput.value;

  newInput.focus();
  newInput.setSelectionRange(0, newInput.value.length);

  // 選択範囲をコピー
  document.execCommand('copy');
  window.getSelection().collapse(document.body, 0);

  // 選択を解除
  const active_element = document.activeElement;
  if(active_element){
    active_element.blur();
  }

  // 作ったinput要素を消す
  newInput.parentNode.removeChild(newInput);
}

以上です。

モバイルバージョンを終了