앞서 작성한 테이블 데이터 정렬(table sorting) 기능을
JQuery로 변환한 후,
다음과 같은 세부 기능을 구현한다.
1. 버튼을 누르면 오름차순으로 정렬
2. 정렬할 데이터가 없을 때 까지 반복
3. 정렬 버튼을 누르면 오름차순로 정렬하고, 다시 버튼을 누르면 내림차순으로 정렬, 다시 버튼을 누르면 오름차순로 반복.
4. 3번 예제 단순화
5. JQuery로 변환
6. 버튼 대신 각 테이블의 필드명(첫 row)을 클릭하면 해당 필드가 정렬
7. 필드별 정렬
8. 필드별 정렬 상태 표시
9. 라이브러리화자바 스크립트로 작성된 코드를
JQuery로 바꾸기 위해
7라인과 같이 JQuery를 사용할 수 있도록 한다.
페이지 로딩이 완료된 후 발생하는 이벤트는
window.onload인데 JQuery에서는
자바 스크립트에서는 createElement로 생성하는 것을
JQuery 기호에 생성한 HTML 태그만
파라미터로 지정하면 된다 [라인 22].
appendChild 대신에 append를 사용한다 [라인 23].
비슷한 구조로 되어 있는 것 같은데
테이블(table) 테그를 생성한 후
속성 지정을 메소드 체인(Method Chaining)으로 작성하였다.
자바 스크립트에서는
개별 속성을 하나씩 직접 지정하거나
setAttribute로 하나씩 호출해야 하는데
JQuery에서는 쭉이어서 작성할 수 있다 [라인 22].
For문 대신에 each문을 사용하여
2차원 배열 데이터의 반복 처리를 구현하였다 [라인 25, 28].
테이블의 각 셀에 값을 지정하는 것은
innerHTML 속성 대신에
JQuery의 html() 함수를 사용한다 [라인 30].
다음으로, 중요한 개념 중 하나인 선택자(selector)를 사용하였다.
앞서 작성한 예제는
행 정보에 접근하기 위해
getElementsByTagName 테이블을 찾고
table[0].rows로 테이블에 대한 행의 정보를 찾았다.
이번에는 선택자(selector)를 이용하여
$('table > tr')와 같이 간단하게 작성하였다 [라인 43].
getElementsByTagNam과 같이 테이블(table) 태그를 찾고
그 테이블 태그 바로 아래(>)에 있는 행(tr)을 반환한다.
여기서는 사용하지 않았지만
만약, tbody가 사용되었다면
이 코드에서는 반환 값이 없다.
$('table > tbody > tr')나 $('table tr')로 사용해야 한다.
자식(>) 기호는 바로 직계 자식을 의미하고
기호가 없으면 모든 자식(자식, 손주, 증손주 등)을 의미한다.
JQuery에서
HTML 태그는 별도의 표시 없이 사용했지만 (getElementsByTagName)
CSS 클래스 이름으로 찾을 때는 점(.)을 (getElementsByClassName)
ID로 찾을 때는 # 을(getElementById)
이름으로 찾을 때는 name=XXX (getElementsByName)
로 작성하면 된다.
보다 자세한 내용은 찾아보길 바라고
자바 스크립트에서는 document.querySelector로
선택자를 사용할 수 있다.
JQuery 선택자는 42 라인에 주석으로 작성 한 것과 같이
Find 메소드로도 구현할 수 있다.
이렇게 반환된 행 정보를
for문 대신 each문으로 작성하여
현재 행과 다음 행의 셀 값 비교를 처리 하였다.
현재 행은 파라미터(row)로 전달되고
다음 행은 현재 행의 다음 형제(nextSibling)로 찾는다 [라인 45, 46].
행에 대한 정보는
each문에서 row로 자바 스크립트 개체가 전달 되었기 때문에
49 라인에서 작성한 행 이동 처리를 (insertBefore)
자바 스크립트로 처리해도 되지만
사용법을 익히기 위해 JQuery로 작성하였다.
자바 스크립트 개체를 JQuery 기호 ($)로 지정하여
JQuery 개체로 변환하여 사용한다.
JQuery 개체로 사용한다는 것은
JQuery 명령어 등을 사용할 수 있다는 것을 의미한다.
앞서 정리한 선택자로 반환한 개체들도
JQuery로 지정한 것들은 JQuery 개체로 반환된다.
이상의 코드에서
자바 스크립트나 JQuery나 큰 차이는 없어 보이지만
JQuery가 좀더 단순하게 작성할 수 있는 장점이 있다.
특히, 메소드 체인은 JQuery의 장점 중 하나이다.
다만, 선택자는 강력하고 편리하지만
주의 해서 사용해야 한다.
여기에서는 테이블 태그가 하나이기 때문에 문제가 없지만
여러개가 있는데 $('table > tr')로 사용하면
문제가 생기게 된다.
이번에는
버튼 대신 각 테이블의 필드명(첫 row)을 클릭하면
해당 필드가 정렬되도록 작성한다.
첫 행을 클릭하면 해당 필드가 정렬되도록
첫 행을 생성할 때
각 필드에 클릭 이벤트를 연결한다(Binding).
해당 이벤트에서는 클릭된 필드가 반환되고
클릭된 필드의 위치(index)을 정렬할 때 참고 하면 된다.
$(function() {
var table = $('<table>').attr('border', 1).attr('width', 200);
$('#targetPn').append( table );
$.each(data, function(inx, row ) {
var tr = $('<tr>');
table.append(tr);
$.each(row, function(inx, col ) {
var td = $('<td>');
tr.append(td.html(col));
});
if (inx===0){
tr.find('td').click(function() {
sortTable(this.cellIndex)
});
}
});
}
var sortType = 'asc';
function sortTable(cellIndex){
sortType = (sortType === 'asc') ? 'desc':'asc';
var chkSort = true;
while (chkSort){
chkSort = false;
$('table > tr').each(function(inx, row) {
if (inx===0 || !row.nextSibling) return;
var fCell = row.cells[cellIndex].innerHTML.toLowerCase();
var sCell = row.nextSibling.cells[cellIndex].innerHTML.toLowerCase();
if ( (sortType === 'asc' && fCell > sCell) ||
(sortType === 'desc' && fCell < sCell) ) {
$( row.nextSibling ).insertBefore( $(row) );
chkSort = true;
}
});
}
}
반복문의 색인 변수(inx) 값이 0 이면 (inx===0)
데이터의 첫 번째라는 의미로
첫 번째 행이 된다.
첫 번째 행이 생성되고 나면
해당 행의 td를 모두 찾아서(find)
마우스 클릭(click) 이벤트를 지정하였다.
이 코드는 다음과 같이
별도의 함수로 작성하고 (mouseClick),
이 함수를 연결(on, bind)해도 된다.
코드가 간략해서 앞서의 코드처럼 많이 사용한다.
function mouseClick() {
sortTable(this.cellIndex)
};
~~ 생략 ~~
if (inx===0){
tr.find('td').on('click', mouseClick);
}
자바 스크립트 개체인 this를 이용하여
현재 이벤트를 발생시킨 개체를 알 수 있다.
이벤트를 발생시킨 개체는
event.target로도 알 수 있고
this로도 알 수 있다.
현재 클릭 이벤트는 td에 지정되어 있기 때문에
this는 클릭된 td를 의미한다.
정렬에서 필요한 것은 클릭된 td의 위치이기 때문에
td의 cellIndex 속성으로 행 내에서의 위치 값을 찾아서,
정렬에서 값을 비교하는 부분에
첫 번째 필드(cellIndex=0)로 고정되어 있는 것을
cellIndex 값으로 수정하면 된다.
실행 후 각 필드를 클릭해 보면
정렬이 되는 것을 알 수 있다.
다만, 이름(Name) 필드를 오름차순으로 정렬하고
Java 필드를 클릭하면,
Java 필드의 내용이 내림차순으로 정렬된다.
다시 이름 필드를 클릭하면
이름 필드의 내용이 오름차순으로 정렬된다.
이름 필드는 이전이 정렬 상태가 오름차순이었으니
이름 필드는 내림차순으로 정렬되어야 한다.
이것은 정렬 상태를 저장하는 변수를 하나만 사용했기 때문이다.
각 필드 별로 정렬 상태를 저장하고
필드를 한번 클릭하면 오름차순,
두 번째는 내림차순이 되게 구현한다.
이것을 구현하는 방법은 정렬 상태(sortType)를
필드 개수 만큼 사용하면 된다.
$.each(data, function(inx, row ) {
var tr = $('<tr>');
table.append(tr);
$.each(row, function(inx, col ) {
var td = $('<td>');
tr.append(td.html(col));
});
});
$(table).find('tr:nth-child(1)').find('td').click(function() {
sortTable(this);
});
});
function sortTable(cell){
var sortType = jQuery.data( cell, 'sortType');
sortType = (sortType === 'asc') ? 'desc':'asc';
jQuery.data( cell, 'sortType', sortType);
var cellIndex = cell.cellIndex;
var chkSort = true;
while (chkSort){
chkSort = false;
$('table > tr').each(function(inx, row) {
~~ 생략 ~~
});
}
}
정렬 상태(sortType)를 필드 개수만큼 사용하는 것은
필드 개수만큼 1차원 배열을 사용하는 것이 가장 쉽다.
이 방식은 자바 스크립트의 특징을 제대로 활용하지 못한 것으로
여기서는 필드(TD)의 속성(attribute)을 이용하였다.
HTML 태그의 속성을 이용하는 방법은 많지만
JQuery에서 제공되는 data 함수를 이용하였다.
jQuery.data()나 $.data() 로 사용하면 된다.
다만, sortTable() 함수를 호출할 때
파라미터로 클릭된 필드의 위치(cellIndex)를 지정했지만
정렬 상태를 저장하고 불러오는 기능을 구현하기 위해
클릭된 필드(this) 자체를 파라미터(cell)로 사용하였다.
앞서의 예에서는
첫 행(컬럼명)에 클릭 이벤트를 적용하기 위해
행을 생성할 때 0 번 째 행이면
모든 필드에 클릭 이벤트를 적용하였다.
이번에는 모든 행을 생성하고 난 뒤,
테이블(table) 태그의 첫 번째 행(tr:nth-child(1))을 찾아서
모든 필드에 클릭 이벤트를 적용하였다.
$(table).find('tr:nth-child(1)').find('td').click
가급적 가독성, 속도 등을 위해 IF문을 적게 사용하는 것이 좋고
자바 스크립트의 선택자를
잘 활용하는 것이 쉬운 프로그래밍을 할 수 있는 지름길이다.
각 필드별로 정렬이 되지만
현재 어떤 필드가 정렬되었고
오름차순(▲)으로 정렬될 것인지 내림차순(▼)으로 정렬된 것인지 알 수 없다.
필드별로 정렬 상태를 표시하도록 구현한다.
현재 진행할 정렬이
오름차순인지, 내림차순인지에 따라
클릭된 필드에 기호를 넣어주면 된다.
다만, 기호를 넣기만 하면
필드에 기호가 잔뜩 쌓이기 때문에지우는 기능이 필요하다.
function sortTable(cell){
$('table > tr:nth-child(1)').find('td').each(function(inx, td) {
td.innerHTML = td.innerHTML.replace(/[▼▲]/g, '') ;
});
var sortType = jQuery.data( cell, 'sortType');
if (sortType === 'asc') {
sortType = 'desc';
cell.innerHTML += '▼';
} else{
sortType = 'asc';
cell.innerHTML += '▲';
}
jQuery.data( cell, 'sortType', sortType);
var cellIndex = cell.cellIndex;
필드별로 정렬 상태를 표시하기 위해
필드를 클릭하면 정렬 상태에 따라
기호(▼▲)를 넣어 주면 된다.
다만, 클릭된 셀(td)이
JQuery 개체가 아닌
자바 스크립트 개체이기 때문에
innerHTML로 필드명 뒤에 기호를 붙여 주었다.
현재 어떤 필드가
오름차순이나 내림차순으로 정렬했는지 만 보여주기 위해
다른 필드에 남아있는 기호는 모두 지워준다. replace(/[▼▲]/g, '')
모든 필드에 있는 기호를 지우고
현재 클릭된 필드에 추가하는 방식으로 구현하고
모든 필드는
앞서 클릭 이벤트에서 처리한 선택자로 구현하였다.
정렬 상태에 따라 처리하는 내용이
한 행이 아니라서 ? 대신에 IF문으로 처리한다.
현재 코드를 다른 웹 페이지에 사용하기 위해서는
관련 코드를 복사해서
해당 페이지에서 붙여 넣기를 해야 한다.
이렇게 사용하는 것보다
라이브러리화해서 데이터만 바꾸어
호출해서 사용하는 것이 편리하다.
마지막으로 간단하게 라이브러리로 만들어 본다.
라이브러리화는 복잡하게 작성하면
자바 스크립트의 클래스를 알아야 한다.
여기서는 관련 코드를 외부 파일로 저장하고
함수를 호출하듯이 작성한다.
<script src='tableSort9.js'></script>
<script>
var data = [
['name', 'Java', 'Node', 'Perl'],
['Gu', 80, 70, 30],
['Kim', 90, 60, 80],
['Lee', 70, 70, 70],
['Brad', 50, 90, 90]
];
$(function() {
tableSoter9('targetPn', data);
});
</script>
function tableSoter9(target, data){
var table = $('<table>').css({'border': '1px solid', 'width': '300px'});
$('#'+target).append( table );
~~ 생략 ~~
데이터를 제외하고
기존에 작성된 자바 스크립트 코드만 tableSort9.js 파일로 작성한다.
load 이벤트 대신 tableSoter9()라는 함수로 바꾸어 준다.
기존의 HTML파일에 있는 load 이벤트에서
tableSoter9.js 파일에 있는
tableSoter9() 함수를 호출하는 방식으로 구현한다.
이 함수의 파라미터로
테이블 태그를 생성할 부모 태그(targetPn)와
테이블 태그 생성시 이용한 데이터(data)를 지정한다.
HTML파일에서 tableSoter9() 함수를 호출할 수 있도록
tableSort9.js 파일을 <script> 태그로 포함시켜 준다.
어떠한 파일에서도
tableSort9.js 파일을 <script> 태그로 포함시킨 후
tableSoter9() 함수만 호출해서 사용할 수 있다.
지금까지 테이블 태그의 데이터를 정렬(table sorting)을 구현하면서
자바 스크립트의 기본 문법과
Jquery 사용법을 익힐 수 있도록 정리하였다.
정리한 내용은 모두 기초적인 것으로
잘 익혀두면 유용하게 사용할 수 있을 것이다.
실제 라이브러리로 사용하기 위해서,
다음의 남아 있는 기능을 보완하면 좋다.
실력 향상을 위해 직접 구현해 보면 좋을 것 같아서
여기에 정리하지 않았다.
남아 있는 기능
1. 현재 작성된 코드는 사용하는 웹 페이지에 하나의 테이블 태그가 사용되었다는 전제로 작성되었다.
실제 사용에서는 수많은 테이블 테그가 사용되기 때문에 문제가 발생한다.
2. 사용된 성적은 60, 70과 같은 두자리 숫자를 사용했다.
6, 7 같은 한 자리 숫자나 600, 700 같은 세 자리 숫자 등을 이용하면 그림과 같이 정렬이 제대로 이루어 지지 않는다.
'JavaScript > 기타' 카테고리의 다른 글
3. 기초 - 테이블 컬럼 이동 (Drag and Drop Table Columns) (2) | 2017.06.29 |
---|---|
1. 기초 - 테이블 정렬 (table sorting) (1) | 2017.06.07 |
CD9 - Chart Design Tool for C3 (0) | 2017.03.26 |
2. gu-upload (4) | 2016.06.18 |
1.guupload - 예제 설치 (0) | 2016.06.18 |