Skip to content

Latest commit

ย 

History

History
515 lines (385 loc) ยท 20.1 KB

step23.md

File metadata and controls

515 lines (385 loc) ยท 20.1 KB

๋ฌธ์„œ ๋ชฉ๋ก์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

STEP 23

๐Ÿ’ก์งˆ์˜์‘๋‹ต์€ https://github.com/pul8219/TIL Issues ํƒญ์˜ ์•Œ๋งž์€ step ์ด์Šˆ์•ˆ์— ๋‚จ๊ฒจ์ฃผ์„ธ์š”. โžก๏ธ Issueํƒญ์œผ๋กœ ์ด๋™

๋ณด์ถฉ ํ•„์š”

๋ชฉ์ฐจ

๐Ÿ’ฌ

Moving the mouse: mouseover/out, mouseenter/leave

Moving the mouse: mouseover/out, mouseenter/leave ๋‚ด์šฉ์„ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

mouseover/mouseout ์ด๋ฒคํŠธ์™€ relatedTarget

image

์ถœ์ฒ˜: https://ko.javascript.info/mousemove-mouseover-mouseout-mouseenter-mouseleave

  • mouseover:๋งˆ์šฐ์Šค ์ปค์„œ๊ฐ€ ์š”์†Œ ๋ฐ–์— ์žˆ๋‹ค๊ฐ€ ์š”์†Œ ์•ˆ์œผ๋กœ ์›€์ง์ผ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ
  • mouseout: ๋งˆ์šฐ์Šค ์ปค์„œ๊ฐ€ ์š”์†Œ ์œ„์— ์žˆ๋‹ค๊ฐ€ ์š”์†Œ ๋ฐ–์œผ๋กœ ์›€์ง์ผ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ

๋‘ ์ด๋ฒคํŠธ ๋ชจ๋‘ ํ•ด๋‹น ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ ์šฉ๋œ ์š”์†Œ์˜ ์ž์‹ ์š”์†Œ์—๊ฒŒ๋„ ์ ์šฉ๋œ๋‹ค. (STEP 22์—์„œ ์‚ดํŽด๋ดค๋‹ค.)

relatedTarget

mouseover๊ณผ mouseout ์ด๋ฒคํŠธ๋Š” relatedTarget์ด๋ผ๋Š” ํŠน๋ณ„ํ•œ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง„๋‹ค. ์ด ํ”„๋กœํผํ‹ฐ๋Š” target ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณด์™„ํ•œ๋‹ค. (+ mouseenter, mouseleave ์ด๋ฒคํŠธ๋„ relatedTarget ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง„๋‹ค.) ๋งˆ์šฐ์Šค๊ฐ€ ์–ด๋–ค ์š”์†Œ๋ฅผ ๋– ๋‚  ๋•Œ ๊ทธ ์ค‘ ํ•˜๋‚˜๋Š” target์ด ๋˜๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” relatedTarget์ด ๋œ๋‹ค.

mouseover์˜ ๊ฒฝ์šฐ,

  • event.target -> ๋งˆ์šฐ์Šค๊ฐ€ ์˜จ ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ด
  • event.relatedTarget -> ๋งˆ์šฐ์Šค๊ฐ€ ๋– ๋‚˜์˜จ ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ด
  • ๋งˆ์šฐ์Šค์˜ ์ด๋™: relatedTarget -> target)

mouseout์˜ ๊ฒฝ์šฐ, (mouseover์˜ ๊ฒฝ์šฐ์™€ ๋ฐ˜๋Œ€)

  • event.target -> ๋งˆ์šฐ์Šค๊ฐ€ ๋– ๋‚œ ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ด
  • event.relatedTarget -> ์ƒˆ๋กœ ๋„์ฐฉํ•œ ์š”์†Œ
  • ๋งˆ์šฐ์Šค์˜ ์ด๋™: target -> relatedTarget)

event.target ์†์„ฑ์ด ์‹ค์ œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์š”์†Œ๋ฅผ ๋œปํ•˜๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜๋ฉด ์œ„์˜ ๋‚ด์šฉ์„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

์ฐธ๊ณ : MouseEvent.relatedTarget, MDN

