JavaScript 30

[ JavaScript30 | Wes Bos ]
Wes Bos가 만든 무료 자바스크립트 학습 코스 JavaScript 30(이하 JS30)을 시작했다. 코스는 미리 준비된 코드에 자바스크립트 코드를 더해가며 JS, CSS와 HTML를 배우는 30가지 문제로 구성되어 있다. 문제를 풀면서 새로 알게 된 지식을 더 잘 이해하기 위해서, 따로 작은 결과물을 만들기로 했다. 블로그 글 JavaScript 30 시리즈에는 각 문제에서 배우고 응용한 지식들을 정리한다.


문제를 응용한 결과물

SS002.png
[ Pick and Clear | 윤슬기 ]
JS 30 중 Day 3과 Day 5에서 배운 내용을 이용해 'Pick and Clear'를 만들었다. 판넬을 골라 클릭하고 바를 움직이면 흐릿한 이미지가 선명해진다. 위 링크에서 확인할 수 있다(데스크탑 전용).

Pick and Clear를 만들며 배운 것들

1. HTMLElement.focus()

[ HTMLElement.focus() | MDN ]
HTMLElement.focus() 메서드는 포커스할 수 있는 특정한 엘리먼트가 포커스되도록 설정한다.

2. EventTarget.removeEventListener()

[ EventTarget.removeEventListener() | MDN ]
EventTarget.removeEventListener() 메서드는 이전에EventTarget.addEventListener()EventTarget 에 등록했던 이벤트 리스너를 제거한다. 이 이벤트 리스너는 이벤트 종류와 이벤트 리스너 함수 자체의 조합으로 식별되어 제거되며, 등록시 제공했던 다양한 옵션과 일치하는 이벤트 리스너만 제거할 수 있다.

3. tabindex

[ tabindex | MDN ]
tabindex 전역 속성은 요소의 포커스 설정 여부와 만약 요소가 키보드 탐색 범위에 속해야 한다면 어느 지점에서 선택되어야 하는지 정수값을 사용해 지정할 수 있다.

가능한 값의 종류는 다음과 같다.

  • 음의 정수값은 요소가 포커스를 받을 수는 있지만 순차적인 키보드 탐색으로는 접근 불가능함을 나타낸다.
    예 ) tabindex="-1"
  • 0은 요소가 포커스를 받을 수 있으며 동시에 순차적인 키보드 탐색으로도 접근 가능함을 나타낸다. 그러나 요소의 상대적인 순서는 플랫폼이 정한 규약에 따라 달라질 수 있다.
    예 ) tabindex="0"
  • 양의 정수값은 요소가 포커스를 받을 수 있으며 동시에 순차적인 키보드 탐색으로도 접근 가능함을 나타낸다. 요소의 상대적인 순서는 속성값에 의해 결정된다. 탭 인덱스 값이 낮은 것부터 차례대로 순차 탐색한다. 만약 몇몇 요소에게 동일한 탭 인덱스 값을 부여한다면, 탐색 순서는 문서내의 요소의 상대적인 위치에 따라 결정된다.
    예 ) tabindex="2"

키보드로 순차 탐색을 할 시에, 0 값이나 부정확한 값 혹은 아무런 탭 인덱스 값도 가지고 있지 않은 요소는 탭 인덱스 값이 양의 정수인 요소 탐색이 완료된 후에 뒤따라 등장해야 한다.

JS30 Day3 : Update CSS Variables with JS

1. :root

[ :root | MDN ]
:root 는 CSS 가상 클래스로 문서의 최상위 엘리먼트를 나타낸다. HTML 문서에서는 <html> 엘리먼트이다. CSS 변수를 선언할 때 유용하다.

/* <html> 엘리먼트의 배경색이 하늘색으로 지정된다. */
:root {
  background: skyblue;
}

2. 사용자 정의 CSS 속성 사용하기 (변수)

[ 사용자 정의 CSS 속성 사용하기 (변수) | MDN ]
CSS 변수는 문서 전반적으로 재사용할 어떠한 특정 값을 포함하는, CSS 작성자가 정의한 엔티티이다. 이 변수는 사용자 정의 속성 표기법 (예 :--main-color: black;)을 사용하여 설정되며 var() 함수를 이용하여 엑세스할 수 있다. (예 : color: var(--main-color);).

