copy-text.js
js
// 사용자 이벤트 후 발생하도록 해야 함
const copyText = (value) => {
const textarea = Object.assign(
document.createElement('textarea'),
{value}
)
document.body.appendChild(textarea)
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
}
download.js
js
const downloadFile = (url) => {
const a = Object.assign(document.createElement('a'), {
href: url,
download: true
})
a.click()
}
csv.ts
ts
interface Props {
listData: string[][];
fileName: string;
}
const downloadCSVFile = ({ listData, fileName }: Props) => {
const BOM_FOR_KOREAN = "\uFEFF";
const options = {
type: "text/csv",
};
const content = listData
.map((item) => {
return item.map((innerItem) => `"${innerItem}"`).join(",");
})
.join("\n");
const csvBlob = new Blob([`${BOM_FOR_KOREAN}${content}`], options);
const href = window.URL.createObjectURL(csvBlob);
Object.assign(document.createElement("a"), {
href,
download: `${fileName}_${Date.now()}.csv`,
}).click();
window.URL.revokeObjectURL(href);
};
event-trigger.js
js
const triggerEvent = (el, type) => {
const event = document.createEvent('Event')
event.initEvent(type, true, true)
el.dispatchEvent(event)
}
triggerEvent(document.getElementById('target'), 'touchstart')
html-to-special-char.js
js
const htmlToSpecialChar = html => html
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
storage.js
js
const BROWSER_STORAGE = sessionStorage
const setItem = (key, value) => {
BROWSER_STORAGE.setItem(key, JSON.stringify(value))
}
const getItem = (key) => {
return JSON.parse(BROWSER_STORAGE.getItem(key))
}
textarea-auto.html
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.wrap {
width: 200px;
position: relative;
background-color: #f9f9f9;
}
.wrap textarea {
position: absolute;
width: 100%;
height: 100%;
padding: 0;
}
.wrap .shadow {
visibility: hidden;
opacity: 0;
word-break: break-all;
}
.wrap textarea,
.wrap .shadow {
font-size: 20px;
line-height: 120%;
}
</style>
</head>
<body>
<div class="wrap">
<textarea oninput="onChange(this)"></textarea>
<div class="shadow"> </div>
</div>
<script>
function onChange({value}) {
document.querySelector('.shadow').innerHTML = ` ${value}`;
}
</script>
</body>
</html>
textarea-auto-no-enter.html
html
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<style>
.wrap {
width: 200px;
background-color: #f9f9f9;
}
.wrap textarea {
font-size: 20px;
}
</style>
</head>
<body>
<div class="wrap">
<textarea
onkeydown="action.onKeyDown(event)"
oninput="action.onInput()"
></textarea>
</div>
<script>
const ONE_LINE = 25
const textarea = document.querySelector('textarea');
const renderHeight = () => {
textarea.value = state.value
textarea.style.height = state.height
textarea.setAttribute('rows', state.rows)
}
const state = {
lineLength: 1,
value: '',
get height () {
return `${state.lineLength * ONE_LINE}px`
},
get rows () {
return state.lineLength
}
}
const mutation = {
mutateLineLength: length => {
state.lineLength = length
renderHeight();
},
mutateValue: value => {
const removedNewLine = value.split(/\n/g).join('')
state.value = removedNewLine
renderHeight();
}
}
const action = {
onKeyDown: (event) => {
if (event.key === 'Enter') {
event.preventDefault();
}
},
onInput: () => {
mutation.mutateValue(textarea.value)
mutation.mutateLineLength(1)
requestAnimationFrame(() => {
const {scrollHeight} = textarea
const lineLength = Math.round(scrollHeight / ONE_LINE)
mutation.mutateLineLength(lineLength)
})
},
}
renderHeight()
</script>
</body>
</html>