โš ๏ธ relatedTarget ์€ null์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค๋ฅธ ์š”์†Œ๋กœ๋ถ€ํ„ฐ ์˜จ ๊ฒŒ ์•„๋‹ˆ๊ฑฐ๋‚˜, window ๋ฐ–์—์„œ ์˜จ ๊ฒฝ์šฐ relatedTarget์€ null๊ฐ’์„ ๊ฐ€์ง„๋‹ค.

relatedTarget์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ์—์„œ null์ผ ๊ฒฝ์šฐ์— ๋Œ€๋น„ํ•ด ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

Skipping elements

image

์ถœ์ฒ˜: https://ko.javascript.info/mousemove-mouseover-mouseout-mouseenter-mouseleave

mousemove ์ด๋ฒคํŠธ๋Š” ๋งˆ์šฐ์Šค๊ฐ€ ์ด๋™ํ•  ๋•Œ ํŠธ๋ฆฌ๊ฑฐ๋˜๋Š”๋ฐ, ๋งˆ์šฐ์Šค๊ฐ€ ์›€์ง์ด๋Š” ๋ชจ๋“  ์ˆœ๊ฐ„(ํ”ฝ์…€์„ ์›€์ง์ผ ๋•Œ๋งˆ๋‹ค) ๋ฐœ์ƒํ•˜์ง„ ์•Š๋Š”๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” Time to Time(์ƒ๊ฐํ•˜๋Š” ๊ฒƒ๋ณด๋‹จ ์ฒœ์ฒœํžˆ?), ๋งˆ์šฐ์Šค์˜ ์œ„์น˜๋ฅผ ์ฒดํฌํ•˜๊ณ  ๋ณ€ํ™”๋ฅผ ์•Œ๋ฆฌ๋ฉด(์•Œ์•„์ฑ„๋ฉด) ๊ทธ๋•Œ ์ด๋ฒคํŠธ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•œ๋‹ค. ์ด ๋ง์€, ๋งˆ์šฐ์Šค๋ฅผ ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ์›€์ง์ผ ๋•Œ ๋ช‡๊ฐœ์˜ DOM ์š”์†Œ๋Š” ๊ฑด๋„ˆ๋›ฐ์–ด์งˆ(skip) ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. (์žฅ์ : ๋ชจ๋“  ์š”์†Œ๋งˆ๋‹ค ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์„ฑ๋Šฅ์— ์ข‹์Œ)

  • ๋งˆ์šฐ์Šค๊ฐ€ window ๋ฐ–์—์„œ ๋น ๋ฅด๊ฒŒ ์š”์†Œ ์•ˆ์ชฝ์œผ๋กœ ์ด๋™ํ•˜๋ฉด relatedTarget์ด body๊ฐ€ ์•„๋‹ˆ๋ผ null์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

โ„น๏ธ mouseover ์ด๋ฒคํŠธ๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ๋˜๋ฉด, mouseout๋„ ๋ฐ˜๋“œ์‹œ ์ผ์–ด๋‚œ๋‹ค.

๋งˆ์šฐ์Šค ํฌ์ธํ„ฐ๊ฐ€ ์–ด๋–ค ์š”์†Œ ์œ„๋กœ ๋“ค์–ด๊ฐ€ mouseover์ด ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด ์ด์ „์— ์žˆ๋˜ ๋– ๋‚œ ์š”์†Œ์—” ๋ฐ˜๋“œ์‹œ mouseout์ด ๋ฐœ์ƒ

mouseover, mouseout ์™€ ์ž์‹ ์š”์†Œ ๊ด€๋ จ

์ฐธ๊ณ : https://eyabc.github.io/Doc/dev/core-javascript/browser_mouse_event.html#parent-%E2%86%92-child-mouseout

mouseover์™€ mouseout์€ ์ž์‹ ์š”์†Œ๋กœ ํ•ด๋‹น ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋„ ๋™์ž‘ํ•œ๋‹ค๊ณ  STEP 22์—์„œ ํ•™์Šตํ–ˆ๋‹ค. ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณด์ž.

mouseover, mouseout ์˜ˆ์ œ

