e.target
- 실제 이벤트를 일으킨 요소
이벤트를 실제로 일으킨 요소와 이벤트리스너가 등록되어있는 요소는 같지 않을 수 있다.
예시
document.querySelector(".outer").addEventListener("click", e => {
alert("outer가 클릭되었습니다.");
// 이벤트 리스너가 직접 실행된 요소 객체. 여기서는 '.button'.
alert("target의 class:" + e.target.getAttribute("class"));
// 현재 이벤트 전파 과정 중에 이벤트 리스너가 등록되어있는 '그 요소 객체'가 들어있다. 여기서는 ''.outer'.
alert("currentTarget의 class:" + e.currentTarget.getAttribute("class"));
});
// document.querySelector('.inner').addEventListener('click', e => {
// alert('inner가 클릭되었습니다.');
// alert('target의 class:' + e.target.getAttribute('class'));
// alert('currentTarget의 class:' + e.currentTarget.getAttribute('class'));
// });
// document.querySelector('button').addEventListener('click', e => {
// alert('버튼이 클릭되었습니다.');
// alert('target의 class:' + e.target.getAttribute('class'));
// alert('currentTarget의 class:' + e.currentTarget.getAttribute('class'));
// });
// document.querySelector('.outer2').addEventListener('click', e => {
// alert('outer2가 클릭되었습니다.');
// });
todo-list 예제에서 변수명 사용하지 않고 e.target
, e.currentTarget
을 사용해서 쓰기(클래스를 사용하지 못해 변수명을 작성하지 못할 경우가 있다).
// 변수명을 사용하지 않고도 e.target과 e.currentTarget 사용해서 표현하기
e.target.parentElement.parentElement.removeChild(e.target.parentElement)
// todoListEl.removeChild(todoItemEl)
})
document.querySelectorAll
사용하면 node.list 객체가 반환된다!!! 이는 for each 라는 메소드를 자기 자신이 가지고 있어서 사용할 수 있다(배열이 아니더라도 사용이 가능)
// for each 다음 divEl이 변수명을 지어준 것
document.querySelectorAll("div").forEach(divEl => {
divEl.addEventListener("click", e => {
// target과 달리 currentTarget 사용 시에는 버블링 단계 때문에 이 후에 버블링 단계 효과를 받는 모든 div 요소들의 배경색도 바꿀 것이다!!!
// target은 이벤트리스너가 어디에 등록되어있던 상관없이 정말 e.target이 설정되어있는 요소만 가리키기 때문에 그 요소의 배경색만 바꾼다.
e.currentTarget.style.backgroundColor = "green";
});
});
버블링이 일어나는 이벤트도 있고, 일어나지 않는 이벤트도 있음 (submit, focus, blur, change 등 form 과 관련된 이벤트들은 특정 타입의 요소를 위해서 존재하기 때문에 캡쳐링이나 버블링이 일어나지 않는다)
e.target.value - 입력된 값을 반환한다.
input 태그에 change 이벤트 리스너는 사용하지 않는다. 그래서 input 이벤트 리스너를 사용하는 것. change 이벤트 리스너는 사용자가 직접 사용을 해야하는 경우에 많이 사용된다.
타입이 text 일 때에는 input 이벤트리스너를 사용하고, 그 외의 타입(checkbox) 일 때에는 change 이벤트리스너를 사용하면 된다.
// 이 경우에는 'div'요소도 입력가능하게 만든 것으로, 인풋 이벤트리스너를 사용한다.
document.querySelector(".contenteditable").addEventListener("in ut", e => {
console.log("contenteditable input");
});
- 폼 이벤트 예제(submit)
- 전송 버튼을 누르거나 혹은 엔터키를 치거나 해서 전송을 시킬 수 있다 - 이는 브라우저의 내장 기능.
- form 안에 button 을 지정해주고 사용하면(아무 attribute 없이) 전송이 정상적으로 동작하는데, 이는 브라우저의 내장 기능이다(이는 아무 속성값이 지정되지 않았을 시에 submit 이 기본값이기 때문).
요즘 form
이 제공하는 전송 기능을 잘 사용하지 않음에도(자바스크립트로 처리하기 때문), 이 form 이 제공하는 편리한 내부기능을 사용하기 위해 form 태그가 많이 사용된다.
e.target.elements
을 사용한 예 - 자바스크립트를 통한 아이디, 패스워드 검증 시에
document.querySelector("form").addEventListener("submit", e => {
// form이 타겟이고 그것의 자식 요소들을 가리킨다. 물론 form 요소를 대상으로 선언했기 때문에, 이 안의 요소들에게만 타겟이 지정된다.
const elements = e.target.elements;
// elements.id는 <input type="text" name="id" required>에 있는 id를 가리킨다.
if (!elements.id.value || !elements.password.value) {
e.preventDefault();
alert("아이디와 비밀번호를 모두 입력하셔야 합니다.");
}
});
form 태그를 사용할 때 이벤트리스너 등록 시에만 밑에와 같이 이벤트리스너의 첫 인수로 submit 사용할 수 있다(무엇이 전송될 때 발생하는 것)
todoFormEl.addEventListener("submit", e => {
// 전송되는 것 막기 위해
e.preventDefault();
addTodo(e.target.elements.todo.value); // input객체에 이름이 todo인 것들을 모두 지정
});
마우스 클릭, 더블 클릭
boxEl.addEventListener("dblclick", e => {
alert("더블 클릭");
});
마우스 무브
모든 요소 위에서 실행되는 마우스무브 - document는 문서 전체를 가리킨다.
document.addEventListener('mousemove', e => {
console.log('포인터 이동', e.clientX, e.clientY)
})
마우스 오버, 아웃
boxEl.addEventListener('mouseover', e => {
console.log('포인터 올라감')
})
boxEl.addEventListener('mouseout', e => {
console.log('포인터 벗어남')
})
스크립트로도 마우스 호버 기능을 할 수 있다. 하지만 이는 최대한 CSS에서 구현할 수 있다면 하는 곳이 옳다.
boxEl.addEventListener('mouseover', e => {
console.log('포인터 올라감')
e.target.style.backgroundColor ='red'
})
boxEl.addEventListener('mouseout', e => {
console.log('포인터 벗어남')
e.target.style.backgroundColor = 'green'
// boxEl.style.backgroundColor... 나는 이렇게 작성했었다. 하지만 `e.target`을 사용하면 안의 요소를 선택 가능...
})
그렇기 때문에 script에서는 단지 클래스의 추가를 해주거나 한 뒤에 CSS를 선택시키면 된다
boxEl.addEventListener('mouseover', e => {
console.log('포인터 올라감')
e.target.classList.add('hover')
})
boxEl.addEventListener('mouseout', e => {
console.log('포인터 벗어남')
e.target.classList.remove('hover')
})
작성 후,
.box.hover{
background-color:red;
}
이런 식으로 css에 설정해주면 된다.
과제!!! mouseenter, mouseleave가 mouseover와 mouseout의 차이가 무엇인지를 찾아보자.
-
mouseenter는 마우스가 만약에 이것이 설정된 요소 위에 올려졌을 때만 한 번 실행이되고, 다시 마우스 포인터가 그 요소를 나가기 전에는 상태의 변화가 없다. 즉 마우스엔터가 설정된 요소에 올라갔을 그 즉시에만 이벤트가 실행이 된다. mouseleave도 결국 그 설정된 요소 밖으로 마우스 포인터가 움직였을 시에 적용된다. 이 설정된 요소 안의 자식요소에게는 영향을 끼치지 않는다.
-
mouseover는 이벤트가 실행되는 조건이 마우스가 이것이 설정된 요소 위에 올라갔을 때와, 그 요소 내의 자식 요소들에게도 해당이 된다. mouseout도 설정이 된 해당 요소에서 벗어나거나 그 자식요소 외의 다른 영역을(해당요소를 가리키더라도) 가리킬 때 실행이 된다.
마우스 드래그 앤드 드롭 실습... 생각하지 못했다.. 후..
// 마우스가 클릭 되었는지 안되었는지 그 상태를 확인해주는 변수 선언
let dragging = false
boxEl.addEventListener('mousedown', e => {
dragging = true
})
boxEl.addEventListener('mouseup', e => {
dragging = false
})
// document - 문서 전체 - 에 대한 적용을 해주어야 원하는 효과가 나온다(마우스가 확 벗어나더라도).
document.addEventListener('mousemove', e => {
if (dragging) {
// 이 좌표는 박스의 왼쪽 끝(좌측 상단)을 뜻하기 때문에 마우스가 움직일 때 마우스 포인터가 계속 상자의 좌측상단으로 맞추어지게 된다.
boxEl.style.top = `${e.clientY}px`
boxEl.style.left = `${e.clientX}px`
}
})
el.getBoundingClientRect()를 사용하여 자연스럽게 드래그 시켜보자...
- const rect = boxEl.getBoundingClientRect()로 설정을 했다 치자.
- rect.left 가 x 좌표, rect.top 이 y 좌표, 마우스 포인터의 좌표는 e.clientX, e.clientY.
- e.clientX - rect.left를 뺀 값, e.clinetY - rect.top을 뺀 값을 구한 뒤 마우스를 땔 때 값을 대입하는 식으로 생각을 하자...
keypress... etc...
// 인풋은 인풋태그에만 사용이 가능하지만 - 키업, 키다운, 키프레스 등은 어디에나 사용 가능하다(언어 때문에 문제가 생길 수도 있다.)
document.querySelector('.todo-input').addEventListener('keypress', e => {
console.log('keypress')
console.log('key:', e.key)
})
키보드를 눌러도 스크롤이 되지않게 할 때:
document.querySelector('.todo-input').addEventListener('keydown', e => {
console.log('키가 눌렸을 때')
console.log('key:', e.key)
e.preventDefault()
})
클로저는 무엇!? : 바깥 스코프에 있는 변수를 가져다 사용하는 함수와, 변수가 저장되는 저장소를 클로저(closure)라고 부릅니다.
수업 후 질문 중
<!-- CSS 선택자 -->
/* 밑과 같이 작성된 CSS 선택자는 option클래스와 abc 클래스 모두가 적용된 html요소를 가리킨다. */
.option.abc {
border: 1px solid black;
width: 30px;
height: 30px;
}
/* 밑과 같이 작성된 CSS 선택자는 option을 클래스로 가지고 있는 html요소의 자식 요소 중에 .abc라는 클래스를 가지고 있는 요소를 가리킨다. */
.option .abc {
border: 1px solid black;
width: 30px;
height: 30px;
}