본문 바로가기
Coding/JavaScript

테마 변경을 해 보자(feat. 라디오 버튼)

by Lv. 35 라이츄 2024. 2. 10.

일단 미리 말씀드리고 갈 부분이 있다. 자바스크립트 코드가 내가 원했던 로직이 아니기때문에 테마가 추가되거나 할 때 if문이 아주 덕지덕지 붙어서 뵈기 싫은데 이걸 대체 어떻게 깔끔하게 해야 할 지 모르겠다. 이건 나중에 방법 찾으면 보완할 예정.


HTML이나 CSS는 걍 깃헙 가서 보는 게 편한데, 기존에 체크박스나 라디오버튼과 달리 이번에는 라벨태그를 추가했다. 라벨태그는 <label>아무개</label> 이런 식으로 쓰는 태그인데, label for=""에 라디오버튼이나 체크박스의 아이디를 넣으면 꼭 그 라디오버튼이나 체크박스를 정확하게 클릭하지 않더라도(글자를 눌러도) 선택이 되게끔 해 주는 매우 편한 태그다. 특히 화면이 작은 모바일에서 말이지.

 

이게 기본 테마. 글자색은 아이보리 블랙이다.

 

.vandyke {
    color: #44362F;
    background-color: #FFE8D2;
}

.prussian {
    color: #003153;
    background-color: #DBF2FF;
}

.viridian {
    color: 	#40826D;
    background-color: #DDECE0;
}

.ultraviolet {
    color: 	#5f4b8b;
    background-color: #FDF7FF;
}

그리고 각 테마별로 배경색과 글자색을 추가했다. 순서대로 반다이크 브라운, 프러시안 블루, 비리디언, 울트라바이올렛. 이름에서 짐작하셨겠지만 순서대로 갈색/파란색/초록색/보라색 계통이다. 그리고 아이보리 블랙은 골탄이라고도 부르는데 반다이크 브라운과 프러시안 블루를 1:1로 섞으면 나오는 검정색. #000000과는 다르다. 실기 할 때는 섞어서 썼었는데 걍 물감 사서 쓰십쇼… 비율 안 맞으면 똥망이니까…

 

const selectTheme = document.getElementsByName('theme');
const page = document.querySelector('.page');
const title = document.querySelector('.title');
const contents = document.querySelectorAll('.contents');

selectTheme.forEach((item) => {
    item.addEventListener("change",(e)=>{
        const selectedTheme = e.currentTarget;
        if (selectedTheme.checked) {
            if (selectedTheme.value == 'default' && page.classList.contains('prussian')){
                page.classList.remove('prussian')
                title.classList.remove('prussian')
                contents.forEach((item) => {
                    item.classList.remove('prussian');
                })
            };
            if (selectedTheme.value == 'default' && page.classList.contains('vandyke')) {
                page.classList.remove('vandyke')
                title.classList.remove('vandyke')
                contents.forEach((item) => {
                    item.classList.remove('vandyke');
                })
            };
            if (selectedTheme.value == 'default' && page.classList.contains('viridian')) {
                page.classList.remove('viridian')
                title.classList.remove('viridian')
                contents.forEach((item) => {
                    item.classList.remove('viridian');
                })
            };
            if (selectedTheme.value == 'default' && page.classList.contains('ultraviolet')) {
                page.classList.remove('ultraviolet')
                title.classList.remove('ultraviolet')
                contents.forEach((item) => {
                    item.classList.remove('ultraviolet');
                })
            };
            if (selectedTheme.value == 'prussian') {
                page.classList.add('prussian');
                title.classList.add('prussian');
                contents.forEach((item) => {
                    item.classList.add('prussian');
                })
            };
            if (selectedTheme.value == 'vandyke') {
                page.classList.add('vandyke');
                title.classList.add('vandyke');
                contents.forEach((item) => {
                    item.classList.add('vandyke');
                })
            };
            if (selectedTheme.value == 'viridian') {
                page.classList.add('viridian');
                title.classList.add('viridian');
                contents.forEach((item) => {
                    item.classList.add('viridian');
                })
            };
            if (selectedTheme.value == 'ultraviolet') {
                page.classList.add('ultraviolet');
                title.classList.add('ultraviolet');
                contents.forEach((item) => {
                    item.classList.add('ultraviolet');
                })
            };
        };
    });
});