id๊ฐ€ #out_div์ธ div์•ˆ์— id๊ฐ€ #in_div์ธ div๊ฐ€ ๋“ค์–ด์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž. mouseover๊ณผ mouseout ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ #out_div์—๋งŒ ์ ์šฉํ–ˆ๋‹ค. ํ•ด๋‹น ์ด๋ฒคํŠธ๊ฐ€ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ ์š”์†Œ์— ๋ฐœ์ƒํ•  ๋•Œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ ํƒ€์ž…๊ณผ event.target ์š”์†Œ์˜ id๊ฐ€ ํ•˜๋‹จ์— (๋ˆ„์ ๋˜๋ฉฐ) ์ถœ๋ ฅ๋œ๋‹ค.

<!-- html -->
<div id="out_div">
  <div id="in_div"></div>
</div>

<input id="clearbtn" type="button" value="clear" />
<div id="result"></div>
/* css */
#out_div {
  background: rgb(153, 113, 185);
  height: 100px;
  width: 100px;
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}

#in_div {
  background: rgb(255, 255, 141);
  height: 50px;
  width: 50px;
  display: inline-block;
}
// js
const div = document.getElementById('out_div');
const clearbtn = document.getElementById('clearbtn');
const result = document.getElementById('result');

div.addEventListener('mouseover', (event) => {
  result.innerHTML += `<div>${event.type} ${event.target.id}</div>`;
});

div.addEventListener('mouseout', (event) => {
  result.innerHTML += `<div>${event.type} ${event.target.id}</div>`;
});

clearbtn.addEventListener('click', (event) => {
  result.innerHTML = '';
  count = 0;
});

๊ฒฐ๊ณผ:

js1_gif

#out_div์—์„œ #in_div๋กœ ๋งˆ์šฐ์Šค๋ฅผ ์ด๋™ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.

mouseout out_div
mouseover in_div

#out_div์—๋งŒ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ฐ”์ธ๋”ฉํ–ˆ๋Š”๋ฐ ์™œ #in_div ์š”์†Œ์—์„œ๋„ mouseover ์— ๋Œ€ํ•œ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋™์ž‘ํ• ๊นŒ? ์ด๋Š” mouseover, mouseout ์ด๋ฒคํŠธ์˜ ๊ฒฝ์šฐ ๋ถ€๋ชจ์— ํ• ๋‹น๋œ ์ด๋ฒคํŠธํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ž์‹์—์„œ๋„ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ •ํ™•ํžˆ ๋งํ•˜๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ๋ฒ„๋ธ”๋ง๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. #out_div์—์„œ #in_div๋กœ ๋งˆ์šฐ์Šค๋ฅผ ์ด๋™ํ•  ๋•Œ #out_div์˜ ์ž์‹์š”์†Œ์ธ #in_div์—์„œ mouseover์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๋‹ค๋งŒ ํ•ด๋‹น ์ž์‹ ์š”์†Œ์—์„œ ๋ฐœ์ƒํ•œ mouseover ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์—†์„ ๋ฟ์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ mouseover, mouseout์˜ ๊ฒฝ์šฐ ์ด๋ฒคํŠธ๋Š” ๋ฒ„๋ธ”๋ง ๋˜๊ธฐ ๋•Œ๋ฌธ์—(๋ฒ„๋ธ”๋ง์€ STEP 13 ๋ฌธ์„œ ์ฐธ๊ณ ) #in_div์—์„œ ๋ฐœ์ƒํ•œ mouseover ์ด๋ฒคํŠธ ์ž์ฒด๊ฐ€ ๋ถ€๋ชจ ์š”์†Œ๋กœ ๋ฒ„๋ธ”๋ง๋˜์–ด #out_div์— ํ• ๋‹น๋œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋•Œ ์ด๋ฒคํŠธ๊ฐ€ ์‹ค์ œ๋กœ ๋ฐœ์ƒํ•œ ๊ณณ์€ #in_div์ด๊ธฐ ๋•Œ๋ฌธ์— event.target.id๋กœ๋Š” #in_div๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.

mouseenter, mouseleave

html, css ์ฝ”๋“œ๋Š” ์œ„์˜ mouseover, mouseout ์˜ˆ์ œ ์ฝ”๋“œ์™€ ๊ฐ™๋‹ค.

const div = document.getElementById('out_div');
const clearbtn = document.getElementById('clearbtn');
const result = document.getElementById('result');

div.addEventListener('mouseenter', (event) => {
  result.innerHTML += `<div>${event.type} ${event.target.id}</div>`;
});

