티스토리 뷰

반응형

제 블로그 내에 코드 블럭을 클릭하면 자동으로 복사가 되는 소스를 구현해보았습니다.  소스는 생각보다 간단하였는데 이를 알기 위해서는 DOM에 대한 기본 지식이 있는 것이 좋을 것 같습니다. 위의 그림처럼 clipboard.js 를 사용하여도 무방하지만 거창하게 사용하고 싶지 않고 간단하게 작성하고자 하는 분들을 위해 글을 작성해보았습니다.

DOM(Document Object Model): HTML 파일 내의 컨트롤은 DOM을 통해 이루어집니다. 즉 DOM은 웹 페이지에 대한 인터페이스입니다. 기본적으로 여러 프로그램들이 페이지의 콘텐츠 및 구조, 그리고 스타일을 읽고 조작할 수 있도록 API를 제공합니다. 보다 자세한 내용은 아래 링크를 통해 확인해주세요 :)

https://wit.nts-corp.com/2019/02/14/5522

 

DOM은 정확히 무엇일까? | WIT블로그

최근 잘못 이해하고 있었던 DOM에 대해 정확한 개념을 정리해 보고자 What, exactly, is the DOM? 문서를 번역해 보았습니다.

wit.nts-corp.com

 

그 다음 확인해볼 것은 자바스크립트 소스입니다. 위에 글에도 나와있지만 스크립트 내에서는 각 노드에 해당하는 DOM을 만들기 위해 아래와 같이 작성합니다.

let copyToClipboard = document.createElement('textarea');

 

HTML은 하나의 페이지 문서라고 보시면 이해하기 쉽습니다. DOM에서 제공해주는 객체가 document 입니다. 이 객체를 활용해서 DOM을 interaction할 수 있게 해줍니다.

저의 경우는 createElement 메소드를 호출하고 그 안에 내용을 적었습니다. 'textarea' 는 말 그대로 <textarea> 태그를 생성한다는 의미입니다. 그리고 안에 내용을 넣는 스크립트는 아래와 같습니다.

copyToClipboard.value = '안에 들어갈 콘텐츠의 내용입니다.';

 

그리고 생성된 Element를 DOM에 넣기 위한 소스입니다. appendChild 메소드를 사용합니다. document.body 는 페이지 내의 body 태그를 의미합니다.

document.body.appendChild(copyToClipboard);

 

 이를 클립보드에 넣기 위해서는 명령어를 사용합니다. 시스템 명령어를 사용하는 메소드는 execCommand 이며 클립보드에 복사를 하기 위해 'copy' 라는 값을 넣었습니다. (9999는 문자열의 최대 길이입니다.)

-다시 확인해보니 해당 메소드는 deprecated 되었다고 하지만 사용 못하는 것은 아니기에 적었습니다. - 

copyToClipboard.select();
copyToClipboard.setSelectionRange(0, 9999);
document.execCommand('copy');

 

클립보드에 복사가 된 내용은 body에서 더 사용될 일이 없으므로 removeChild 메소드를 이용해서 삭제합니다.

document.body.removeChild(copyToClipboard);

이 내용을 하나의 소스로 정리하면 이렇게 됩니다. 편의를 위해 jQuery를 사용해보았습니다.

// code 선택자
$('code').on('click', function(e){
  let copyToClipboard = document.createElement('textarea');
  
  // 태그가 필요한 것은 아니므로
  copyToClipboard.value = e.target.innerText;
  document.body.appendChild(copyToClipboard);
  copyToClipboard.select();
  copyToClipboard.setSelectionRange(0, 9999); 
  document.execCommand('copy');
  document.body.removeChild(copyToClipboard);
}

실제 사용하고 있는 소스.html

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    .copied {
      font-size: 12px;
      padding: 12px;
      background-color: rgba(65, 105, 225, 0.87);
      color: rgba(255, 255, 255, 0.93);
      border-radius: 30px;
    }
    .copied_div {
      width: 100%;
      text-align: center;
      top: 90%;
      left: 50%;
      position: absolute;
      transform: translate(-50%,-50%);
      display: none;
    }
    .fadein-box {
      animation: fadein 0.3s;
      -moz-animation: fadein 0.3s; /* Firefox */
      -webkit-animation: fadein 0.3s; /* Safari and Chrome */
      -o-animation: fadein 0.3s; /* Opera */
    }
    .fadeout-box {
      animation: fadeout 0.3s;
      -moz-animation: fadeout 0.3s; /* Firefox */
      -webkit-animation: fadeout 0.3s; /* Safari and Chrome */
      -o-animation: fadeout 0.3s; /* Opera */
    }
    @-webkit-keyframes fadein { /* Safari and Chrome */
      from {
        opacity:0;
      }
      to {
        opacity:1;
      }
    }
    @-webkit-keyframes fadeout { /* Safari and Chrome */
      from {
        opacity: 1;
      }
      to {
        opacity: 0;
      }
    }
  </style>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button id="button">버튼</button>

<div id="where"></div>
<!--<div class="copied_div">-->
<!--  <span class="copied">복사되었어요!</span>-->
<!--</div>-->

</body>
<script>
  let el = document.getElementById('button');
  el.onclick = function() {
    let div = document.createElement('div');
    div.className = 'copied_div';
    let copied = document.createElement('span');
    copied.className = 'copied';
    copied.innerText = '복사되었어요!';
    div.append(copied);
    div.style = 'display: block';
    let where = document.getElementsByTagName("body")[0];
      where.append(div);
    where.className = 'fadein-box';
    setTimeout(() => {
      where.className = 'fadeout-box';
      setTimeout(() => {
        div.style = 'display: none';
      }, 1000)
    }, 1000)

    el.style = 'display: none';
  }

</script>
</html>

 

반응형
댓글
공지사항