본 포스팅은 여기에 올라온 게시글을 바탕으로 작성되었습니다.
파트와 카테고리 동일한 순서로 모든 내용을 소개하는 것이 아닌, 몰랐거나 새로운 내용 위주로 다시 정리하여 개인공부 목적으로 작성합니다.
중간중간 개인 판단 하에 필요하다고 생각될 시, 기존 내용에 추가로 보충되는 내용이 있을 수 있습니다.
폼(form
)을 조작하는데 사용되는 요소에는 특별한 프로퍼티와 이벤트가 많다. 아무래도 서버와의 통신에 자주 사용되는 기본적인 요소이다 보니 그에 관련된 처리가 지원되어야 하기 때문이다.
폼은 특수한 컬렉션인 document.forms
의 구성원이다. document.forms
는 이름과 순서가 있는 기명 컬렉션(named collection)
으로, 개발자는 이 이름이나 순서를 사용해 문서 내 폼에 접근할 수 있다.
document.forms.my // name='my'인 폼
document.forms[0] // 문서 내 첫 번째 폼
이렇게 원하는 폼을 가져온 다음에는, 또 다른 기명 컬렉션인 form.elements
를 사용해 폼 내부의 요소에 다시 접근할 수 있다.
<form name="my">
<input name="one" value="1">
<input name="two" value="2">
</form>
<script>
// <form name="my"> 인 요소
let form = document.forms.my;
// 해당 폼 내부에 <input name="one"> 인 요소
let elem = form.elements.one;
alert(elem.value);
</script>
HTML 마크업 구조에서 <form>
요소 내부에는 다른 기본 HTML 요소도 위치할 수는 있지만, 이들은 폼의 elements
로는 인식되지 않는다. form.elements
의 구성요소는 다음과 같은 요소가 있다. 자세한 요소는 다른 챕터에서 조금 더 상세히 살펴보자.
<input>
<textarea>
label
<form>
: 폼 내부에 또 다른 폼이 위치하는 경우이때 라디오 버튼과 같은 input
타입을 다루다보면 동일한 이름을 가진 여러 개의 요소를 다뤄야 하는 경우가 생길 수 있다. 이 경우 form.elements[name]
과 같이 이름으로 접근하는 경우에 그 대상은 컬렉션이 된다.
<form>
<input type="radio" name="age" value="10" />
<input type="radio" name="age" value="20" />
</form>
<script>
// 문서 내 첫 번째 <form>에 접근
let form = document.forms[0];
// 해당 폼에서 age란 이름을 갖고 있는 요소에 접근
let ageElems = form.elements.age;
// 해당 요소가 여러 개이므로 해당 값은 컬렉션이 됨
alert(ageElems[0]);
</script>
이처럼 폼과 그 요소를 탐색할 때 사용하는 프로퍼티는 폼을 포함한 요소의 name
속성에 해당하는 값으로 접근하는 방식인 것을 알 수 있다.
폼 내부에서는 추가적으로 <fieldset>
이라는 폼 요소를 하나로 묶을 수 있는 태그를 사용할 수 있는데, 해당 요소는 폼과 마찬가지로 자신의 내부에 있는 폼 조작 요소에 접근할 수 있도록 elements
프로퍼티를 동일하게 지원한다.
<body>
<form id='form'>
<fieldset name='userFields'>
<legend>info</legend>
<input name='login' type='text' />
</fieldset>
</form>
</body>
<script>
// <input name='login'>인 요소에 접근
alert(form.elements.login);
// name='userFields'인 <fieldset> 요소에 접근
let fieldset = form.elements.userFields;
alert(fieldset);
// 두 군데에서 접근하는 요소는 서로 동일함
alert(fieldset.elements.login == form.elements.login);
</script>
form.elemnets[name]
방식보다 더 짧게 접근하는 방법도 있다. elements
프로퍼티를 생략하고 form[name/index]
방식으로 접근하더라도 동일한 요소에 접근할 수 있다. 다만 해당 방식은 어떤 요소의 name
속성이 변경되고 난 후에도, 계속 변경되기 전의 이름으로 접근이 가능하다는 문제가 있다. 물론 새롭게 변경한 이름으로도 접근이 가능한데, 이전의 이름이 제거되지 않음으로 인해 예기치 않은 충돌이 발생할 수 있다.
<form id='form'>
<input name='login' />
</form>
<script>
// 두 방식은 서로 동일한 요소에 접근
alert(form.elements.login == form.login);
// 기존 <input> 요소의 name 속성값을 변경
form.login.name = 'username';
// form.elements엔 변경된 name 속성값이 반영
form.elements.login; // undefined
form.elements.username; // input
// 단축된 방식은 새로운 이름과 이전 이름 모두 인식
alert(form.login === form.username); // true
</script>
다만 폼 요소의 이름(name
)은 한 번 지정된 후 수정되는 경우는 흔치 않기 때문에 이러한 특징이 큰 문제로 이어지는 경우는 드물다.
폼 내부의 요소는 다시 element.form
으로 상위의 폼에 접근할 수 있다. 이는 폼이 내부 요소에 대해 참조가 가능하듯, 각 내부 요소 또한 역으로 폼을 참조할 수 있음을 보여준다. 이를 그림으로 나타내면 아래와 같다.
<form id='form'>
<input type='text' name='login' />
</form>
<script>
// form 요소 내부의 <input name='login'>
let login = form.login;
// <input name='login'> 요소 상위의 form
alert(login.form);
</script>
앞서 언급한 폼 요소 외에도 다양한 폼 요소가 있다. 폼 조작에 사용되는 요소들에 대해 간단하게 살펴보자.
1. input과 textarea
텍스트를 다룰 때 가장 많이 사용하는 폼 요소 중에 하나이다. input
의 경우엔 따로 타입을 지정하여 텍스트 외의 자료도 다룰 수 있지만, textarea
의 경우엔 그 이름에서 알 수 있듯이 텍스트 위주의 자료를 다룬다. 그 외에 차이점으로 textarea
는 입력하는 칸의 영역을 input
요소보다 유연하게 조절이 가능하다.
input
과 textarea
요소의 값은 input.value (string)
또는 input.checked (boolean)
을 사용해서 얻을 수 있다.
input.value = 'New value';
textarea.value = 'New text';
input.checked = true; // 체크박스 또는 라디오 버튼 등
textarea
요소 내부에 다른 HTML 요소가 있더라도 브라우저는 이를 렌더링한다. 그러나 기본적으로 textarea
는 사용자 입력값을 받는데 사용되는 요소임을 잊지말자. 만약 내부의 값이 HTML이라고 할 지라도 값을 얻을 때 textarea.innerHTML
을 사용해서는 안 된다. textarea.innerHTML
에는 페이지를 처음 열 당시의 HTML만 저장되어 최신 값을 구할 수 없기 때문이다.
2. select와 option
<select>
요소에는 세 가지 중요 프로퍼티가 있다.
select.options
: <option>
하위 요소를 담고 있는 컬렉션select.value
: 현재 선택된 <option>
값select.selectedIndex
: 현재 선택된 <option>
의 번호(인덱스)이 세가지 프로퍼티를 사용하면 아래와 같은 세 가지 방법으로 <select>
의 값 설정이 가능하다.
<option>
하위 요소를 찾아 option.selected
속성을 true
로 설정select.value
를 원하는 값으로 수정select.selectedIndex
를 원하는 option
번호/인덱스로 수정세 방법 중 첫 번째 방법이 가장 확실하지만, 두 번째나 세 번째 방법이 대체로 더 편리할 때가 많다.
<select id='select'>
<option value="apple">Apple</option>
<option value="pear">Pear</option>
<option value="banana">Banana</option>
</select>
<script>
// 세 가지 코드의 실행 결과는 모두 동일하다
select.options[2].selected = true;
select.value = 'banana';
select.seletedIndex = 2;
</script>
대부분의 다른 폼 조작 요소와는 달리 <select>
요소는 multiple
속성을 통해 여러 개의 option
을 선택할 수 있다. multiple
속성을 사용하는 경우는 드물지만, 쓰게 된다면 첫 번째 방법을 사용해 <option>
하위 요소에 있는 selected
프로퍼티를 추가/제거해야 정확한 처리가 가능하다. 이때 선택된 여러 개의 option
이 담긴 컬렉션은 다음 예시처럼 select.options
를 사용해 얻을 수 있다.
<select id="select" multiple>
<option value="blues" selected>Blues</option>
<option value="rock" selected>Rock</option>
<option value="classic">Classic</option>
</select>
<script>
// 선택된 값 전체를 출력
let selected = Array.from(select.options)
.filter(option => option.selected)
.map(option => option.value);
alert(selected); // blues, rock
</script>
3. Option 생성자
Option
생성자는 잘 사용되지 않으나 흥미로운 점이 있다. <option>
요소를 생성자를 통해 만드는 문법은 아래와 같다.
option = new Option(text, value, defaultSelected, selected);
각 매개변수는 다음과 같다.
text
: option
내부 텍스트value
: option
의 값defaultSelected
: true
이면 HTML 속성 selected
생성selected
: true
이면 해당 option
이 선택됨이때 defaultSelected
와 selected
의 차이는 다음과 같다. defaultSelected
의 경우엔 option.getAttribute('selected')
를 사용해서 얻을 수 있는 HTML 속성을 설정해준다. 반면 selected
는 option
의 선택 여부 자체를 결정한다. 보통 Option
생성자를 사용할 때엔 대개 두 매개변수를 모두 true/false
로 지정하여 함께 사용한다.
// 선택되지 않은 상태의 option 생성
// <option value='value'>Text</option>
let option = new Option('Text', 'value');
// 선택된 상태의 option 생성
// <option value='value' selected>Text</option>
let option = new Option('Text', 'value', true, true);
Option
생성자를 통해 만든 요소에는 다음과 같은 프로퍼티가 지원된다.
option.selected
: option
의 선택 여부option.index
: option
중 몇 번째인지를 나타내는 번호/인덱스option.text
: 사용자가 보게 될 텍스트사용자가 폼 요소를 클릭하거나 탭(Tab
) 키를 눌러 요소를 이동하면 해당 요소가 포커스(focus
)된다. HTML 속성 중에는 autofocus
라는 속성이 있는데, 해당 속성을 사용하면 페이지가 로드된 후 자동으로 포커싱이 일어난다. 이 외에도 자바스크립트를 이용하는 등 다양한 포커싱 방법이 있다.
요소를 포커싱한다는 것은 암묵적으로 '이 곳에 데이터를 입력할 준비가 되었다'는 것을 의미하기에, 포커싱이 이뤄지는 순간에 요구사항을 충족시키는 초기화 코드를 실행시킬 판단 근거가 되기도 한다.
반면 요소가 포커싱을 잃는 순간(blur
)는 때때로 포커싱보다 더 중요한 의미를 가질 수 있다. 사용자가 다른 곳을 클릭하거나 탭키를 눌러 다음 폼 필드로 이동하면 포커싱을 잃게 된다. 마찬가지로 이 외에도 다양한 방법으로 포커싱을 잃게 할 수 있다.
요소가 포커싱을 잃었다는 것은 '데이터 입력이 완료되었다'는 것을 의미하기 때문에, 포커싱이 해제되는 순간엔 데이터를 검증하거나, 입력된 데이터를 임시저장 또는 서버에 요청을 보내는 등의 코드를 실행할 수 있다.
focus
이벤트는 요소가 포커싱을 받을 때, blur
이벤트는 포커싱을 잃을 때 발생한다. 두 이벤트를 사용해서 입력 필드 값 검증을 수행할 수 있다.
blur
이벤트 핸들러에서는 필드에 이메일이 정상적으로 입력되었는지 확인 후 비정상 입력이 있다면 에러를 출력focus
이벤트 핸들러에선 에러 메시지를 숨김<style>
.invalid { border-color: red; }
#error { color: red }
</style>
이메일: <input type="email" id="input">
<div id="error"></div>
<script>
input.onblur = function() {
if (!input.value.includes('@')) {
input.classList.add('invalid');
error.innerHTML = '올바른 메일 주소 기입 필요';
}
};
input.onfocus = function() {
if (this.classList.contains('invalid')) {
this.classList.remove('invalid');
error.innerHTML = "";
}
};
</script>
모던 HTML에서는 그 외에도 required
, pattern
등의 속성을 지원하기 때문에 HTML 내부에서도 어느 정도 입력값 검증을 수행할 수 있다. 그럼에도 불구하고 추가적으로 자바스크립트를 사용해 검증을 하는 이유는 자바스크립트가 보다 더 유연한 처리가 가능하기 때문이다. 또한 자바스크립트를 통해 제대로 된 값이 입력되었다면, 자동으로 이를 서버에 보낼 수 있는 처리를 원활하게 할 수 있다.
elem.focus()
와 elem.blur()
메서드를 사용하면 요소에 포커스를 줄 수도 있고 제거할 수도 있다. 사이트 방문자가 유효하지 않은 값을 입력하면 사이트를 떠나지 못하도록 하는 코드를 작성해보자.
<style>
.error {
background: red;
}
</style>
이메일: <input type="email" id="input">
<input type="text" style="width:220px" placeholder="이메일 형식이 아닌 값을 입력하고 여기에 포커스를 주세요.">
<script>
input.onblur = function() {
// 이메일이 아닌 경우 => 에러 출력
if (!this.value.includes('@')) {
this.classList.add('error');
input.focus(); // 포커스 이벤트 발생
}
else {
this.classList.remove('error');
}
}
</script>
해당 코드는 파이어폭스의 고질적인 버그를 제외한다면 다른 브라우저에서 모두 잘 동작한다.
이메일이 아닌 값을 입력한 후에 <input>
요소를 벗어나려는 경우엔 onblur
메서드가 이를 캐치해 포커스를 다시 해당 요소로 되돌려 놓는다. 이때 onblur
는 요소가 포커스를 잃고 난 후에 발생하는 이벤트를 처리하기 때문에 해당 메서드 내부에서 event.preventDefault()
를 통해 포커스를 잃게 하는 것을 방지할 수 없다.
이 외에도 포커스를 잃는 경우를 자바스크립트적으로 조절할 수 있다.
alert
출력창이 뜨게 되면 자동적으로 blur
이벤트가 발생한다. 그러나 해당 출력창이 해제되면 자동으로 다시 focus
이벤트가 발생해 해당 요소로 돌아간다
만약 어떤 요소가 DOM
에서 제거된다면 자동으로 focus
가 해제된다. 이때 해당 요소가 다시 삽입되더라도 잃어버린 focus
는 복구되지 않는다.
이 외에도 다른 방법이 존재한다. 그러나 보통 자바스크립트 내부적으로 포커싱을 잃는 방식은 오동작의 우려가 많다. 사용자가 의도적으로 원하는 때에 포커스를 잃는 것이 보장되지 않기 때문이다. 따라서 가장 최선의 방식은 사용자가 직접 스스로 포커스를 잃는 순간에 관여하도록 하는 것이다.
대다수의 요소는 기본적으로 포커싱을 지원하지 않는다. 이는 브라우저 별로 약간의 차이가 있을 수는 있지만, 보통 <button>
, <input>
, <select>
, <a>
와 같이 사용자가 웹 페이지와 상호작용 할 수 있도록 도와주는 요소는 focus/blur
이벤트를 지원하는 경우가 많다.
반면 <div>
, <span>
, <table>
과 같이 무언가를 표시하는 용도로 사용되는 요소는 포커싱이 지원되지 않는다. 그럼에도 불구하고 해당 요소에도 포커싱을 지원하고자 한다면 HTML 속성 중 tabindex
를 사용하는 방법이 있다.
tabindex
속성이 있는 요소는 종류와 상관없이 포커스가 가능하다. 속성값은 숫자인데, 이 숫자는 탭 키를 눌러 요소 사이를 이동할 때 기준이 되는 순서를 의미한다. 예를 들어 두 개의 요소에 tabindex
를 지정하고 각각 1
번과 2
번의 값을 할당했다면, 첫 요소가 포커싱 되어있는 상태에서 탭을 누르면 2번 요소로 이동하게 된다.
tabindex
의 순서는 기본적으로 오름차순 순서로 적용된다. 즉 1
부터 시작해 점점 큰 숫자가 매겨진 순서로 이동하며, 그 이후엔 tabindex
가 없이도 포커싱이 작용하는 요소 순서로 이동한다. tabindex
가 없는 요소는 문서 내 순서에 따라 포커스가 이동한다.
이때 tabindex
에는 다음과 같은 미묘한 순서값이 존재한다.
tabindex
가 0
인 요소 : 이 요소는 tabindex
속성이 없는 것처럼 동작한다. 따라서 포커싱은 받을 수 있지만, tabindex
가 1보다 크거나 같은 요소보다는 나중에 포커스를 받는다. 즉 이 값은 주로 포커스는 가능하게 만들지만 포커스 순서는 문서 레벨에서 기본 순서를 그대로 유지하고 싶은 경우 사용한다.
tabindex
가 -1
인 요소 : 이는 오직 스크립트만 사용해서 포커스 하고자 할 때 사용한다. 탭 키를 통해서는 해당 요소에 포커싱을 적용할 수 없지만, 자바스크립트를 사용해 elem.focus()
메서드 등을 사용하면 제대로 포커싱이 가능하다.
<ul>
<li tabindex="1">일</li>
<li tabindex="0">영</li>
<li tabindex="2">이</li>
<li tabindex="-1">음수 일</li>
</ul>
<style>
li { cursor: pointer; }
:focus { outline: 1px dashed green; }
</style>
위 코드를 실행하면 포커스는 tabindex
가 1
, 2
, 0
인 순서로 이동한다. <li>
는 기본적으로 포커스 할 수 없는 요소이나 tabindex
를 사용해 실제 포커스를 적용하는 것을 볼 수 있다. tabindex
는 HTML 속성 외에도 DOM
객체의 프로퍼티로 지원되는데 elem.tabIndex
를 사용해서 동일한 효과를 볼 수 있다.
이벤트 버블링을 다루는 챕터에서 기본적으로 버블링이 발생하지 않는 몇몇 이벤트가 있음을 살펴보았다. 여기서 다루는 focus
와 blur
이벤트가 바로 버블링이 발생하지 않는 이벤트이다. 따라서 다음의 예시는 제대로 동작하지 않는다.
<!-- 폼 안에서 포커스가 된 경우 클래스를 추가함 -->
<form onfocus="this.className='focused'">
<input type="text" name="surname" value="성">
<input type="text" name="name" value="이름">
</form>
<style> .focused { outline: 1px solid red; } </style>
<input>
요소의 공동 조상 요소인 <form>
에서 포커싱 이벤트를 처리하고 있으나 버블링 되지 않는 관계로 이를 제대로 처리하지 못하고 있다. 이런 기본 동작을 피해 이벤트 위임 방식으로 포커싱을 처리하는 방법은 크게 두 가지가 있다.
캡처링(Capturing
) 이용
focus
와 blur
이벤트는 버블링은 되지 않지만 캡처링은 가능하다. 따라서 캡처링 단계에서 핸들러가 트리거 되도록 한다면 상위 요소에서 이벤트 위임 패턴으로 처리할 수 있다.
<form id="form">
<input type="text" name="surname" value="성">
<input type="text" name="name" value="이름">
</form>
<style> .focused { outline: 1px solid red; } </style>
<script>
form.addEventListener('focus', () => form.classList.add('focused'), true);
form.addEventListener('blur', () => form.classList.remove('focused'), true);
</script>
focusin
과 focusout
이벤트 사용
두 번째 방법으로는 focusin
과 focusout
이벤트를 사용하는 것이다. 두 이벤트는 focus
, blur
와 동일하지만 버블링이 된다는 특징을 가지고 있다. 때문에 이벤트 위임 패턴으로 포커싱을 처리할 수 있다.
다만 두 이벤트는 on<event>
방식으로 핸들러를 추가하는 방식이 아닌, elem.addEventListener
방식으로만 핸들러를 등록해야 정상적으로 처리되는 이벤트라는 점에 주의하자.
<form id="form">
<input type="text" name="surname" value="성">
<input type="text" name="name" value="이름">
</form>
<style> .focused { outline: 1px solid red; } </style>
<script>
form.addEventListener('focusin', () => form.classList.add('focused'));
form.addEventListener('focusout', () => form.classList.remove('focused'));
</script>
그 외 현재 포커스 된 요소를 파악하기 위해서는 document.activeElement
프로퍼티를 사용해 접근할 수 있다.
데이터가 변경될 때 실행되는 다양한 이벤트가 존재한다. 이번 챕터에서는 해당 이벤트들을 짚고 넘어가보자.
change
이벤트는 요소 변경이 끝나면 발생한다. 텍스트 입력 요소의 경우엔 요소 변경이 끝날 때가 아니라, 요소 입력 후 포커스를 잃을 때 해당 이벤트가 발생한다. 아래 예시에서는 입력 필드에 글자를 입력하는 동안엔 change
이벤트가 발생하지 않음을 볼 수 있다. 하지만 입력을 끝내고 다른 곳으로 이동하는 등의 동작을 통해 포커스를 잃게 되는 경우 그 순간 change
이벤트가 발생한다.
<input type='text' onchange='alert(this.value)' />
<input type='button' value='버튼' />
그러나 텍스트 입력 요소가 아닌 경우라면 선택 값이 변경된 직후에 해당 이벤트가 발생한다. 예를 들어 <select>
요소 또는 <input>
요소 타입이 checkbox/radio
인 경우가 이에 해당한다.
<select onchange="alert(this.value)">
<option value="">선택하세요.</option>
<option value="1">옵션 1</option>
<option value="2">옵션 2</option>
<option value="3">옵션 3</option>
</select>
React
에서는 텍스트 입력 필드에서onChange
이벤트를 사용해서 값을 입력/수정/제거 등의 과정을 처리한다. 폼 요소는 리액트에서 제어 컴포넌트(Controlled Component)
로 분류되는데 각 요소의value
를 리액트 컴포넌트의state
로 관리한다. 리액트는state
가 변경될 때마다 리-렌더링 되기 때문에onChange
이벤트를 통해 텍스트 입력값을 받더라도, 매번 철자가 입력되는 순간 렌더링이 재차 발생하고 그로 인해 순간순간 새로이 입력되는 값을 설정할 수 있다.
input
이벤트는 사용자가 값을 수정할 때마다 발생한다. 키보드 이벤트와 달리 input
이벤트는 어떤 방법으로든 값을 변경할 때 발생한다. 즉 마우스를 사용해서 글자를 붙여 넣는다거나, 음성인식 기능을 통해 글자를 입력하는 경우처럼 키보드 이외의 수단으로 값을 변경할 때도 input
이벤트가 발생한다.
<input type="text" id="input"> oninput: <span id="result"></span>
<script>
input.oninput = function() {
result.innerHTML = input.value;
};
</script>
때문에 만약 수정이 발생할 때마다 이벤트를 실행하고 싶다면 <input>
이벤트가 가정 적절하다. 다만 방향키와 같이 값을 변경시키지 않는 조작에는 반응하지 않는다.
그 무엇도
oninput
을 막을 수는 없다.input
이벤트는 값이 수정되자 마자 발생하기 때문이다. 따라서event.preventDefault()
를 사용해 기본 동작을 막더라도, 값이 수정되면 그 즉시input
이벤트가 새로 발생하기에 효과가 없다.
cut
, copy
, paste
이벤트는 각각 값을 잘라내기·복사·붙여넣기 할 때 발생한다. 이 이벤트는 ClipboradEvent
클래스의 하위 클래스로 분류되며, 복사 및 붙여넣기 한 데이터에 접근할 수 있다. 가령 어떤 블로그에서 내용을 복사해서 다른 곳에 붙여넣을때 자동으로 출처가 같이 기입되는 경우가 있다. 이러한 동작을 클립보드(Clipboard
) API 차원에서 다룰 수 있다.
input
이벤트와는 달리 세 이벤트는 event.preventDefault()
를 사용해 기본 동작을 막을 수 있다. 이 경우엔 아무것도 복사 및 붙여넣기 작업을 할 수 없는 상태가 된다. 예를 들어 아래의 코드는 잘라내기·복사·붙여넣기 동작을 시도하면 모든 동작이 중단되고 alert
창을 통해 중단된 이벤트 이름을 보여준다.
<input type="text" id="input">
<script>
input.oncut = input.oncopy = input.onpaste = function(event) {
alert(event.type + ' - ' + event.clipboardData.getData('text/plain'));
return false;
};
</script>
해당 이벤트는 단순히 텍스트 뿐만 아니라 모든 것을 복사/붙여넣기 할 수 있다. 예를 들어 OS 파일 매니저에서 파일을 복사해 붙여넣는 등의 작업도 가능하다.
클립보드에서 읽기·쓰기, 파일 등 다양한 데이터 타입에서 작동하는 메서드 목록 명세를 확인할 수 있다. 다만 클립보드는 전역 OS 레벨이기에 onclick
이벤트 핸들러처럼 대부분의 브라우저는 안전을 위해 특정 사용자 동작 범위에서만 클립보드의 읽기와 쓰기에 대한 접근을 허용한다.
예를 들어 IE에서는 window.clipboardData.getData()
와 같이 전역변수 window
레벨에서 바로 클립보드의 내용을 가져올 수 있지만 크롬 브라우저에서는 보안상의 이유로 이 같은 접근이 불가하다. 따라서 세 이벤트가 동작할 때 event
객체를 통해 접근하는 방식으로 처리해야 한다.
// 크롬 등 대부분 브라우저 (IE 제외)
function handlePaste (event) {
let clipboardData = event.clipboardData || window.clipboardData;
// ...
}
또한 파이어폭스를 제외한 모든 브라우저에서는 dispatchEvent
를 사용해 커스텀 클립보드 이벤트를 생성하는 것을 금지하고 있다.
submit
이벤트는 폼을 제출할 때 발생하는데, 주로 폼을 서버로 전송하기 전에 내용을 검증하거나 전송 취소할 때 사용할 수 있다.
한편 form.submit()
메서드는 자바스크립트만으로 폼을 전송하고자 할 때 사용할 수 있다. submit()
메서드는 주로 동적으로 폼을 생성하고 서버에 보내고자 할 때 사용한다.
폼을 전송하는 방법엔 크게 두 가지가 있다.
<input type='submit
> 또는 <input type='image'>
클릭input
필드에서 엔터(Enter
) 누르기두 방법 모두 폼의 submit
이벤트를 발생시키는 동작이다. 이벤트 핸들러에서는 데이터를 체크할 수 있는데, 데이터에 에러가 있다면 전송을 취소할 수 있다. 서버에 전송하는 동작은 submit
이벤트의 기본 동작이기 때문에 취소 시점에서 event.preventDefault()
를 호출하면 된다.
// return false로 인해 서버에 전송되지는 않는다
// 1번과 2번 방식 모두 submit 이벤트를 발생시킨다
<form onsubmit="alert('submit!');return false">
1. input 필드에 포커스를 준 다음 Enter 키 누르기: <input type="text" value="text"><br>
2. '제출' 버튼 누르기: <input type="submit" value="제출">
</form>
이와 관련해서 재미난 연계 동작이 하나 있다. input
필드에서 엔터 키를 눌러 폼을 전송하는 경우엔 <input type='submit'>
에 있는 click
이벤트가 같이 트리거 된다. 클릭을 하지 않았는데도 불구하고 click
이벤트가 동작하는 것이 조금 이상해보일 수 있지만, 기본 동작으로 정의되어 있다.
<form onsubmit="return false">
<input type="text" size="30" value="여기에 포커스를 준 다음에 Enter 키 누르기">
<input type="submit" value="제출" onclick="alert('클릭 이벤트가 트리거!')">
</form>
자바스크립트를 사용해서 직접 폼을 서버에 전송할 수 있다. form.submit()
메서드를 이용하는 것인데, 해당 메서드가 호출된 다음엔 기본적으로 submit
이벤트는 생성되지 않는다. 이는 개발자가 명시적으로 form.submit()
메서드를 호출했다면 스크립트에서 이미 필요한 모든 조치를 다 했다고 가정하기 때문이다. 따라서 submit()
메서드는 다음과 같이 폼을 직접 만들고 전송하길 원하는 경우 사용할 수 있다.
let form = document.createElement('form');
form.action = 'https://google.com/search';
form.method = 'GET';
form.innerHTML = '<input name="q" value="text" />';
// 폼을 제출하려면 반드시 폼이 존재해야 하므로 문서에 추가
document.body.append(form);
form.submit();