div.addEventListener('mouseleave', (event) => {
  result.innerHTML += `<div>${event.type} ${event.target.id}</div>`;
});

clearbtn.addEventListener('click', (event) => {
  result.innerHTML = '';
  count = 0;
});

๊ฒฐ๊ณผ:

js2_gif

mouseover, mouseout์™€ ๋‹ฌ๋ฆฌ mouseenter, mouseleave๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฒ„๋ธ”๋ง๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋“ฑ๋ก๋œ #out_div์— ๋งˆ์šฐ์Šค๊ฐ€ ๋“ค์–ด๊ฐ”๋‹ค ๋‚˜์˜ฌ ๋•Œ๋งŒ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. #out_div์—์„œ ํ•˜์œ„์š”์†Œ์ธ #in_div๋กœ ๋“ค๋ฝ๋‚ ๋ฝํ•ด๋„ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ์ „ํ˜€ ๋ฐ˜์‘์ด ์—†๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

mouseover, mouseout ๋ฒ„๋ธ”๋ง ๊ด€๋ จ ์ด์Šˆ

mouseover, mouseout ์˜ˆ์ œ ์ฝ”๋“œ์™€ ๊ฐ™์ด ๋ถ€๋ชจ ์š”์†Œ ์•ˆ์— ์ž์‹ ์š”์†Œ๊ฐ€ ๊ฒน์ณ์ ธ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ, ๋ถ€๋ชจ ์š”์†Œ๋ฅผ ๋– ๋‚˜๋ฉด ํŠน์ • ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์‹คํ–‰๋˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? #out_div(๋ถ€๋ชจ) ์—์„œ #in_div(์ž์‹)์š”์†Œ๋กœ ๋งˆ์šฐ์Šค๊ฐ€ ์ด๋™ํ•  ๋•Œ๋Š” ๋ถ€๋ชจ ์š”์†Œ์˜ ๋” ์•ˆ์ชฝ์œผ๋กœ ๋“ค์–ด๊ฐ„ ๊ฒƒ์ด์ง€ ๋ถ€๋ชจ ์š”์†Œ๋ฅผ ์™„์ „ํžˆ ๋– ๋‚œ ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐ˜์˜ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜ ๋ฐฉ๋ฒ•๋“ค์„ ์ด์šฉํ•œ๋‹ค.

  1. relatedTarget๊ฐ’ ์ฒดํฌ

ํŽธ์˜์ƒ #out_div -> #parent, #input_div -> #child ๋กœ ๋ณ€๊ฒฝ

<div id="parent">
  <div id="child"></div>
</div>

<input id="clearbtn" type="button" value="clear" />
<div id="result"></div>
#parent {
  background: rgb(153, 113, 185);
  height: 100px;
  width: 100px;
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}

#child {
  background: rgb(255, 255, 141);
  height: 50px;
  width: 50px;
  display: inline-block;
}

#red_box {
  background: rgb(255, 0, 0);
  height: 100px;
  width: 100px;
  text-align: center;
}
const div = document.getElementById('parent');
const clearbtn = document.getElementById('clearbtn');
const result = document.getElementById('result');

// id๊ฐ€ parent์ธ div๋ฅผ ๋– ๋‚˜๋ฉด(parent ๋‚ด๋ถ€์˜ child๋กœ ๊ฐ€๋Š” ๊ฒƒ์€ ๋– ๋‚˜๋Š” ๊ฒƒ ์•„๋‹˜) ํ•˜๋‹จ์— ๋นจ๊ฐ„ ๋ฐ•์Šค๋ฅผ ๋„์šฐ๊ณ  ์‹ถ๋‹ค๊ณ  ํ•ด๋ณด์ž.

div.addEventListener('mouseout', (event) => {
  if (event.target.id == 'parent' && event.relatedTarget.id !== 'child') {
    // parent๋ฅผ ๋– ๋‚œ ๊ฒƒ์ด๋ฉด์„œ child๋กœ ๋“ค์–ด๊ฐ„ ๊ฒฝ์šฐ๋Š” ์ œ์™ธํ•ด์•ผํ•œ๋‹ค.
    result.innerHTML += `<div id='red_box'></div>`;
  }
});

