사용자의 입력값에 따라 textarea 크기가 자동으로 조정되는 auto-resizing 기능이 있는 아래와 같은 textarea를 구현해보자.
1. 유저가 값을 입력했을 때 textarea 영역의 높이를 자동으로 증가/축소시킨다
2. 입력 가능한 라인 수(textarea 높이)는 제한한다
3. 입력시엔 textarea를 사용하고, 노출(읽기모드)시엔 textarea 대신 border가 없는 다른 tag를 사용한다
[구현에 필요한 사전지식]
1. HTML DOM element 와 jQuery Object
this 사용시 this가 jQuery Object 인지 DOM element 인지 명확히 구분해야 한다. (참고1, 참고2)
1. $(): jQuery Object 2. $var: jQuery 변수 3. $.each(function(){ 여기서 this는 DOM element }) 4. jQuery Object에서 DOM element를 꺼내는 방법 - $(el).get(0) - $(el)[0]
2. offsetHeight, clientHeight, scrollHeight 의 차이 (참고)
1. clientHeight : returns the inner height of an element in pixels, including padding but not the horizontal scrollbar height, border, or margin padding을 포함한 엘리먼트의 pixel 높이를 리턴, 가로스크롤바의 높이, border, margin 값은 포함하지 않음
2. offsetHeight : is a measurement which includes the element borders, the element vertical padding, the element horizontal scrollbar (if present, if rendered) and the element CSS height. 엘리먼트의 borders, 수직 padding 값, 가로 스크롤바(존재할경우)를 포함한 css 높이
3. scrollHeight : is a measurement of the height of an element's content including content not visible on the screen due to overflow 엘리먼트 내용물의 높이 (overflow로 보이지 않는 영역 포함)
3. textarea 의 문자열을 입력한 그대로(줄바꿈 형태 유지) 출력하는 방법
1) 출력시에도 textarea 를 그대로 사용
2) <pre> tag 혹은 줄바꿈/탭/자동줄바꿈 처리에 대한 white-space 속성 사용
유저가 값을 입력했을 때 textarea 영역의 높이를 자동으로 증가시키기 위한 이벤트리스너(eventlistener)로 textarea에 keyup 이벤트에 걸어준다. 해상도가 정해진 환경에서 개발하므로 높이는 230으로 고정했으나 보다 정확한 라인 수 제한을 위해선 1줄짜리 textarea 를 생성한 후 높이값을 가져와 (높이 값 * 높이 제한 라인 수)로 maxHeight 를 뽑아 사용하는게 정확할 듯 하다.(1줄짜리 textarea는 사용자에겐 보이지 않게 hidden 처리)
2).noticeTextarea.initSizing();
최초 화면 로드시 textarea 영역 높이 조절. 이벤트 리스너를 걸어주고 $textarea.keyup(); 으로 강제로 이벤트를 호출해도 무방.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var noticeTextarea = {
//초기 로딩시 notice값 기준으로 textarea height 재조정
initSizing : function(){
var orgEle = $("#noticeTextarea")[0];
var offsetOrgEle = orgEle.offsetHeight - orgEle.clientHeight;
- 자바스크립트에서 원시 타입을 제외한 모든 나머지 값들(함수 배열 정규표현식 등)은 객체. - 객체는 key 와 value 로 구성된 property 의 집합 - 프로퍼티 값이 함수인 경우 일반 함수와 구분하기 위해 메소드라 부름 (자바스크립트의 함수는 일급객체(참고)이므로 값으로 취급 가능) - 객체는 데이터를 의미하는 프로퍼티와 데이터를 참조하고 조작할 수 있는 동작(메소드)로 구성된 집합 - 프로퍼티 및 메소드를 모두 포함할 수 있어 하나의 단위로 구조화하기 유용 - 프로토타입을 상속받아 객체지향의 상속을 구현한다
[프로퍼티] - 프로퍼티 키를 중복 선언시 나중에 선언한 프로퍼티가 먼저 선언한 프로퍼티를 덮어씀 - 프로퍼티간 순서를 보장하지 않음
[메소드] - 프로퍼티 값이 함수인 경우 메소드라 부름 - 객체에 제한되어 있는 함수를 의미
[객체 생성 방법] 1. 객체 리터럴 - 중괄호 사용하여 생성 - 비어있는 객체 생성 가능 ex) var empty = {};
2. Object 생성자 함수 - new 연산자와 Object 생성자 함수를 호출하여 빈 객체 생성 가능 - 생성자 함수의 이름은 파스칼 케이스를 사용하는게 일반적 - 객체가 소유하고 있지 않은 프로퍼티 키에 값을 할당하면 해당 객체에 프로퍼티를 추가하고 값을 할당, 이미 존재하는 프로퍼티 키에 새로운 값을 할당하면 해당 값으로 변경 * Object 생성자 함수 사용보단 객체 리터럴 사용 (객체 리터럴 사용시 내부적으로 Object 생성자 함수를 사용하여 객체를 생성하므로)
3. 생성자 함수 프로퍼티 값만 다른 객체를 여러개 생성할 때 객체 리터럴 및 Object 생성자 함수를 사용한다면 아래와 같이 코드량이 많아지고 불편
- 생성자 함수명은 대문자로 시작하여 생성자임을 인식하도록 도움을 줌 - 프로퍼티 또는 메소드 앞에 기술한 this는 생성할 인스턴스(비어있는 새로운 객체)를 의미(new 연산자와 함께 함수를 호출시 this 바인딩이 다르게 동작) - this 에 바인딩되어있는 프로퍼티와 메소드는 외부에서 참조가 가능, 생성자 함수 내에서 선언된 일반 변수는 외부에서 참조 불가 : 생성자 함수 내부에서 자유롭게 접근이 가능하나 외부에서 접근은 불가 (아래 참고)
※ 자바의 생성자와 다르게 형식이 정해져 있지 않고, 기존 함수와 동일한 방법으로 선언하고 new 연산자를 붙여 호출하면 생성자 함수로 동작 ※ 생성자 함수가 아닌 일반 함수에 new 연산자를 붙일 경우 생성자 함수처럼 동작 가능하다는 것을 의미. 따라서 생성자 함수의 첫문자는 대문자로 명명하여 혼란 야기를 방지 ※ new 연산자와 함께 함수를 호출하면 this 바인딩이 다르게 동작
[ new 연산자와 함께 생성자 함수 호출시 동작 순서 ] 1. 빈 객체 생성 및 this 바인딩 - 생성자 함수의 코드가 실행되기 전 비어있는 객체가 생성된다 - 생성자 함수 내에서 사용하는 this 는 이 비어있는 객체를 가리킨다. - 생성된 빈 객체의 프로토타입 객체는 생성자 함수의 prototype 프로퍼티가 가리키는 객체. 2. this를 통한 프로퍼티 생성 - 생성된 빈 객체에 this를 사용하여 프로퍼티나 메소드 생성 가능 3. 생성된 객체 반환 - this 에 바인딩된 객체 자동 반환
[ 객체 프로퍼티 선언 및 접근 ] [ 프로퍼티 키 선언 ] - 프로퍼티 키에 표현식(- 연산자 등)이 존재하는 경우 대괄호로 묶어야 함 otherwise, ReferenceError 발생, 예약어는 당연히 사용하면 안된다 ex: var person = {first-name : 'gildong'} >> ReferenceError
[ 프로퍼티 키 접근 ] - 마짐표 . 표기법: 프로퍼티 키가 유효(표현식(- 연산자 등)이 있는 경우 무효), 예약어가 아닌 경우 마침표/대괄호 표기법 모두 사용 가능 - 대괄호 [] 표기법: 프로퍼티 키가 유효한 값이 아니거나, 예약어인 경우 대괄호 내에 들어가는 프로퍼티 이름은 반드시 문자열이어야 함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var person = {
'first-name': 'gildong',
'last-name': 'Hong',
gender: 'male',
1: 10
}
console.log(person.first-name); // NaN : undefined - undefined