위에 네 줄은 가져오는거니까 패스. ForEach가 보면 if문 안쪽에 하나씩 있는 게 있고 그 바깥쪽에 있는 ForEach문이 또 있을 것이다. 위에 selectTheme가 테마 옵션을 선택할 라디오 버튼, 그러니까 위 사진에 있는 동글뱅이들인데… 그렇죠. 동글뱅이'들'이니까 단체로 가져왔을거고, 당연하지만 이거 배열이기 때문에 반복문을 돌려야 쓸 수 있다. 밖에 있는 ForEach문은 그래서 있는거다.

 

안쪽에 있는 ForEach문은 컨텐츠라는 클래스를 갖는 P태그가 여러개이기 때문에 거기에 전부 클래스를 붙여야 해서 존재하는 거다. 요소가 여러개라 배열로 가져오기 때문에 반복문 없으면 클래스가 가장 첫 번째 요소에만 붙거나 떨어지기 때문.

 

어쨌든 돌아는 가는 걸 알겠는데, 그럼 뭐가 문제일까?

if (selectedTheme.value == 'default' && page.classList.contains('prussian')) {
	page.classList.remove('prussian')
	title.classList.remove('prussian')
	contents.forEach((item) => {
		item.classList.remove('prussian');
	})
};
if (selectedTheme.value == 'default' && page.classList.contains('vandyke')) {
	page.classList.remove('vandyke')
	title.classList.remove('vandyke')
	contents.forEach((item) => {
		item.classList.remove('vandyke');
	})
};
if (selectedTheme.value == 'default' && page.classList.contains('viridian')) {
	page.classList.remove('viridian')
	title.classList.remove('viridian')
	contents.forEach((item) => {
		item.classList.remove('viridian');
	})
};
if (selectedTheme.value == 'default' && page.classList.contains('ultraviolet')) {
	page.classList.remove('ultraviolet')
	title.classList.remove('ultraviolet')
	contents.forEach((item) => {
		item.classList.remove('ultraviolet');
	})
};

여기 이 모든 if문이 default를 선택했을 때에 대한 if문이다. default(기본 테마)를 선택했고 클래스가 프러시안을 포함할 때(프러시안 블루 테마가 선택되어 있었을 때) 프러시안 클래스를제거한다. default를 선택했고 클래스가 반다이크를 포함할 때 반다이크 클래스를 제거한다. default를 선택했고 클래스가 비리디언을 포함할 때 비리디언 클래스를 제거한다. default를 선택했고 클래스가 울트라바이올렛을 포함할 때 울트라바이올렛을 제거한다.

 

이제 뭐가 문제인 지 보이는가? 이거 사실 default를 선택했고 뭐가 됐든 클래스가 '붙어 있으면' 그걸 떼기만 하면 장땡이다. 저렇게 if 줄줄이 달 필요가 없다 이거임. 그리고 다른 걸 선택했을 때도 마찬가지다. 반다이크 브라운에서 울트라 바이올렛으로 넘어가면 반다이크 클래스를 떼고 울트라 바이올렛 클래스를 붙여야 하는데 저것도 골치아파서 다른 선택지에는 붙어있으면 떼십쇼 이거를 추가를 못 했어요 지금...

 

그리고 내가 언젠가 개선하겠다고 한 부분이 이것과 관련 있는 것이다. 예를 들어서 내가 비리디언 테마를 선택했다, 그러면 default에서 바로 선택한거면 그냥 viridian 클래스를 붙이면 된다. 하지만 다른 테마에서 비리디언으로 변경하는 거면 어떤 테마에서 선택하건간에 해당하는 클래스를 '떼버리고' 비리디언 클래스를 붙이는 걸 하고 싶은거다.

 

테마는 순서대로 기본(아이보리 블랙)-반다이크 브라운-프러시안 블루-비리디언-울트라바이올렛. 왜 소스 코드에 프러시안 블루가 먼저 있었냐면 이게 잘 됐나 봐야 하는데 아이보리 블랙이랑 반다이크 브라운이랑 구별이 잘 안 돼서...

최근댓글

최근글

skin by © 2024 ttutta