clearbtn.addEventListener('click', (event) => {
  result.innerHTML = '';
  count = 0;
});

๊ฒฐ๊ณผ:

js3_gif

  1. mouseover, mouseout ๋Œ€์‹  mouseenter, mouseleave ์‚ฌ์šฉ

Event delegation

mouseenter, mouseleave ์ด๋ฒคํŠธ๋Š” ์œ ์šฉํ•˜์ง€๋งŒ ๋ฒ„๋ธ”๋ง๋˜์ง€ ์•Š์•„์„œ ์ด ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์‹œ ์ด๋ฒคํŠธ ์œ„์ž„์„ ํ™œ์šฉํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค.(์ด๋ฒคํŠธ ์œ„์ž„์€ STEP 19 ๋ฌธ์„œ ๋ฅผ ์ฐธ๊ณ ) ํ…Œ์ด๋ธ”์˜ ์…€๋“ค์— ๋Œ€ํ•ด ๋งˆ์šฐ์Šค enter/leave ๋™์ž‘์„ ํ•ธ๋“ค๋งํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ํ•ด๋ณด์ž. (์‹ฌ์ง€์–ด ๊ทธ ์…€๋“ค์€ ์ˆ˜๋ฐฑ๊ฐœ๊ฐ€ ๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž) ๋งŒ์•ฝ <table>์— ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ง€์ •๋˜์–ด์žˆ์„ ๋•Œ, mouseenter/leave ์ด๋ฒคํŠธ๋ฅผ ์“ธ ๊ฒฝ์šฐ ์ด๋Š” ๋ฒ„๋ธ”๋ง๋˜์ง€ ์•Š๋Š”๋‹ค. <td>์— ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚˜๋„ ํ•ธ๋“ค๋Ÿฌ๋Š” <table> ์ „์ฒด์— ๋Œ€ํ•œ enter/leave๋งŒ ์žก์•„๋‚ธ๋‹ค. mouseenter/leave ๋Œ€์‹  mouseover/out์„ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ณด์ž.

์˜ˆ์ œ ์ฝ”๋“œ

๋‹ค์Œ์€ ๋ฒ„๋ธ”๋ง์ด ๋˜๋Š” mouseover/out์„ ์ด์šฉํ•˜์—ฌ ์š”์†Œ์— ๋งˆ์šฐ์Šค๋ฅผ ๋†“์•˜์„ ๋•Œ ์š”์†Œ๊ฐ€ ํ•˜์ด๋ผ์ดํŠธ ๋˜๊ฒŒํ•œ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์ด๋‹ค.

<table id="table">
  <tr>
    <th colspan="3"><em>Mandal-Art</em> 2021 Plan</th>
  </tr>
  <tr>
    <td class="nw"><strong>๊ฑด๊ฐ•</strong> <br />๋ฌผ 2L ๋งˆ์‹œ๊ธฐ</td>
    <td class="n"><strong>์ž๊ธฐ๊ณ„๋ฐœ</strong> <br />ํ† ์ต ์ ์ˆ˜ ์ทจ๋“</td>
    <td class="ne"><strong>์ŠคํŠธ๋ ˆ์Šค ๊ด€๋ฆฌ</strong> <br />๋ช…์ƒ</td>
  </tr>
  <tr>
    <td class="w"><strong>๊ณต๋ถ€</strong> <br />์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ</td>
    <td class="c"><strong>Wol-dan</strong> <br />Better me!</td>
    <td class="e"><strong>์žฌํ…Œํฌ</strong> <br />์•ฑํ…Œํฌ ํ•˜๊ธฐ</td>
  </tr>
  <tr>
    <td class="sw"><strong>์Šต๊ด€</strong> <br />7์‹œ ๊ธฐ์ƒ</td>
    <td class="s"><strong>๋„คํŠธ์›Œํ‚น</strong> <br />์—ฐ๋ฝ</td>
    <td class="se"><strong>์ทจ๋ฏธ</strong> <br />๋…ธ๋ž˜๋“ฃ๊ธฐ</td>
  </tr>
</table>

<textarea id="text"></textarea>

<input type="button" onclick="text.value=''" value="Clear" />
/* index4.html, step23_4.js ๊ด€๋ จ */
#text {
  display: block;
  height: 100px;
  width: 456px;
}

