[Javascript] Clipboard를 사용하는 방법(Ctrl + c 할때 출처 붙이기)


안녕하세요. 명월입니다.


이 글은 Javascript에서 Clipboard를 사용하는 방법(Ctrl + c 할때 출처 붙이기)에 대한 글입니다.


Clipboard란 우리가 임시로 Ctrl + C를 해서 글이나 이미지, 파일 등을 임시로 저장하는 프로그램입니다. clipboard에 관해서는 최근 모든 UI OS계에는 거의 표준으로 장착되어 있고 MAC이나 Ubuntu에서 Ctrl + C가 아닌 다른 단축키로 대응하는 경우가 있습니다.

우리가 흔히 이야기하는 복붙 개념입니다. Clipboard를 잘 활용하면 Web service 환경에서도 꽤 편리하게 사용할 수 있습니다.

가령, CSV를 업로드에서 데이터를 업데이트하는 기능이 있다고 하면 이 clipboard를 이용해서 사용자가 더 간편하게 사용할 수 있게 수정할 수도 있습니다.


우선, 웹 브라우저에서 Ctrl + C를 누를 때, 데이터를 가공하는 방법입니다. 일명, 출처 붙이기 입니다.

<!DOCTYPE html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    hello world<br />
    hello world<br />
    hello world<br />
    hello world<br />
    hello world<br />
    hello world<br />
    hello world<br />
    hello world<br />
    hello world<br />
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script>
      $("body").bind('copy', function (e) {
        var url = document.location.href,
          decodedUrl = decodeURI(url),
          selection = window.getSelection();
        
        // 구 IE8 버젼의 경우.
        if (typeof window.getSelection == "undefined") {
          event.preventDefault();
          if (window.clipboardData) {
            window.clipboardData.setData('Text', selection + '\n\n 출처: [명월 일지]' + decodedUrl);
          }
          return;
        }
        
        // body 돔에 div 엘리먼트를 생성하고 그 안에 pre 태그를 사용해서 html 형식으로 밀어 넣는다.
        // 복사할 임시 엘리먼트는 화면상에 보이면 안되기 때문에 absolute형식으로 좌로 -99999로 넣는다.
        // 참고: display:none을 하면 복사가 되지 않습니다.
        var body_element = document.getElementsByTagName('body')[0];

        var newdiv = document.createElement('div');
        newdiv.style.position = 'absolute';
        newdiv.style.left = '-99999px';
        body_element.appendChild(newdiv);
        // 드래그 선택한 데이터를 복사하여 넣는다.
        newdiv.appendChild(selection.getRangeAt(0).cloneContents());

        // 그리고 하위에 출처를 넣으므로해서 완료한다.
        newdiv.innerHTML += '<br /><br />출처: <a href="' + url + '">' + decodedUrl + '</a> [명월 일지]';

        // 생성한 div를 셀렉트한다.
        selection.selectAllChildren(newdiv);
        // 약간의 딜레이가 필요하기 때문에 setTimeout으로 제어한다.
        window.setTimeout(function () {
          body_element.removeChild(newdiv);
        }, 1);
        // 이 event가 끝나면 자동으로 clipboard 복사를 실시한다.
      });
    </script>
  </body>
</html>

참고 출처 - https://www.w3schools.com/jsref/event_oncopy.asp

참고 출처 - view-source:https://nowonbun.tistory.com 의 약 1700줄정도..

※티스토리 소스를 참고했는데... 이걸 출처 링크 달기가 애네하네요.


Clipboard를 사용한다면 웹 사이트에서 출처 붙이기를 가장 많이 사용하지 않을까 싶습니다. 그러나 그것 이외에도 사용할 데가 많습니다.

예를 들면, textbox로 되어있는 것들을 clipboard로 csv형태로 저장하고 다시 csv형태의 데이터라면 그대로 textbox에 집어넣는 기능입니다. (이걸 활용하여, 유저 사용자 학습이 된다면 매우 편리한 기능이 될지도 모릅니다.)

