[javascript] JavaScript로 클립 보드에 복사하는 방법

텍스트를 클립 보드에 복사하는 가장 좋은 방법은 무엇입니까? (멀티 브라우저)

나는 시도했다 :

function copyToClipboard(text) {
    if (window.clipboardData) { // Internet Explorer
        window.clipboardData.setData("Text", text);
    } else {
        unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
        const clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
        clipboardHelper.copyString(text);
    }
}

그러나 Internet Explorer에서는 구문 오류가 발생합니다. Firefox에서는라고 말합니다 unsafeWindow is not defined.

플래시가없는 좋은 방법 : Trello는 어떻게 사용자의 클립 보드에 액세스합니까?



답변

개요

클립 보드에 복사하기위한 세 가지 기본 브라우저 API가 있습니다.

  1. 비동기 클립 보드 API [navigator.clipboard.writeText]
    • Chrome 66 에서 제공되는 텍스트 중심 부분 (2018 년 3 월)
    • 액세스는 비동기식이며 JavaScript Promises를 사용 하므로 보안 사용자 프롬프트 (표시되는 경우)가 페이지의 JavaScript를 방해하지 않도록 작성할 수 있습니다.
    • 변수에서 직접 텍스트를 클립 보드로 복사 할 수 있습니다.
    • HTTPS를 통해 제공되는 페이지에서만 지원됩니다.
    • Chrome 66에서 활성 탭의 페이지는 권한 프롬프트없이 클립 보드에 쓸 수 있습니다.
  2. document.execCommand('copy')
    • 대부분의 브라우저는 2015 년 4 월 ~ 현재이를 지원합니다 (아래 브라우저 지원 참조).
    • 액세스는 동 기적입니다. 즉, 표시 및 사용자가 보안 프롬프트와 상호 작용하는 것을 포함하여 완료 될 때까지 페이지에서 JavaScript를 중지합니다.
    • DOM에서 텍스트를 읽고 클립 보드에 배치합니다.
    • ~ 2015 년 4 월 ~ 테스트 동안 클립 보드에 쓰는 동안 Internet Explorer 만 권한 프롬프트를 표시하는 것으로 나타났습니다.
  3. 복사 이벤트 재정의
    • 복사 이벤트 재정의에 대한 클립 보드 API 설명서를 참조하십시오 .
    • 복사 이벤트에서 클립 보드에 표시되는 내용을 수정하고 일반 텍스트 이외의 다른 형식의 데이터를 포함 할 수 있습니다.
    • 질문에 직접 대답하지 않으므로 여기에서 다루지 않습니다.

일반적인 개발 노트

콘솔에서 코드를 테스트하는 동안 클립 보드 관련 명령이 작동하지 않아도됩니다. 일반적으로 페이지가 활성화되어 있거나 (Async Clipboard API) 클립 보드 document.execCommand('copy')에 액세스 할 수 있도록 사용자 상호 작용 (예 : 사용자 클릭)이 필요합니다 ( 자세한 내용은 아래 참조).

중요 (여기에서 2020/02/20으로 표시)

이 게시물은 원래 교차 출처 IFRAME 및 기타 IFRAME “샌드 박스” 에서 권한이 더 이상 사용되지 않기 때문에 임베디드 데모 “Run code snippet”버튼 및 “codepen.io example”이 일부 브라우저 (Chrome 및 Microsoft Edge 포함)에서 작동하지 못하게합니다. ).

자체 웹 페이지를 개발하려면 HTTPS 연결을 통해 해당 페이지를 제공하여 테스트 및 개발하십시오.

다음은 코드 작동을 보여주는 테스트 / 데모 페이지입니다.
https://deanmarktaylor.github.io/clipboard-test/

비동기 + 폴백

새로운 Async Clipboard API에 대한 브라우저 지원 수준으로 인해 document.execCommand('copy')브라우저 범위 를 넓히기 위해 메소드로 대체하려고 할 것 입니다.

다음은 간단한 예입니다 (이 사이트에 포함되지 않은 경우 위의 “중요”참고 사항 참조).

function fallbackCopyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;

  // Avoid scrolling to bottom
  textArea.style.top = "0";
  textArea.style.left = "0";
  textArea.style.position = "fixed";

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    console.error('Async: Could not copy text: ', err);
  });
}

var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:

  </textarea>
</div>

(codepen.io 예제가 작동하지 않을 수 있습니다. 위의 “중요한”참고 사항을 읽으십시오)이 스 니펫은 Stack Overflow의 내장 미리보기에서 제대로 작동하지 않습니다. https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors = 1011

비동기 클립 보드 API

Chrome 66의 권한 API를 통해 ‘권한을 요청’하고 클립 보드에 대한 액세스를 테스트하는 기능이 있습니다.

