HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A==" crossorigin="anonymous" referrerpolicy="no-referrer"/>
<title>clipboard</title>
</head>
<body>
<div class="container">
<div class="label">
복사 영역
</div>
<div class="copy-text">
<input class="text" type="text">
<button>
<i class="fa fa fa-clone"></i>
</button>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
CSS
.container
컨테이너 가운데로 정렬
.copy-text
input이랑 button을 가로 정렬하기 위해 display:flex;
.copy--text button:before/after
말풍선을 before/after로 만든 후에 display:none;으로 지워두고
active 클래스가 붙으면 display:block;으로 보여주기
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #f0f2f7;
}
.container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.label {
padding: 10px;
font-size: 18px;
color: #111;
}
.copy-text {
position: relative;
padding: 10px;
background: #fff;
border: 1px solid #ddd;
border-radius: 10px;
display: flex;
}
.copy-text input.text {
padding: 10px;
font-size: 18px;
color: #555;
border: none;
outline: none;
}
.copy-text button {
padding: 10px;
background: #5784f5;
color: #fff;
font-size: 18px;
border: none;
outline: none;
border-radius: 10px;
cursor: pointer;
}
.copy-text button:active {
background: #809ce2;
}
.copy-text button:before {
content: "Copied";
position: absolute;
top: -50px;
right: 0px;
background: #5c81dc;
padding: 8px 10px;
border-radius: 20px;
font-size: 15px;
display: none;
}
.copy-text button:after {
content: "";
position: absolute;
top: -22px;
right: 25px;
width: 10px;
height: 10px;
background: #5c81dc;
transform: rotate(45deg);
display: none;
}
/*
active 붙기 전에는 display:none 해두었다가
active 붙으면 display:block으로 보여주기 */
.copy-text.active button:before,
.copy-text.active button:after {
display: block;
}
JS
input.select();
document.execCommend('copy');
HTMLInputElement.select()는 input 또는 textarea의 모든 텍스트를 선택하는 메서드. 복사할 문자가 input/textarea처럼 selection 가능한 입력 영역이면서 hidden이 아니어야 한다.
document.execCommend('copy'); 복사하기
document.execCommend('cut'); 자르기
document.execCommend('paste'); 붙여넣기
는 권장되지 않으므로
-->>
clipboard API를 사용했다.
navigator.clipboard.writeText()로 값을 받아와서(복사 기능)
navigator.clipboard.readText()로 뿌려주는 건데(붙여넣기 기능),
그냥 작성하면 값이 안 받아와지는 걸 보니 비동기로 동작하는 것 같아서(web api니까!) async/await을 사용해줬다. 이유가 맞는지는 모르겠다.
여기서 예외 처리는 할 필요 없으므로 try-catch는 안 해줬다.
아래 코드처럼 단순히 alert로 처리하지 않고 요소에 꽂아넣는 식으로 개발하면 응용할 수 있겠다.
let copyText = document.querySelector('.copy-text');
copyText.querySelector('button').addEventListener('click', async function () {
let input = copyText.querySelector('input.text');
// navigator.clipboard.writeText()로 값을 받아와서 readText()로 뿌려주는 방법
await navigator.clipboard.writeText(input.value);
copyText.classList.add('active');
setTimeout(async function () {
// await 처리 안하면 text에 값이 안 담기네..
const text = await navigator.clipboard.readText();
alert(`${text}가 복사되었어요.`);
copyText.classList.remove('active');
}, 2500);
})
참고