<!DOCTYPE html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    Name : <input type="text" id="name" class="paste-data"><br />
    NickName : <input type="text" id="nickname" class="paste-data"><br />
    Comment : <input type="text" id="comment" class="paste-data"><br />
    <button id="copy">Copy</button>
    <button id="paste">Paste</button>
    <button id="clear">Clear</button>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script>
      // Clear 버튼을 누르면 텍스트 박스가 초기화됩니다.
      $("#clear").on("click", function(){
        $("#name").val('');
        $("#nickname").val('');
        $("#comment").val('');
      });
      // Copy 버튼을 누르면 클립보드로 복사됩니다.
      $("#copy").on("click", function(){
        var data = $("#name").val() + ','+ $("#nickname").val() + ',' + $("#comment").val();
        $("#copy").data("copy", true);
        $("#copy").data("val", data);
        document.execCommand('copy');
      });
      // 브라우져 보안 때문에 동작을 하지 않습니다.
      // https://developer.chrome.com/extensions/declare_permissions
      // https://stackoverflow.com/questions/6969403/why-is-document-execcommandpaste-not-working-in-google-chrome
      $("#paste").on("click", function(){
        $("#paste").data("paste", true);
        document.execCommand('paste');
      });
      // 키보드로 Ctrl + V를 누를 경우 데이터가 들어갑니다.
      window.addEventListener('paste', function (e){
        /*if($("#paste").data("paste") === undefined){
          return;
        }
        $("#paste").removeData("paste");*/
        var data = e.clipboardData.getData('text/plain');
        var list = data.split(',');
        for(var i=0;i < list.length; i++){
          $($(".paste-data")[i]).val(list[i]);
        }
      });
      $("body").bind('copy', function (e) {
        if($("#copy").data("copy") === undefined){
          return;
        }
        $("#copy").removeData("copy");
        var selection = window.getSelection();
        // body 돔에 div 엘리먼트를 생성하고 그 안에 pre 태그를 사용해서 html 형식으로 밀어 넣는다.
        // 복사할 임시 엘리먼트는 화면상에 보이면 안되기 때문에 absolute형식으로 좌로 -99999로 넣는다.
        // 참고: display:none을 하면 복사가 되지 않습니다.
        var body_element = document.getElementsByTagName('body')[0];

        var newdiv = document.createElement('div');
        newdiv.style.position = 'absolute';
        newdiv.style.left = '-99999px';
        body_element.appendChild(newdiv);
        // data를 넣는다.
        var data = $('#copy').data('val');
        newdiv.innerHTML = data;
        $("#copy").removeData('val');

        // 생성한 div를 셀렉트한다.
        selection.selectAllChildren(newdiv);
        
        // 약간의 딜레이가 필요하기 때문에 setTimeout으로 제어한다.
        window.setTimeout(function () {
          body_element.removeChild(newdiv);
        }, 1);
      });
    </script>
  </body>
</html>

위 소스를 확인하면 Name과 Nickname, Comment에 값을 넣고 copy를 누르면 데이터가 클립보드에 복사가 됩니다.

여기서 clear 버튼을 눌러서 텍스트 박스 데이터를 전부 초기화하고 메모장에 콤마(,) 구분으로 세 데이터를 작성합니다.

※여기서 document.execCommand('paste');는 작동을 하지 않습니다. 아예 작동을 하지 않는 것은 아니고 브라우져에서 보안 설정하면 작동됩니다.

링크 - https://developer.chrome.com/extensions/declare_permissions

링크 - https://support.google.com/chrome/answer/114662?co=GENIE.Platform%3DDesktop&hl=ko


예전에 제가 만들 때는 별도의 설정없이 되었던 걸로 생각되는데, 아마도 보안상에 문제가 있나 봅니다. 그러나 브라우져에서 Ctrl + v를 누르면 위 「window.addEventListener('paste', function)」은 작동합니다.

이 부분도 「$("body").bind('paste', function)」로 작성을 해봤는데 역시 작동을 하지 않습니다. 이슈를 구글링해서 찾아보긴 했는데, 정확한 이유를 모르겠네요.


여기까지 Javascript에서 Clipboard를 사용하는 방법(Ctrl + c 할때 출처 붙이기)에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.