#table th {
  text-align: center;
  font-weight: bold;
}

#table td {
  width: 150px;
  white-space: nowrap;
  text-align: center;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 12px;
  cursor: pointer;
}

#table .nw {
  background: rgb(255, 0, 0);
  color: #fff;
}

#table .n {
  background: rgb(255, 123, 0);
  color: #fff;
}

#table .ne {
  background: rgb(230, 208, 14);
  color: #fff;
}

#table .w {
  background: rgb(29, 231, 11);
  color: #fff;
}

#table .c {
  background: rgb(197, 197, 197);
  color: #fff;
}

#table .e {
  background: #09f;
  color: #fff;
}

#table .sw {
  background: rgb(17, 0, 255);
  color: #fff;
}

#table .s {
  background: rgb(153, 0, 255);
  color: #fff;
}

#table .se {
  background: rgb(255, 0, 170);
  color: #fff;
}

#table .highlight {
  background: rgb(58, 58, 58);
}
table.onmouseover = function (event) {
  let target = event.target;
  target.classList.toggle('highlight');
  // target.style.background = 'pink';

  text.value += `over -> ${target.tagName}\n`;
  text.scrollTop = text.scrollHeight;
  // console.log(text.scrollTop);
  // console.log(text.scrollHeight);
};

table.onmouseout = function (event) {
  let target = event.target;
  target.classList.toggle('highlight');
  // target.style.background = '';

  text.value += `out <- ${target.tagName}\n`;
  text.scrollTop = text.scrollHeight;
};

๊ฒฐ๊ณผ:

js_last_1

๊ทธ๋Ÿฐ๋ฐ ์ด๋ ‡๊ฒŒ ๋˜๋ฉด <td> ๋‚ด์˜ <strong>๊ฐ™์€ ์š”์†Œ๋‚˜ ์ œ๋ชฉ์˜ <em>๊ณผ ๊ฐ™์€ ์š”์†Œ๋„ ๋งˆ์šฐ์Šค๋ฅผ ๋Œ€๋ฉด ํ•˜์ด๋ผ์ดํŒ…๋œ๋‹ค. ์ด๋“ค์€ ๊ฑธ๋Ÿฌ๋‚ด๊ณ  ํ‘œ์˜ ์…€๋งŒ ํ•˜์ด๋ผ์ดํŒ… ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ์ด์™ธ์˜ ๊ฒฝ์šฐ๋“ค์„ ์ œ์™ธ์‹œ์ผœ์•ผ ํ•œ๋‹ค.

  1. mouseover ๋ฐœ์ƒ์‹œ, ์—ฌ์ „ํžˆ ํ˜„์žฌ <td>์•ˆ์— ๋งˆ์šฐ์Šค๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ฌด์‹œ
  2. mouseout ๋ฐœ์ƒ์‹œ, ํ˜„์žฌ <td>๋ฅผ ๋– ๋‚œ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด ๋ฌด์‹œ

๐Ÿ’ก ์ƒˆ๋กœ ์•Œ๊ฒŒ๋œ ์ 

  • js์ฝ”๋“œ์—์„œ table ์„ ์ž…๋ ฅํ•˜๋ฉด <table> ์š”์†Œ๊ฐ€, ํŠน์ • id๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ํ•ด๋‹น ์š”์†Œ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค. ์˜ˆ์ œ ์ฝ”๋“œ์˜ js ์ฝ”๋“œ์— table, text๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ์Œ

  • Element.closest: ์—˜๋ฆฌ๋จผํŠธ์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์กฐ์ƒ ๋ฐ˜ํ™˜(์—†๋‹ค๋ฉด null๊ฐ’ ๋ฐ˜ํ™˜) (์ž๊ธฐ์ž์‹ ๋„ ํฌํ•จ)

  • Node.contains: ์ธ์ž๊ฐ€ ์ฃผ์–ด์ง„ ๋…ธ๋“œ์˜ ์ž์†์ธ์ง€ ์•„๋‹Œ์ง€ Boolean๊ฐ’ ๋ฆฌํ„ด

  • Element.scrollTop ํ”„๋กœํผํ‹ฐ: ์š”์†Œ์˜ ๋‚ด์šฉ์ด ์ˆ˜์ง์ ์œผ๋กœ ์Šคํฌ๋กค๋œ ํ”ฝ์…€๊ฐ’์„ ์˜๋ฏธํ•˜๋ฉฐ ์ฝ์„ ์ˆ˜๋„, ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Œ.

    ์š”์†Œ๋ฅผ ์Šคํฌ๋กคํ•  ์ˆ˜ ์—†๋‹ค๋ฉด scrollTop์€ 0์ผ ๊ฒƒ.

    ์ฐธ๊ณ : Element.scrollTop, MDN

  • Element.scrollHeight ํ”„๋กœํผํ‹ฐ: read-only. overflow๋กœ ์ธํ•ด ํ™”๋ฉด์— ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ์ฝ˜ํ…์ธ ๋ฅผ ํฌํ•จํ•˜์—ฌ ์š”์†Œ์˜ ์ฝ˜ํ…์ธ  ๋†’์ด๋ฅผ ์ธก์ •ํ•œ ๊ฐ’์ž„. padding์€ ํฌํ•จํ•˜๋‚˜ border, margin, ์ˆ˜ํ‰ ์Šคํฌ๋กค๋ฐ”๋Š” ํฌํ•จํ•˜์ง€ ์•Š์Œ

    ์ฐธ๊ณ : Element.scrollHeight, MDN

