file-upload.js
js
const handleClick = async () => {
const files = await getFiles();
if (files.length) {
// 업로드 API 실행
console.log(files);
}
};
const getFiles = () => {
return new Promise((resolve) => {
const fileInput = document.createElement("input");
const handler = () => {
resolve(fileInput.files);
};
fileInput.setAttribute("type", "file");
fileInput.setAttribute("accept", "image/*");
fileInput.setAttribute("multiple", "true");
fileInput.onchange = handler;
fileInput.oncancel = handler;
fileInput.click();
});
};
debounce.js
js
/**
* Debounce
*
* @param callback {Function} Callback function
* @param _delay {Number} Delay time
* @return {Function} Event Listener
*/
const debounce = (callback, ms) => {
let timer = null
return function(...args){
const self = this
clearTimeout(timer)
timer = setTimeout(() => {
callback.apply(self, args)
}, ms)
}
}
const log = debounce(console.log, 100)
log('1')
log('2')
log('3')
log('4')
// 4
debounce.ts
ts
export const debounce = (callback, ms = 100) => {
let timer
return function(...args: any[]) {
clearTimeout(timer)
timer = setTimeout(() => {
callback(...args)
}, ms)
}
}
highlight.js
js
const highlight = (target, keyword, template = `<span>$1</span>`) => {
if (!keyword) {
return target
}
const reg = new RegExp(`(${keyword})`, 'gi')
return target.replace(reg, template)
}
is-primitive.js
js
const isPrimitive = value => {
switch (true) {
case value === undefined:
case value === null:
return true
case typeof value === 'object':
case typeof value === 'function':
case Number.isNaN(value):
return false
default:
return true
}
}
module.exports = {isPrimitive}
is-object.js
js
const isNull = value => value === null;
const isArray = value => Array.isArray(value);
const isObject = value => [
!isNull(value),
!isArray(value),
typeof value === 'object',
].every(v => v);
const arr = [null, undefined, {}, '', []];
console.log(arr.map(isObject)); // [false, false, true, false, false]
console.log(arr.map(isArray)); // [false, false, false, false, true]
is-valid-url.js
js
const isValidUrl = url => {
try {
new URL(url)
return true
} catch (e) {
return false
}
}
console.log(isValidUrl('http://www.naver.com')) // true
console.log(isValidUrl('http:/')) // false
more-text.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>
.txt{
width: 200px;
max-height: 35px;
line-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
word-wrap: break-word;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.txt.show{display:block;max-height:none}
.txt.show + .more{display:none}
</style>
</head>
<body>
<div class="wrap">
<div class="txt">
가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마
가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마가나다라마
</div>
<a href="#" class="more" onclick="toggle()">More</a>
</div>
<script>
const toggle = () => {
const txt = document.querySelector('.txt').classList
if (txt.contains('show')) {
txt.remove('show')
} else {
txt.add('show')
}
}
</script>
</body>
</html>
overlap.js
js
const isOverlap = (base, target) => {
if (target.end <= base.begin) return false
if (target.begin >= base.end) return false
return true
}
const assert = v1 => v2 => console.log(v1 === v2)
const base = {begin: 2, end: 4}
assert(false)(isOverlap(base, {begin: 0, end: 1})) // true
assert(false)(isOverlap(base, {begin: 1, end: 2})) // true
assert(true)(isOverlap(base, {begin: 2, end: 3})) // true
assert(true)(isOverlap(base, {begin: 3, end: 4})) // true
assert(false)(isOverlap(base, {begin: 4, end: 5})) // true
assert(false)(isOverlap(base, {begin: 5, end: 6})) // true
assert(true)(isOverlap(base, {begin: 2, end: 4})) // true
assert(true)(isOverlap(base, {begin: 1, end: 5})) // true
query-to-string.js
js
const queryToString = obj => {
if (!obj) {
return ''
}
const query = Object
.entries(obj)
.map(item => item.join('='))
.join('&')
return `?${query}`
}
console.log(queryToString({
name: 'Peter.Cho',
address: 'Korea'
}))
stepper.ts
ts
export class Stepper {
readonly min: number
readonly max: number
readonly step: number
private position: number
private constructor(min: number, max: number, step: number, position: number) {
this.min = min
this.max = max
this.step = step
this.position = position
}
get isMax(): boolean {
return this.position === this.max
}
get isMin(): boolean {
return this.position === this.min
}
get currentPosition(): number {
return this.position
}
next(): void {
this.changePosition(this.position + this.step)
}
prev(): void {
this.changePosition(this.position - this.step)
}
moveTo(position: number): void {
this.changePosition(position)
}
private changePosition(position: number): void {
this.position = this.calibratePosition(position)
}
private calibratePosition(position: number): number {
return position > this.max
? this.max
: position < this.min
? this.min
: position
}
static create(max: number): Stepper {
return new Stepper(1, max, 1, 1)
}
}
subset.js
js
// base: [begin: number, end: number]
// target: [begin: number, end: number]
const isSubset = (base, target) => {
if (base[0] > target[0]) return false
if (base[1] < target[1]) return false
if (base[0] >= target[1] ) return false
if (base[1] <= target[0] ) return false
return true
}
const assert = v1 => v2 => console.log(v1 === v2)
const base = [2, 4]
assert(false)(isSubset(base, [0, 1]))
assert(false)(isSubset(base, [1, 2]))
assert(true)(isSubset(base, [2, 3]))
assert(true)(isSubset(base, [3, 4]))
assert(false)(isSubset(base, [4, 5]))
assert(false)(isSubset(base, [5, 6]))
assert(true)(isSubset(base, [2, 4]))
assert(false)(isSubset(base, [1, 5]))
throttle.js
js
/**
* Throttle
*
* @param callback {Function} Callback function
* @param _threshhold {Number} Throttle time
* @return {Function} Event Listener
*/
const throttle = (callback, ms = 100) => {
let timer = null
let last = 0
return function (...args) {
const self = this
const now = +new Date
if (last && now < last + ms){
clearTimeout(timer)
timer = setTimeout(() => {
last = now
callback.apply(self, args)
}, ms)
} else {
last = now
callback.apply(self, args)
}
}
}
const log = throttle(console.log, 1000)
setInterval(() => {
console.log('------')
log('1000')
console.log('------')
}, 500)
throttle.ts
ts
export const throttle = (callback, ms = 100) => {
let timer
let last = 0
return function(...args: any[]) {
const now = Date.now()
if (last && now < last + ms) {
clearTimeout(timer)
timer = setTimeout(() => {
last = now
callback(...args)
}, ms)
} else {
last = now
callback(...args)
}
}
}
toggle.ts
ts
export class ToggleHelper {
private state: boolean
private constructor(state: boolean) {
this.state = state
}
on(): void {
this.state = true
}
off(): void {
this.state = false
}
toggle(): void {
this.state = !this.state
}
get isOn(): boolean {
return this.state
}
static create(state: boolean): ToggleHelper {
return new ToggleHelper(state)
}
}