var text = "Example text to appear on clipboard";
navigator.clipboard.writeText(text).then(function() {
  console.log('Async: Copying to clipboard was successful!');
}, function(err) {
  console.error('Async: Could not copy text: ', err);
});

document.execCommand ( ‘copy’)

이 포스트의 나머지 부분은 document.execCommand('copy')API 의 미묘한 차이와 세부 사항에 대해 설명 합니다.

브라우저 지원

JavaScript document.execCommand('copy')지원이 커졌습니다. 브라우저 업데이트는 아래 링크를 참조하십시오.

간단한 예

(이 사이트에 포함되어 작동하지 않을 수 있습니다. 위의 “중요”참고 사항을 읽으십시오)

var copyTextareaBtn = document.querySelector('.js-textareacopybtn');

copyTextareaBtn.addEventListener('click', function(event) {
  var copyTextarea = document.querySelector('.js-copytextarea');
  copyTextarea.focus();
  copyTextarea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }
});
<p>
  <button class="js-textareacopybtn" style="vertical-align:top;">Copy Textarea</button>
  <textarea class="js-copytextarea">Hello I'm some text</textarea>
</p>

복잡한 예 : 입력을 표시하지 않고 클립 보드에 복사

위의 간단한 예는 화면에 textarea또는 input요소가 표시되어 있으면 효과적 입니다.

경우에 따라 input/ textarea요소 를 표시하지 않고 클립 보드에 텍스트를 복사 할 수 있습니다 . 이 문제를 해결하는 방법의 한 예입니다 (기본적으로 요소 삽입, 클립 보드에 복사, 요소 제거).

Chrome 44, Firefox 42.0a1 및 Internet Explorer 11.0.8600.17814에서 테스트되었습니다.

(이 사이트에 포함되어 작동하지 않을 수 있습니다. 위의 “중요”참고 사항을 읽으십시오)

function copyTextToClipboard(text) {
  var textArea = document.createElement("textarea");

  //
  // *** This styling is an extra step which is likely not required. ***
  //
  // Why is it here? To ensure:
  // 1. the element is able to have focus and selection.
  // 2. if element was to flash render it has minimal visual impact.
  // 3. less flakyness with selection and copying which **might** occur if
  //    the textarea element is not visible.
  //
  // The likelihood is the element won't even render, not even a
  // flash, so some of these are just precautions. However in
  // Internet Explorer the element is visible whilst the popup
  // box asking the user for permission for the web page to
  // copy to the clipboard.
  //

  // Place in top-left corner of screen regardless of scroll position.
  textArea.style.position = 'fixed';
  textArea.style.top = 0;
  textArea.style.left = 0;

  // Ensure it has a small width and height. Setting to 1px / 1em
  // doesn't work as this gives a negative w/h on some browsers.
  textArea.style.width = '2em';
  textArea.style.height = '2em';

  // We don't need padding, reducing the size if it does flash render.
  textArea.style.padding = 0;

  // Clean up any borders.
  textArea.style.border = 'none';
  textArea.style.outline = 'none';
  textArea.style.boxShadow = 'none';

  // Avoid flash of white box if rendered for any reason.
  textArea.style.background = 'transparent';


  textArea.value = text;

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }

  document.body.removeChild(textArea);
}


var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:

  </textarea>
</div>

추가 사항

사용자가 조치를 취한 경우에만 작동

document.execCommand('copy')클릭 이벤트 핸들러와 같은 사용자 작업의 직접적인 결과로 모든 호출이 이루어져야합니다. 이는 사용자 클립 보드가 예상하지 못한 경우 사용자의 클립 보드가 엉망이되는 것을 방지하기위한 조치입니다.

자세한 내용은 여기 에서 Google 개발자 게시물 을 참조하십시오.

클립 보드 API

전체 클립 보드 API 초안 사양은 https://w3c.github.io/clipboard-apis/ 에서 확인할 수 있습니다.

지원됩니까?

  • document.queryCommandSupported('copy')true“브라우저에서 지원하는”명령이면 반환 해야합니다.
  • document.queryCommandEnabled('copy')반환 true(가) 경우 document.execCommand('copy')지금이라고하면 성공합니다. 사용자 시작 스레드에서 명령이 호출되었고 다른 요구 사항이 충족되는지 확인

그러나 브라우저 호환성 문제의 예로, ~ 4 월에서 ~ 10 월 2015까지 Chrome 은 명령이 사용자 시작 스레드에서 호출 된 경우 에만 반환 true되었습니다 document.queryCommandSupported('copy').

아래의 호환성 세부 사항에 유의하십시오.

브라우저 호환성 세부 사항