โ“ ์ฝ”๋“œ์— scrollTop = scrollHeight ์‹์œผ๋กœ ์ž‘์„ฑ๋˜์–ด์žˆ๋Š”๋ฐ ์ด๊ฒŒ ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค textarea์— ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ์„ ์Šคํฌ๋กค์„ ๋‚ด๋ฆฌ๋ฉฐ ์ซ“์•„๊ฐ€๊ธฐ ์œ„ํ•ด์„œ ์ž‘์„ฑํ•œ ๊ฒƒ์ด๋ž€ ๊ฑด ์•Œ๊ฒ ๋‹ค. ๊ทผ๋ฐ ๊ฐ’์ด ์ดํ•ด๊ฐ€ ์•ˆ๋จ... scrollTop์— scrollHeight๋ฅผ ๋Œ€์ž…ํ•˜๋Š”๋ฐ, ๋‘˜์„ ์ถœ๋ ฅํ•ด๋ณด๋ฉด ๊ทธ ๊ฐ’์ด ๋‹ค๋ฆ„. scrollTop์€ ์Šคํฌ๋กค๋œ ์ •๋„(๊ทธ๋‹ˆ๊นŒ ์š”์†Œ์˜ top๋ถ€ํ„ฐ ์Šคํฌ๋กค๋˜์„œ ์•ˆ๋ณด์ด๋Š” ๋ถ€๋ถ„๋„ ํฌํ•จํ•˜๋ฉด์„œ ๋ณด์ด๊ธฐ ์‹œ์ž‘ํ•˜๋Š” ๋”ฑ ๊ทธ ๋ถ€๋ถ„๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ๊ฐ’)์ด๊ณ  scrollHeight์€ ์š”์†Œ์˜ ์ฝ˜ํ…์ธ ์˜ ๋†’์ด(์Šคํฌ๋กค๋กœ ์•ˆ๋ณด์ด๋Š” ๋ถ€๋ถ„ ๋ชจ๋‘ ํฌํ•จ)์ธ ๋“ฏ ํ•œ๋ฐ ํ—ท๊ฐˆ๋ฆฐ๋‹ค

image

์ˆ˜์ •๋œ ์ฝ”๋“œ

html, css ์ฝ”๋“œ๋Š” ์œ„์˜ ์˜ˆ์ œ ์ฝ”๋“œ์™€ ๊ฐ™๋‹ค.

โ— TODO ์ฝ”๋“œ ๋” ์ดํ•ด ํ•„์š”

let currentElem = null;

