[HTML 요소] 라디오 버튼

라디오 버튼이 뭐임? 그 왜 회원가입 받거나 구글폼으로 설문조사 할 때 동그란 버튼 있죠? 중복으로 선택 안 되고 하나만 선택 되는. 지금은 그게 뭔데요? 지만 아래 예시를 보면 아마 바로 아 이거! 할 것이다.


봐봐요 이 버튼 어디서 봤잖아. 이게 라디오 버튼이다. 해당 예시에 JS는 적용 안돼서 그냥 선택만 할 수 있는 정도다.

<html>
  <div>
    <p>바깥은 위험하니 이 아이들을 데려가렴! <p>
    <input type="radio" name="pokemon" value="Bulbasaur" checked><span>이상해씨</span>
    <input type="radio" name="pokemon" value="Charmander"><span>파이리</span>
    <input type="radio" name="pokemon" value="Squirtle"><span>꼬부기</span>
  </div
</html>

라디오 버튼은 ‘같은 그룹 내에서 하나만 선택할 수 있는’ 버튼이다. 체크박스처럼 중복 선택이 안되는데 그걸 위해서 필요한 게 name이다. 위에 있는거 HTML코드 그대로 가져온거다. 잘 보면 이상해씨, 파이리, 꼬부기가 같은 name으로 묶여있는 것을 볼 수 있을 것이다. 저거 없으면? 우웅 중복선택? 얘네 같은 그룹임? 이 돼서 막 갖다 고를 수 있는 대참사가 터진다.

이렇게 선택지 그룹에 따라 name을 다르게 하면 여러 개의 선택지를 만들 수도 있다. 그럼 어떻게 만드는 지는 알았으니 여기에 CSS 적용을 어떻게 하는 지 알아보자. 여기서 CSS 적용이라는 건 span 말고 그 옆에 있는 라디오 버튼 말하는거다. 일단 새로 쓰기는 귀찮으니 2번 소스를 복사해서 써먹어봅시다.

소스에 주석이 붙은 부분도 있지만… 일단 라디오 버튼에 CSS를 주기 위해서는 그냥 줘서는 안된다. 안보이그덩. 그래서 appearance: none;을 줘서 기존 스타일을 숨긴 다음 적용했다. 아무튼 이런 식으로 라디오버튼의 그 동그란거에 대한 CSS를 적용할 수 있다. transition은 PPT의 애니메이션 효과 같은 건데, 이게 있으면 좀 자연스럽게 전환할 수 있다.

근데 만약 위 예제에서 스테이크 재료가 다 떨어져서 스테이크를 못 팔면 어떻게 하나요? 아, 그거 간단합니다.

<input type="radio" name="main" value="meat" disabled><span>스테이크</span>

요로코롬 disabled를 써 주면 사용자가 선택을 못 한다. 그렇다면 이제 자바스크립트도 쓰까봅시다.

갑자기 뭔가 개 복잡한 게 나왔다?? 가끔 스칼렛 바이올렛 중 뭘 사야 할 지 고민하는 사람들이 있어서 만들어 본 선택지다. 정작 오래 걸린 부분은 유효성 검사였던 게 함정. 아무튼… 이 코드가 어떻게 돌아가냐면 1) 질문에 따라 선택을 하면 2) 그 선택지의 value를 배열에 넣고 3) 스칼렛과 바이올렛 중 많은 걸 종합해서 추천해준다. 근데 이게 라디오버튼이 비면 안되잖아요? 그것때문에 처리하느라 오래 걸린거임…ㅠㅠ

아무튼… 예제를 보면 선택지가 두개씩인데 스칼렛/바이올렛 버전에 따라 분기되는 걸 나타낸거다. 라디오버튼에 따라 색이 다른 건 CSS 적용해서 그럼. 아무튼 그럼. 그러면 HTML, CSS는 각각 뼈와 살이고 자바스크립트로 작동하는건데… 일단 선택지 요소를 가져온 다음, 반복문과 if문의 조합을 통해 선택된 선택지의 value를 가져온다.

const colorList = document.getElementsByName("color");
const timeList = document.getElementsByName("time");
const pfList = document.getElementsByName("professor");
const vehicleList = document.getElementsByName("vehicle");
const pokemonList = document.getElementsByName("pokemon");

이렇게 라디오버튼에 지정해 둔 name으로 묶어서 가져오면, 이 중에서 선택된 거 하나의 결과값을 가져오게 된다. 값은 스칼렛 or 바이올렛이고 전부 선택하면 5개니까 스칼렛쪽이 더 많으면 스칼렛을, 바이올렛 버전이 더 많으면 바이올렛 버전을 추천해주는 거다. 근데 이거 어렵죠? 그래서 위에 있는 메뉴 예제를 다시 가져와봤습니다.

메뉴가 좀 늘어난 것 같지만 기분탓이다. 그럼 전체 자바스크립트 코드를 보자.

let dish = document.getElementsByName("main");
let drink = document.getElementsByName("desert");
let selection = document.querySelector("#selection");
let selectDish = "";
let selectDrink = "";

function order() {
  //메인메뉴
  dish.forEach((node) => {
    if (node.checked && node.value == "meat") {
      selectDish = "T본스테이크";
    } else if (node.checked && node.value == "bibim") {
      selectDish = "돌솥비빔밥";
    } else if (node.checked && node.value == "sushi") {
      selectDish = "모둠초밥+미니우동";
    } else if (node.checked && node.value == "ddeokggalbi") {
      selectDish = "떡갈비 정식";
    } else if (node.checked && node.value == "burger") {
      selectDish = "수제버거&감자튀김";
    }
  });

  //음료
  drink.forEach((node) => {
    if (node.checked && node.value == "plum") {
      selectDrink = "매실차";
    } else if (node.checked && node.value == "coffee") {
      selectDrink = "아포가토";
    } else if (node.checked && node.value == "greentea") {
      selectDrink = "녹차";
    } else if (node.checked && node.value == "earlgray") {
      selectDrink = "홍차(얼 그레이)";
    } else if (node.checked && node.value == "assam") {
      selectDrink = "홍차(아삼)";
    }
  });

  //주문을 포함한 출력
  let orderDish = document.createElement("p");
  orderDish.innerHTML =
    "주문하신 메뉴는 " + selectDish + "와 " + selectDrink + "입니다. ";
  selection.appendChild(orderDish);
}

메뉴를 하나씩 고르고 버튼을 누르면 식사와 음료가 출력되는 개 심플한 코드다. 유효성 검사… 귀찮아서 안함… 아무튼 위에 두 줄은 getElementsByName인데 이게 라디오버튼의 선택지를 가져오는 코드이다. 그리고 order 함수 에 보면 주석으로 음식과 음료로 나뉘어진 부분이 있는데, 이걸 왜 이렇게 했냐… HTML 태그를 보면 아시겠지만 value가 영어다. 스테이크는 meat, 수제버거+감자튀김은 burger 이런 식인데 이거 사용자한테 그대로 보여줄거임? 아니잖아요. 그니까 노드 밸류에 따라 라디오 버튼 옆에 있는 메뉴로 바꿔줘야 한다.

출력은 p태그를 만들어서 div에 갖다 붙이는 식으로 진행된다. 라디오버튼의 경우 동일 그룹 내에서는 하나만 선택할 수 있어서 가져오는 건 쉬운 편이다. 체크박스 과연…