CSS 변수의 값만 변경하면 그 값에 var() 로 접근하는 속성 모두가 한번에 변경되기 때문에, 어떤 같은 속성값을 여러 곳에서 사용하고 또 변경 가능성이 있다면 CSS 변수를 사용하면 편리하다.

/* 변수 base의 값을 변경하면, img의 background값과 .hl의 color가 모두 변경된다. */
:root {
  --base: red;
  --spacing: 0px;
  --blur: 0px;
}

img {
  background: var(--base);
  padding: var(--spacing);
  filter: blur(var(--blur));
}

.hl {
  color: var(--base);
}

3. filter

[[ filter | MDN ]]
(https://developer.mozilla.org/ko/docs/Web/CSS/filter)
filter CSS 속성은 흐림 효과나 색상 변형 등 그래픽 효과를 요소에 적용한다. 보통 필터는 이미지, 배경, 테두리 렌더링을 조정하는 데 쓰인다. MDN 페이지에서 다양한 속성들의 상세한 예시를 확인할 수 있다.

4. HTMLElement: change event

[ HTMLElement: change event | MDN ]
change 이벤트는 <input>, <select> 그리고 <textarea> 엘리먼트에서 사용자의 입력을 통해 value 가 바뀌었을 때 작동한다. input 이벤트는 엘리먼트의 value 가 바뀔 때마다 작동하지만, change 이벤트는 대부분 value 가 엔터키 입력이나 리스트에서 어떤 옵션을 선택하여 값이 commite 되었을 때 작동한다.

엘리먼트의 성질에 따라서 change 이벤트가 작동하는 순간이 다르다.

  • <input type="radio"> 혹은 <input type="checkbox"> 일 때, 클릭 혹은 키보드로 항목이 선택되어 value 가 바뀌었을 때.
  • <select> 의 드롭다운 메뉴에서 옵션을, <input type="date"> 에서 날짜를, <input type="file"> 에서 파일을 선택했을 때.
  • 엔터키나 클릭 등으로 값을 선택하지 않더라도, <textarea> 혹은 <input type="text"> 의 입력란에 사용자가 값을 입력하고 마우스 클릭 등으로 다른 부분으로 포커스를 이동시켜 해당 엘리먼트에서 포커스가 사라졌을 때.

5. CSSStyleDeclaration.setProperty()

[ CSSStyleDeclaration.setProperty() | MDN ]
CSSStyleDeclaration.setProperty() 는 CSS 속성에 새로운 value를 설정한다.

Document.documentElement 는 읽기 전용 속성으로 document 의 루트 엘리먼트를 반환한다 (가령, HTML 문서의 <html> 요소). 아래 코드는 <html>엘리먼트의 인라인 style 에 접근하여 background 속성 값을 red로 설정한다.

document.documentElement.style.setProperty('background', 'red');

Element.classList.toggle()

[ Element.classList | MDN ]
toggle( String [, force] ) 메서드는 엘리먼트의 클래스를 추가하기도 하고, 제거하기도 한다.

  • 하나의 인수만 있을 때: 클래스 값을 토글링한다. 즉, 클래스가 존재한다면 제거하고 false를 반환하며, 존재하지 않으면 클래스를 추가하고 true를 반환한다.
  • 두번째 인수가 있을 때: 두번째 인수가 true로 평가되면 지정한 클래스 값을 추가하고 false로 평가되면 제거한다.

아래 예시는 구역(panel)을 클릭하면 open 클래스가 해당 엘리먼트에 추가되어 flex-grow 값이 달라지면서 크기가 넓어지고, 다시 한 번 클릭하면 open클래스가 제거되어 창이 본래 크기로 돌아오는 코드다.

.panel {
  flex: 1;
}

.panel.open {
  flex: 5;
}
// 3. 만약 엘리먼트의 classList에 open이 존재한다면 지운다. 존재하지 않는다면 추가한다.
const toggleOpen = function() {
  this.classList.toggle('open');
}

// 1. panel이라는 class값을 가진 엘리먼트를 모두 선택한다.
const panels = document.querySelectorAll('.panel');
// 2. 각 엘리먼트에 클릭 시 toggleOpen 함수를 실행하는 이벤트를 단다.
panels.forEach(node => node.addEventListener('click', toggleOpen));