사용자 클릭의 결과로 호출 document.execCommand('copy')try/ catch블록 으로 래핑 된 간단한 호출 은 당신에게 가장 호환성을 제공하지만 다음과 같은 조항이 있습니다.

어느 전화 document.execCommand, document.queryCommandSupported또는이 document.queryCommandEnabledA의 포장되어야한다 try/ catch블록.

서로 다른 브라우저 구현과 브라우저 버전은 return 대신에 호출 될 때 다른 유형의 예외를 발생 false시킵니다.

다른 브라우저 구현은 여전히 ​​유동적이며 클립 보드 API 는 아직 초안이므로 테스트를 수행해야합니다.


답변

클립 보드로 자동 복사하는 것은 위험 할 수 있으므로 대부분의 브라우저 (IE 제외)는 매우 어렵습니다. 개인적으로 다음과 같은 간단한 트릭을 사용합니다.

function copyToClipboard(text) {
  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}

복사 할 텍스트가 이미 선택된 프롬프트 상자가 사용자에게 표시됩니다. 이제 Ctrl+ CEnter(상자를 닫으려면) 를 누르면 충분합니다 .

이제 클립 보드 복사 작업은 사용자가 수동으로 수행하기 때문에 안전하지만 매우 간단합니다. 물론 모든 브라우저에서 작동합니다.

<button id="demo" onclick="copyToClipboard(document.getElementById('demo').innerHTML)">This is what I want to copy</button>

<script>
  function copyToClipboard(text) {
    window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
  }
</script>


답변

다음 접근 방식은 Chrome, Firefox, Internet Explorer 및 Edge 및 최신 버전의 Safari에서 작동합니다 (2016 년 10 월에 릴리스 된 버전 10에서 복사 지원이 추가됨).

  • 텍스트 영역을 만들고 그 내용을 클립 보드에 복사 할 텍스트로 설정하십시오.
  • 텍스트 영역을 DOM에 추가하십시오.
  • 텍스트 영역에서 텍스트를 선택하십시오.
  • document.execCommand ( “copy”)를 호출하십시오.
  • 돔에서 텍스트 영역을 제거하십시오.

참고 : 텍스트 영역은 동일한 JavaScript 코드 호출 내에서 추가 및 제거되므로 텍스트 영역이 표시되지 않습니다.

직접 구현할 경우주의해야 할 사항 :

  • 보안상의 이유로, 이것은 클릭과 같은 이벤트 핸들러에서만 호출 할 수 있습니다 (창 열기와 마찬가지로).
  • Internet Explorer는 클립 보드를 처음 업데이트 할 때 권한 대화 상자를 표시합니다.
  • 텍스트 영역에 초점이 맞춰지면 Internet Explorer 및 Edge가 스크롤됩니다.
  • 경우에 따라 execCommand ()가 발생할 수 있습니다.
  • 텍스트 영역을 사용하지 않으면 줄 바꿈 및 탭이 삼킬 수 있습니다. (대부분의 기사는 div를 사용하는 것이 좋습니다)
  • 텍스트 영역은 Internet Explorer 대화 상자가 표시되는 동안 표시되며 숨기거나 Internet Explorer 특정 clipboardData API를 사용해야합니다.
  • Internet Explorer 시스템 관리자는 클립 보드 API를 비활성화 할 수 있습니다.

아래의 기능은 다음 문제를 가능한 한 깨끗하게 처리해야합니다. 문제를 발견하거나 개선을위한 제안 사항이 있으면 의견을 남겨주십시오.

// Copies a string to the clipboard. Must be called from within an
// event handler such as click. May return false if it failed, but
// this is not always possible. Browser support for Chrome 43+,
// Firefox 42+, Safari 10+, Edge and Internet Explorer 10+.
// Internet Explorer: The clipboard feature may be disabled by
// an administrator. By default a prompt is shown the first
// time the clipboard is used (per session).
function copyToClipboard(text) {
    if (window.clipboardData && window.clipboardData.setData) {
        // Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
        return clipboardData.setData("Text", text);

    }
    else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
        var textarea = document.createElement("textarea");
        textarea.textContent = text;
        textarea.style.position = "fixed";  // Prevent scrolling to bottom of page in Microsoft Edge.
        document.body.appendChild(textarea);
        textarea.select();
        try {
            return document.execCommand("copy");  // Security exception may be thrown by some browsers.
        }
        catch (ex) {
            console.warn("Copy to clipboard failed.", ex);
            return false;
        }
        finally {
            document.body.removeChild(textarea);
        }
    }
}

https://jsfiddle.net/fx6a6n6x/


답변

여기에 내가 가져가는 것이 있습니다 …

function copy(text) {
    var input = document.createElement('input');
    input.setAttribute('value', text);
    document.body.appendChild(input);
    input.select();
    var result = document.execCommand('copy');
    document.body.removeChild(input);
    return result;
 }