table.onmouseover = function (event) {
  // ์ƒˆ๋กœ์šด ์š”์†Œ์— ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—, ๋งˆ์šฐ์Šค๋Š” ํ•ญ์ƒ ์ด์ „ ๊ฒƒ์„ ๋– ๋‚œ๋‹ค.
  // (๋งŒ์•ฝ currentElem์ด ์ง€์ •๋๋‹ค๋ฉด, <td>๋ฅผ ๋– ๋‚œ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.)
  // mouseover์ด ๊ฐ™์€? <td>์•ˆ์— ์žˆ๋Š” ๊ฒƒ์ด๋ผ๋Š” ๊ฑฐ๊ณ  ์ด๋ฒคํŠธ๋ฅผ ๋ฌด์‹œ
  if (currentElem) return;

  // ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์—˜๋ฆฌ๋จผํŠธ์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์กฐ์ƒ์ธ td ๋ฐ˜ํ™˜(์—†๋‹ค๋ฉด null๊ฐ’ ๋ฐ˜ํ™˜)
  let target = event.target.closest('td');

  // <td> ์•ˆ์œผ๋กœ ์ด๋™ํ•œ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด ๋ฌด์‹œ(td๋‚˜ td ๋” ๋‚ด๋ถ€๋กœ ์ด๋™ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ฉด ๋ฌด์‹œํ•˜๋Š” ๊ฒƒ์ž„)
  if (!target) return;

  // <td>๋กœ ์ด๋™ํ–ˆ์œผ๋‚˜, ํ…Œ์ด๋ธ” ๋ฐ–์˜ <td>์ธ ๊ฒฝ์šฐ(์ค‘์ฒฉ ํ…Œ์ด๋ธ”์—์„œ ๊ฐ€๋Šฅํ•จ) ๋ฌด์‹œ // td๊ฐ€ table์˜ ์ž์†์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ -> ์ค‘์ฒฉํ…Œ์ด๋ธ”์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ
  if (!table.contains(target)) return;

  // ๋“œ๋””์–ด ์ƒˆ๋กœ์šด <td>๋กœ ๋“ค์–ด์™”๋‹ค๋Š”๊ฒŒ ์ฆ๋ช…๋์Œ!
  currentElem = target;
  onEnter(currentElem); // ํ•ด๋‹น td ํ•˜์ด๋ผ์ดํŒ…
};

table.onmouseout = function (event) {
  // (<td>๋ฐ–์— ์žˆ๋‹ค๋ฉด ๋ฌด์‹œ ex) tr->tr)
  if (!currentElem) return;

  // mouseout์€ ๋– ๋‚œ๊ฑฐ๋‹ˆ๊นŒ ํ–ฅํ•˜๋Š” ๊ณณ์€ relatedTarget ํ”„๋กœํผํ‹ฐ ์•ˆ์— ์žˆ์„ ๊ฒƒ // ๋งˆ์šฐ์Šค ๋– ๋‚˜์„œ ์–ด๋””๋กœ ํ–ฅํ•˜๋Š”๊ฐ€?
  let relatedTarget = event.relatedTarget;

  while (relatedTarget) {
    // ๋ถ€๋ชจ ์ฒดํฌ - ์—ฌ์ „ํžˆ currentElem์— ์žˆ๋Š” ๊ฑฐ๋ผ๋ฉด ๋ฌด์‹œํ•˜๊ธฐ ์œ„ํ•ด // td->๊ฐ™์€ td๋ฉด ๋ฌด์‹œํ•ด์•ผ๋˜๋‹ˆ๊นŒ
    if (relatedTarget == currentElem) return;

    relatedTarget = relatedTarget.parentNode;
  }

  // ํ˜„์žฌ <td>๋ฅผ ์™„์ „ํžˆ ๋– ๋‚˜์˜จ ๊ฒƒ์ด really ํ™•์ธ๋œ ๊ฒƒ!
  onLeave(currentElem);
  currentElem = null;
};

function onEnter(elem) {
  elem.style.background = 'gray';

  // textarea์— ์ถœ๋ ฅํ•˜๋Š” ๋ถ€๋ถ„
  text.value += `over -> ${elem.tagName}.${elem.className}\n`;
  //text.scrollTop = text.scrollHeight;
  text.scrollTop = 1e6;
}

function onLeave(elem) {
  elem.style.background = '';

  // textarea์— ์ถœ๋ ฅํ•˜๋Š” ๋ถ€๋ถ„
  text.value += `out <- ${elem.tagName}.${elem.className}\n`;
  text.scrollTop = 1e6;
}

๊ฒฐ๊ณผ:

js_last_2

Comment

References

ํŒ€์›๋“ค ๊ฒฐ๊ณผ๋ฌผ