우리가 해 볼 게 위 그림 두 장에 나와있다. 머스크가 인수해서 똥을 싸제끼고 있는 트위터나 마스토돈, 블루스카이에는 한 번에 올릴 수 있는 내용에 글자수 제한이 있다. 트위터는 140자, 마스토돈은 500자(하이퍼스페이스 인스턴스), 블루스카이는 300자.
오늘은 입력창의 글자수를 실시간으로 세 보는 걸 할 건데, 해볼 게 총 두가지이다. 첫번째는 그냥 입력창에 몇 글자가 입력됐는지를 세 주는거고, 두번째가 위 두 장의 사진에 나와있는 n자 제한에서 n자가 남았는지 표시해보는 것이다. 아, 저 원은 아쉽게도 구현을 못 한다. 내 능력 밖임.
입력창의 글자 수를 나타내보자
그러니까 일단 남은 글자수는 모르겠고 몇 글자 썼는지 실시간으로 띄우는 것 먼저 해 보자. 얘를 해야 밑에께 좀 더 쉬워진다. 뭐 해요, VScode 키셔야지.
여기서 h1만 뭐가 없고 밑에 textarea랑 p는 클래스나 아이디가 하나씩은 있다. 왜? JS에서 갖고와야 하니까요.
const inputarea = document.querySelector('#inputarea');
const counter = document.querySelector('.count');
갖고 왔다고 끝이 아닌 거 다들 아시죠? 이제 험난한 코딩이 시작될것이다.
const inputarea = document.querySelector('#inputarea');
const counter = document.querySelector('.count');
inputarea.addEventListener('keyup',()=>{
counter.innerText = inputarea.value.length;
});
그렇게 생각하던 시절이 저에게도 있었습니다. 아니 코드가 진짜로 저게 다다. 그리고 우리가 여기서 봐야 할 부분은 이벤트 리스트너밖에 없다. 진짜 이게 다예요? 네! 이게 답니다! 나도 내 두 눈을 의심했다니까.
여기 보이죠? 텍스트 입력하니까 21자라고 나오는 거.
지금까지 여기서 했던 코딩들을 보면 이벤트 리스트너에 'click'이 들어가 있다. 그러니까 이 클릭은 뭐냐면 뭘 눌렀을 때 이벤트를 발동시켜라 이 얘기다. 근데 이번 코드에는 클릭이 아니라… keyup? 이게 뭐임?
이벤트 리스트너의 트리거 중에는 키업(keyup)과 키다운(keydown)이 있다. 각각 키보드를 놓을 때/키보드를 누를 때 이벤트를 발동시켜라 이건데 무슨 차이인지는 모르겠음… 아무튼 키보드를 누를 때 이벤트를 발동시켜서 저 네모 상자에 입력한 텍스트가 몇 글자인지 알려줘라~ 라는 것만 알아두시면 된다. 그럼 이제 다음걸로 넘어가보자.
남은 글자 수를 나타내보자
일단 이건 위에꺼랑 달리 단순히 몇 글자를 썼냐를 표시하는 게 아니라, 본문 맨 위에 있는 스크린샷처럼 제한 글자 수에서 남은 글자 수를 표시할거다. 예를 들어서 글자 수가 140자라면 아무것도 안 썼을 때 140부터 시작해야 한다. 이해 하셨죠?
이게 아까 그거인데, 총 21자 나온다. 그럼 우리는 최대 글자 수에서 저걸 뺀 만큼을 출력하면 된다. 그러니까 아까 그 코드에서 JS 코드의 이벤트 리스트너 부분을 수정하면 된다. 일단 여기서는 최대 글자 수를 200자로 정해보자.
const inputarea = document.querySelector('#inputarea');
const counter = document.querySelector('.count');
let maxtext = 200;
counter.innerText = maxtext;
inputarea.addEventListener('keyup',()=>{
counter.innerText = maxtext - inputarea.value.length;
});
일단 이 코드에는 두 가지 변경점이 있다. 하나는 위에도 썼듯이 최대 글자 수에서 현재 글자 수를 뺀 걸 출력하게끔 바꾼거고… 다른 하나는 뭔가 하고 코드를 유심히 들여다 본 여러분은 뭔가 두 줄 추가된 것을 발견했다.
let maxtext = 200;
counter.innerText = maxtext;
엥? 이거 머임? 이거 왜 추가했어요? 얘가 없으면 페이지를 갓 띄웠을 때는 남은 글자수가 0으로 나온다. HTML코드에 0으로 되어있거든... 이게 뵈기 싫으면 아예 p태그나 span태그만 만들어놓고 innerText 박아버리는 방법도 있긴 하다. 대신 창이 열렸을 때 내용을 바꾸게 별도로 코딩은 해야겠지만.
그래서 남은 글자수만큼 제대로 표시해준다.
근데 또 여기서 끝내기는 뭔가 아쉽죠? 그래서 한가지를 더 해볼거다. 남은 글자 수에 따라서 저 밑에 숫자 색을 바꿔볼건데… 첫번째로는 전체 글자의 90% 이상을 썼을 때, 그러니까 10%가 남았을 때 주황색으로 바뀌게 할 거고, 두번째로는 글자 수가 전체 글자 수를 초과했을 때(음수가 될 때) 빨간색으로 바꿀거다.
남은 글자 수에 따라 색깔 변경하기
const inputarea = document.querySelector('#inputarea');
const counter = document.querySelector('.count');
let maxtext = 200;
counter.innerText = maxtext;
inputarea.addEventListener('keyup',()=>{
counter.innerText = maxtext - inputarea.value.length;
if (inputarea.value.length < (maxtext * 0.1)) {
console.log(maxtext * 0.1)
counter.classList.add('almost');
} else if (inputarea.value.length > maxtext) {
counter.classList.add('over');
}
});
그래... 이게 한번에 될 리가 없지. 이렇게 해놨더니 글자를 입력하기만 하면 주황색으로 바뀐다...
const inputarea = document.querySelector('#inputarea');
const counter = document.querySelector('.count');
let maxtext = 200;
counter.innerText = maxtext;
inputarea.addEventListener('keyup',()=>{
counter.innerText = maxtext - inputarea.value.length;
if (inputarea.value.length > (maxtext * 0.9)) {
counter.classList.add('almost');
} else if (inputarea.value.length > maxtext) {
counter.classList.add('over');
};
});
뭔가가 안 될때는 코드에 원인이 있음.
뭐가 문제였냐면, 일단 inputarea.value.length는 현재 입력한 글자이다. 그러니까 저 변수를 안 건들고 조건을 제대로 설정하려면 현재 입력한 글자가 180자가 '넘어가야'한다. 왜? 그래야 남은 글자수가 20자 미만이 되니까. 그래서 그거 변경해줬더니 됐다.
여기까지는 됐는데, 글자수가 오버됐을 때 빨간색으로 안 바뀌는겨… 진짜 아무리 해도 안바껴서 채찍피티한테 물어봤다.
const inputarea = document.querySelector('#inputarea');
const counter = document.querySelector('.count');
const maxtext = 200;
counter.innerText = maxtext;
inputarea.addEventListener('keyup', () => {
const length = inputarea.value.length;
const remaining = maxtext - length;
counter.innerText = remaining;
counter.classList.remove('almost', 'over');
if (length > maxtext) {
counter.classList.add('over');
} else if (length > maxtext * 0.9) {
counter.classList.add('almost');
}
});
이 녀석... 독심술 쓰나... 나 코드만 올렸는데 뭐땜시 질문한건지 다 알고 있어... 심지어 저 변수는 내가 갖고 오기만 하면 undefined떠서 에이씨 그냥 생으로 써야겠다 했던건데 저걸 또 해결봐주네… 아무튼 그렇습니다.
const inputarea = document.querySelector('#inputarea');
const counter = document.querySelector('.count');
let maxtext = 200;
counter.innerText = maxtext;
inputarea.addEventListener('keyup',()=>{
counter.innerText = maxtext - inputarea.value.length;
if (inputarea.value.length > (maxtext * 0.9)) {
counter.classList.add('almost');
} else if (inputarea.value.length < (maxtext * 0.9) && counter.classList.contains('almost')) {
counter.classList.remove('almost');
} else if (inputarea.value.length < maxtext && counter.classList.contains('over') && inputarea.value.length > (maxtext * 0.9)) {
counter.classList.remove('over');
} else if (inputarea.value.length > maxtext) {
counter.classList.add('over');
alert('글자수 제한 초과입니다!')
}
;
});
조건문 우선순위 너무 복잡함... 아무튼 수정 포인트를 봅시다. 위 코드가 내가 짰던 코드인데, 보면 if문이 개같이 많아요. 그죠? 그걸 남은 글자 수가 10% 미만일때(200자 제한 기준 19자 이하 남았을 때)랑 남은 글자 수가 음수일때(글자수 초과했을 때) 두 가지로 나눴다. 그리고 우선순위를 올렸다는 건 무슨 얘기냐... if문을 잘 보자.
inputarea.addEventListener('keyup',()=>{
counter.innerText = maxtext - inputarea.value.length;
if (inputarea.value.length > (maxtext * 0.9)) {
counter.classList.add('almost');
} else if (inputarea.value.length < (maxtext * 0.9) && counter.classList.contains('almost')) {
counter.classList.remove('almost');
} else if (inputarea.value.length < maxtext && counter.classList.contains('over') && inputarea.value.length > (maxtext * 0.9)) {
counter.classList.remove('over');
} else if (inputarea.value.length > maxtext) {
counter.classList.add('over');
alert('글자수 제한 초과입니다!')
}
;
});
이게 내가 쓴 코드고
inputarea.addEventListener('keyup', () => {
const length = inputarea.value.length;
const remaining = maxtext - length;
counter.innerText = remaining;
counter.classList.remove('almost', 'over');
if (length > maxtext) {
counter.classList.add('over');
} else if (length > maxtext * 0.9) {
counter.classList.add('almost');
}
});
이게 채찍피티가 쓴 코드다.
두 코드의 if문에서 over가 어디에 위치해있는지 확인해보자. 내가 쓴 코드는 over 클래스가 붙는 조건... 그러니까 글자 수가 제한을 넘겼을 때가 맨 밑에 있고, 채찍피티가 보완해 준 코드는 글자수가 제한을 넘겼을 때를 먼저 처리해준다. 이 위치 차이만으로도 적용되고 안되고가 갈린다. 정말 복잡시럽다.
진짜 채찍피티 있어서 다행이다…
'Coding > JavaScript' 카테고리의 다른 글
::selection 색상을 부분부분 다르게 할 수 있을까? (0) | 2025.04.23 |
---|---|
모바일 뷰포트 확인하는 법(feat. 개발자 도구) (0) | 2025.01.24 |
미디어쿼리에 대해 알아보자 (0) | 2025.01.24 |
간단한 이미지 갤러리를 만들어보자 (0) | 2025.01.07 |
마우스 오버 강조하는 방법(with not) (0) | 2025.01.06 |