@ korayem : html input필드 를 사용 하면 줄 바꿈이 존중되지 \n않으며 텍스트가 한 줄로 병합됩니다.

의견에서 @nikksan이 언급했듯이을 사용 textarea하면 다음과 같이 문제가 해결됩니다.

function copy(text) {
    var input = document.createElement('textarea');
    input.innerHTML = text;
    document.body.appendChild(input);
    input.select();
    var result = document.execCommand('copy');
    document.body.removeChild(input);
    return result;
}


답변

정말 간단한 솔루션을 원하고 (통합하는데 5 분도 걸리지 않음) 즉시 사용 가능한 것처럼 보이면 Clippy 는 좀 더 복잡한 솔루션을 대신 할 수있는 훌륭한 대안입니다.

GitHub의 공동 설립자에 의해 작성되었습니다. 아래의 플래시 임베드 코드 예 :

<object
   classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
   width="110"
   height="14"
   id="clippy">
  <param name="movie" value="/flash/clippy.swf"/>
  <param name="allowScriptAccess" value="always"/>
  <param name="quality" value="high"/>
  <param name="scale" value="noscale"/>
  <param NAME="FlashVars" value="text=#{text}"/>
  <param name="bgcolor" value="#{bgcolor}"/>
  <embed
     src="/flash/clippy.swf"
     width="110"
     height="14"
     name="clippy"
     quality="high"
     allowScriptAccess="always"
     type="application/x-shockwave-flash"
     pluginspage="http://www.macromedia.com/go/getflashplayer"
     FlashVars="text=#{text}"
     bgcolor="#{bgcolor}"/>
</object>

대체 기억 #{text}이 복사 필요한 텍스트 및 #{bgcolor}컬러로.


답변

웹 페이지에서 클립 보드를 읽고 수정하면 보안 및 개인 정보 보호 문제가 발생합니다. 그러나 Internet Explorer에서는 그렇게 할 수 있습니다. 이 예제 스 니펫을 발견했습니다 .

    <script type="text/javascript">
        function select_all(obj) {
            var text_val=eval(obj);
            text_val.focus();
            text_val.select();
            r = text_val.createTextRange();
            if (!r.execCommand) return; // feature detection
            r.execCommand('copy');
        }
    </script>
    <input value="http://www.sajithmr.com"
     onclick="select_all(this)" name="url" type="text" />


답변

나는 최근 에이 문제에 대한 기술 블로그 게시물 을 작성했습니다 (나는 Lucidchart에서 일하고 있으며 최근 클립 보드를 점검했습니다).

시스템 복사 이벤트 중 (사용자 CtrlC가 브라우저 메뉴를 누르 거나 사용하는 동안) 일반 텍스트를 클립 보드에 복사하는 것은 비교적 간단 합니다.

var isIe = (navigator.userAgent.toLowerCase().indexOf("msie") != -1
           || navigator.userAgent.toLowerCase().indexOf("trident") != -1);

document.addEventListener('copy', function(e) {
    var textToPutOnClipboard = "This is some text";
    if (isIe) {
        window.clipboardData.setData('Text', textToPutOnClipboard);
    } else {
        e.clipboardData.setData('text/plain', textToPutOnClipboard);
    }
    e.preventDefault();
});

시스템 복사 이벤트가 아닌 동안 클립 보드에 텍스트를 입력하는 것은 훨씬 어렵습니다. 이 다른 답변 중 일부는 Flash를 통해 수행하는 방법을 참조하는 것처럼 보입니다.이 방법은 브라우저 간 유일한 방법입니다 (내가 이해하는 한).

그 외에도 브라우저별로 몇 가지 옵션이 있습니다.

이것은 IE에서 가장 간단합니다. JavaScript를 통해 언제든지 clipboardData 객체에 액세스 할 수 있습니다.

window.clipboardData

그러나 시스템 잘라 내기, 복사 또는 붙여 넣기 이벤트 외부에서이 작업을 시도하면 IE는 사용자에게 웹 응용 프로그램 클립 보드 권한을 부여하라는 메시지를 표시합니다.

Chrome에서 클립 보드 권한 을 제공하는 Chrome 확장 프로그램을 만들 수 있습니다 (이것이 Lucidchart에서 수행하는 작업입니다). 그런 다음 확장 기능이 설치된 사용자의 경우 시스템 이벤트를 직접 시작하면됩니다.

document.execCommand('copy');

Firefox에는 사용자가 특정 사이트에 클립 보드에 액세스 할 수있는 권한을 부여 할 수있는 몇 가지 옵션 이 있지만 개인적으로는 시도하지 않았습니다.