페이스북 입력 필드는 지저분하다는걸 알았으니 제껴 두었고, 다음으로 눈에 띄는 UI는 다음과 같은 입력 필드입니다.
▲ Guided Text Input
비단 페이스북뿐만 아니라 네이트에서도 이러한 방식의 입력 필드를 구현하여 사용하고 있었습니다.
▲ 네이트 메일 주소 입력창
이런 입력 필드를 뭐라고 부르는지는 나도 잘 모르겠으니 우선 내 맘대로 'Guided Text Input'이라고 부르도록 하겠습니다. 의미상으로도 이게 맞을 듯 합니다.
이게 무엇인고 하면, 사용자가 입력한 값들을 위와같이 박스 형태로 묶어서 표현하고, 지울 때는 오른쪽에 있는 [×] 버튼을 눌러서 항목별로 삭제를 할 수 있도록 구현해 놓은 UI입니다.
사용자가 입력을 하고 구분자(여기서는 Comma)를 입력하거나 필드를 벗어나면, 앞서 입력한 내용이 자동으로 박스로 만들어져 삽입됩니다. 항목을 지우기 위해 [×] 버튼을 클릭해도 되지만, 커서가 깜박이는 위치에서 백스페이스를 누르면 상자가 하나씩 뭉테기로 삭제 됩니다.
이게 지난번에 살펴본 '페이스북 입력필드'처럼 깔려있는 레이어를 이용해 구현했더라면 저는 거들떠보지도 않았을 것입니다. 이는 그와는 조금 다른 방식으로 구현되어 있습니다.
눈에 보이는대로 저 테두리가 input 박스라고 판단한다면, 그건 오산입니다. 실제 input 박스는 입력중인 내용 크기만큼만 자리를 차지하고 있고, 테두리는 단지 input 박스를 흉내내서 만든 DIV 가짜 박스일 뿐입니다.
Guided Text Input
요즘 하고 있는 프로젝트에 이와 유사한 입력 필드가 필요해서 직접 구현해 보았습니다.
저는 참조를 했다면 반드시 그보다 더 좋은 기능을 추가해서 구현하려고 합니다.3일 정도 틈틈히 삽질을 해서 만든 결과물은 다음과 같습니다.
▲ Guided Text Input
페이스북이나 네이트에 구현된것보다 초라해 보이지만, 그건 단지 초기 프로토타입을 위해 최대한 심플하게 만들었기 때문입니다. 함께 동작하는 CSS 파일에서 스타일을 지정하면 얼마든지 예쁘게 꾸밀 수 있습니다.
추가한 기능 중에 가장 공을 들였던건 바로 자동완성 기능입니다. 마크업에 자동완성 항목을 구현해 놓으면, 스크립트가 알아서 자동으로 위처럼 자동완성 박스로 바꿔 줍니다. 입력 값에 따라서 필터링이 되는 것도 물론입니다.
▲ 항목 입력 직후 하이라이트 동작
항목을 입력하면 이렇게 하이라이트가 되면서 입력되어 들어갑니다.
이 하이라이트 색도 역시 옵션 설정으로 간단히 바꿀 수 있습니다. 하이라이트 기능은 새로운 항목이 입력된 시점 뿐만 아니라, 중복을 불허한 경우 이미 입력된 항목을 유저에게 강조해서 보여주는데도 활용됩니다.
▲ 입력한 항목들은 드래그&드롭으로 간단히 순서를 바꿀 수 있습니다.
▲ Guided Text Input 구현 방법
이런 기능을 구현하면서도 마크업은 최대한 간단하게 유지하기 위해 많은 주의를 기울였습니다. Container부터 시작하여 입력 필드까지 단 3층으로 모든 기능이 구현되도록 하였다. (개인적으로, HTML 마크업을 구현할 때 Depth는 최소한으로 유지하면서 필요한 기능을 구현하는게 좋다고 생각합니다. 쓸데없이 DIV박스를 남발해서 DOM탑을 쌓는건 정말 지양해야 할 코딩습관입니다.)
위 구현 방법 그림이 나타내듯이, 이 UI의 핵심 동작 방식은 매우 간단합니다.
입력 필드에 값을 입력하고 [Enter]를 누르거나 구분자(',')를 입력하면, 입력된 내용을 <SPAN> 상자로 만들어서 입력 필드 앞에 삽입하면 됩니다. 그러면 입력 필드가 삽입된 상자만큼 뒤로 밀리면서 새로운 값을 입력받을 준비를 합니다.
입력하는 항목이 많아서 Container를 넘어가게 되는 경우도 별로 문제가 되지 않습니다. 항목을 둘러싸고 있는 <SPAN> 상자와 입력 필드를 둘러싸고 있는 <SPAN> 상자가 같은 DOM Level에 있으므로 항목이 많아질 경우 자연스럽게 다음 줄로 워드랩 되어 내려가게 됩니다.
▲ 입력 항목이 많아지면 이렇게 자동으로 워드랩이 됩니다.
자연스러운 워드랩을 위해서는 입력 필드의 가로폭을 입력된 글자 폭과 최대한 같도록 유지하는 것이 중요한데, 이를 위해 지난번에 살펴본 페이스북 입력필드에서와 유사한 기법을 사용하였습니다.
Markup
정말 간결하게 구현된 마크업은 다음과 같습니다.
스크립트 파일을 로드하고, 필요한 위치에 다음 형식의 마크업을 작성하는 것만으로 간단하게 Guided Text Input UI를 사용할 수 있습니다. 별도의 초기화(init) 함수 호출 필요 없이 스크립트에서 자동으로 초기화 수행합니다.
<div tuwlab-lib="inputTextGuide" tuwlab-param-sortable="(true|false)" tuwlab-param-overlap="(true|false)" tuwlab-param-delim="(구분자)" tuwlab-data-default="(기본값)" tuwlab-param-highlight="(강조색)"> <span tuwlab-type="item" value="(값 1)"> <span tuwlab-type="text">(항목 1)</span> <span tuwlab-type="delete">×</span> </span> <span tuwlab-type="item" value="(값 2)"> <span tuwlab-type="text">(항목 2)</span> <span tuwlab-type="delete">×</span> </span> <span tuwlab-type="item" value="(값 3)"> <span tuwlab-type="text">(항목 3)</span> <span tuwlab-type="delete">×</span> </span> . . . <span tuwlab-type="item" value="(값 N)"> <span tuwlab-type="text">(항목 N)</span> <span tuwlab-type="delete">×</span> </span> <span tuwlab-type="input"> <input type="text" tuwlab-type="text" value="(초기값)" /> <div tuwlab-type="suggests" tuwlab-param-limit="(자동완성 갯수)" tuwlab-param-void="(show|hide)"> <div tuwlab-type="suggest" value="(값 1)">(추천항목 1)</div> <div tuwlab-type="suggest" value="(값 2)">(추천항목 2)</div> <div tuwlab-type="suggest" value="(값 3)">(추천항목 3)</div> . . . <div tuwlab-type="suggest" value="(값 N)">(추천항목 N)</div> </div> </span> <input type="hidden" name="(값 출력 필드명)" tuwlab-type="values" /> <input type="hidden" name="(항목 출력 필드명)" tuwlab-type="texts" /> </div>
Options
설정 옵션 내용은 다음과 같습니다.
[tuwlab-param-sortable]
이미 입력한 항목들의 재정렬 가능 여부를 지정합니다.
- true : 재정렬 허용 (입력한 항목을 드래그 & 드롭으로 재정렬 할 수 있습니다.)
- false : 재정렬 불허
[tuwlab-param-overlap]
중복된 항목을 허용할 지 여부를 지정합니다. (중복 판별 기준 : 항목 텍스트)
초기에 입력된 항목에 대하여는 필터링이 수행되지 않습니다.
- true : 중복 입력을 허용합니다.
- false : 중복 입력을 불허합니다.
※ 본 속성을 true로 지정하고 동시에 자동완성 기능을 사용하는 경우 반응 속도가 현저하게 저하될 수 있습니다. 가능하면 중복 항목 제거는 서버측에서 처리하는 것이 좋습니다.
[tuwlab-param-delim]
입력한 항목과 값들을 구분할 구분자를 입력합니다. 입력 필드에 구분자를 입력하면 이전까지 입력한 내용이 항목으로 자동 삽입됩니다.
- 기본값 : Comma(,)
[tuwlab-data-default]
자동완성 항목에 없는 새로운 텍스트를 삽입한 경우 해당 항목에 할당될 값(Value)을 지정합니다.
- 기본값 : ''
[tuwlab-param-highlight]
방금 입력할 항목을 눈에 띄도록 강조하는 데 사용할 색을 입력합니다. 중복 불허시 기존 입력한 항목을 강조하는 데도 공통으로 사용됩니다.
- 예 : rgb(255,0,0)
[tuwlab-param-limit]
한 번에 표시할 최대 자동완성 항목 갯수를 입력합니다. 이 속성을 지정하지 않으면 표시 가능한 자동완성 항목을 모두 출력합니다.
[tuwlab-param-void]
입력 필드가 비었을 경우 자동완성 창을 표시할 지 여부를 선택합니다.
- show : 입력 필드가 비었을 경우에도 자동완성 창을 표시합니다.
- hide : 입력 필드가 비었을 경우 자동완성 창을 표시하지 않습니다.
데이터 출력 방식
모든 입력 항목은 값(Value)과 텍스트(Text) 의 쌍으로 된 형식을 갖는데, 항목이 추가/삭제되거나 재정렬 될 때마다 [tuwlab-type='values'] 및 [tuwlab-type='texts'] 필드로 값이 자동으로 갱신됩니다.
이 두 필드에는 항목들의 Value 및 Text들을 옵션으로 지정한 구분자(delimiter)로 구분하여 순서대로 직렬화 한 값이 자동으로 입력됩니다. 즉, 서버측으로 값을 전송할 때는 이 두 필드의 값만 참조하면 되는 것입니다.
기타 고려 사항
예초 설계단계부터 다른 UI들과 네임스페이스 등이 충돌하는 불상사를 막고자, 모든 파라미터 및 속성에 'tuwlab-'이라는 접두어(prefix)를 사용하였습니다.
스크립트 내부적으로 DOM 요소를 찾을 때는 이 속성값만을 참조하며, 따라서 태그 이름은 적절하게 수정해도 무관합니다.
예를 들어, 자동완성 박스를 DIV 대신 UL로 작성해도 올바르게 동작합니다. 단, 직접 값을 저장하는 input field는 다른 태그로 바꿀 수 없습니다. [tuwlab-type='text']의 경우 input[type='text'] 대신 textarea를 활용할 수도 있으나, 권장되지 않습니다.