jQuery paging plugin update

jQuery paging plugin

내가 이걸 개발하고 방치한 지 3년이 지났다.
하지만 의외로 사람들이 페이징 플러그인을 찾다가 내 블로그에 들리기도 한다.
그리고 어느 블로그에서 내가 만든 페이징 플러그인을 소개하기도 했다.
그래도 돌아가긴 하나보다. 안정적으로.

그래서 오늘 오랜만에 재대로 손 좀 대봤다.
0.1.7 에서 0.2.0 으로 업데이트 했다.
기존 버전과 달라진 건 크게 없는데, append 속성이 쓸모 없어져서 제거하고, className 으로 컨테이너 관리 편의성을 높여준 업데이트이다.
나머진 기존 그대로 쓰면 되긴 하지만, 좀 더 편리하게
재호출할 때를 대비하여 일부 속성만 정의해도 기존 속성에서 정의 속성을 덮어씌워 페이징을 구성하겠끔 만들었다.
그렇다 보니 destroy 키워드가 생겼다.

아, 그리고 마지막으로 이건 문서에 안넣었는데, .paging(‘속성명’) 을 통해 속성값을 불러올 수 있다.
이는 아직 실험 단계지만, 조만간 편리하게 페이징이 처리되도록 할 생각이다.

프로젝트 페이지는 여기로 가면 되고,
bower 설치도 지원한다. bower install jquery.paging

언제까지나 유의사항은 “스타일링은 알아서 하라” 이다.

앞으로도 많은 성원 바란다.
감사하다.

독자: 이 미친새끼가 반말하고 지랄이야.

composite / 2016년 1월 26일 / Piss Development / 2 Comments

지연된 객체 (Deferred Object) 만들기 – 오리지날 JS편

오랜만에 골때리게 한번 팁을 날려보겠습니다.

jQuery 1.5 에서 획기적이지만 잘 안쓰는 게 있죠.

바로 지연된 객체(Deferred Object) 입니다.

이 객체의 위력을 정말 느껴본사람 빼고는 잘 안쓰죠.

이놈의 패턴이 어떻냐..

$.get(‘/serv/get.php’,null,function(){

     alert(‘뭘 받아온듯.’);

});

이 기존 패턴과

$.get(‘/serv/get.php’)

    .success(function(){

        alert(‘뭘 받아온듯.’);

    });

이 제이쿼리에서 제안한 패턴과 똑같은 효과를 줍니다.

뭐.. 느낌상 패턴은 당연히 틀리죠.

분명 Ajax는 비동기 스크립트입니다. 하지만 동기한 것 처럼 뭔가 착각을 불러일으키기도 하고.

바로 비동기 스크립트를 이렇게 눈에 보기 좋게 꾸며 놓는다는 장점이 있습니다.

node.js 개발하다보면 이벤트 중점적이다 보니 종종 비동기 쓸때 이런 패턴이 발생합니다.

var mongodb = require(‘mongodb’),

Db = mongodb.Db;

var db = new Db(‘test_db’, new Server(process.env[“MONGODB_HOST”], process.env[“MONGODB_PORT”], {}));

db.open(function(err, db) {

     db.collection(“test_collection”, function(err, collection) {

          collection.find({“cmd”:cmd}, {“sort”:”order”}, function(err, cursor) {

               cursor.each(function(err, item) {

                   if (item != null) {

                       // Do something

                   }

                   if (item != null) {} // 반복문 끝

                });

           db.close();

           });

  });

});

오우 쉣. 함수안에 함수안에.. 너무 지저분합니다.

하지만 제이쿼리가 제안한 지연된 객체 패턴으로 간다면 저걸?

db.open()

.collection(‘test_collection’)

.find({“cmd”:cmd}, {“sort”:”order”})

.fetch(function(err,cursor){

cursor.each(function(err, item) {

if (item != null) {

// Do something

}

if (item != null) {} // 반복문 끝

});

})

.close();

이런 식으로 비동기 스크립팅에 제이쿼리의 최강무기 메서드 체이닝을 구사할 수 있다는 겁니다.

물론 저런 패턴 제공하는 놈은 아직까지 없으니 그대로 따라하지 마시길. 그냥 예를 든거니까요.

그럼 어떤 원리로 하는건지 오늘 골때리게 설명해 드리도록 하겠습니다.

일단 먼저, 동적 클래스의 개념과 클로저 개념을 이해하고 있어야 합니다.

저는 그 이해를 하고 있는 분으로 간주하고 팁을 씁니다. 모르면 문학이님이 떡하니 강좌 올려놨으니 보시길.

..라고 무섭게 얘기했는데. 어렵지 않습니다. 먼저 동적 클래스를 만들 함수를 하나 짜주세요.

fuynction MyDefferd(){

this.fn={};

//초기화 할거 있음 하덩가.

}

그리고 지연된 객체에서 체이닝에 사용할 프로토타입 함수 하나 만들겠습니다.

MyDefferd.prototype.done=function(func){

this.fn.done=func;

};

뭐.. 준비 끝입니다.

그리고 이제 지연된 객체를 리턴할 함수를 하나 만들겠습니다.

그리고 이 함수는 비동기 작업을 할 겁니다. 간단하게 setTimeout 을 쓰겠습니다.

function Deffer(delay){

var deff=new MyDefferd();//아까 만든 지연객체를 동적으로 하나 불러와 주시고.

alert(‘작업 시작!’);

setTimeout(function(){

if(typeof(deff.fn.done)==’function’)

deff.fn.done();//done 함수를 끌어다 씁니다.

},delay*1000);//몇초 후에? 님이 쓴 초 후에.

return deff;//반드시 동적 지연 객체를 반환해줘야 합니다!

}

이것으로 지연객체 패턴을 사용할 수 있는 함수를 쓸 준비가 끝났습니다. 참 쉽죠?

어떻게 쓰냐? 간단합니다. 예를 들어 3초 후에 작업 끝 메시지가 나오도록 꾸며보겠습니다.

Deffer(3).done(function(){

alert(‘작업 끝!’);

});

그럼 처음에 작업 시작이란 경고창이 뜬 다음, 3초 후에 작업 끝이란 경고창이 뜰겁니다.

그렇게 나오면 성공!

어때요. 참 쉽죠?

동적 클래스는 함수 종료 후 클로저 때문에 메모리 다시 반납해 하는걸 개나 줘버라는는 성질 덕분에 deff 함수에서 언제든지 저렇게 동적 클래스 안에 있는 데이터를 잃지 않고 갖다 쓸 수 있습니다.

이걸 이용해서 지연된 객체를 통해 비동기 스크립트 패턴을 동기 스크립트 패턴같이 꾸밀 수가 있는 것이죠.

이런 지연 객체를 응용해서 Ajax는 물론, node.js 에서 할 수 있는 대부분의 비동기 작업에서 여러분의 눈을 정화시키는 패턴을 만들 수 있을 것입니다.

그리고 쿨하게 오늘의 골때리는 팁을 마치겠습니다.

링크 #1은 지연된 객체 패턴을 이용한 동적 스크립트 불러오는 함수입니다.

링크 #2는 이 강좌 예제입니다. 바로 실행되고 또 하고싶음 run 버튼 누르셈.

라이센스 : 해당 강좌에 사용한 기술은 죽써도 밥써도 상관없는 Public Domain. 강좌 자체는 크리에이티브 커먼즈 라이선스

composite / 2013년 9월 16일 / 미분류 / 0 Comments

적응형 가상 스크롤 Adaptive Virtual Scrolling

이번 undefine 이라는 소프트웨어 진흥원 산하 자바스크립트 팀 세미나에서 에서 마지막에 흥미로운 발표를 했다.

바로 네이버 오피스를 만들었다는 한 자스 개발자의 개발기, “자바스크립트, 어디까지 가봤니?” 라는 주제로 발표를 했다.

네이버 오피스를 만들면서 자바스크립트로 아주 그냥 철인 경기를 한 듯한 개발기를 한 그 개발자에게 먼저 경의를 표한다.

누군지 까먹어서 ㅈㅅ. 하지만 그는 정말 대단한 열정으로 자스계의 신의 경지에 올라왔다 해도 과언이 아니라고 말해주고 싶다.

어쨌든 이 발표가 끝나고 내 선배한테 헬프성 문자가 왔는데 그 중 하나가 바로 대용량 그리드 스크롤이 필요하게 생겼단다.

허.. 가는날이 장날인가..

나같은 경우 원리는 이해하나 구현해본 적이 없다. 그렇다고 직접 구현하기엔 여러가지 삽질이 필요했고

그거 생각할 시간은 너무나 부족했다.

그래서 내가 즐겨쓰던 그리드 플러그인인 SlickGrid 를 통해 답변을 찾기로 했다.

그리고 SlickGrid 는 나에게 정말 속 시원한 답변을 주었다.

왜 내가 SlickGrid 를 선택했냐면, 처음으로 대용량 그리드에 대한 스크롤링을 구현하여 몇십만 행의 데이터를 아무렇지도 않게 불러오는 스킬로 전 세계의 위엄을 떨친 그리드이기 때문이다. 게다가 라이센스가 MIT이다.

그리고 그 개발과정도 녹아 있었다. (제작자가 공개한 대용량 데이터 스크롤링 개발과정이 있다. 물론 영문이다.)

https://github.com/mleibman/SlickGrid/issues/22

그리고 그는 대용량 스크롤링을 구현하였고, 그것을 jsfiddle 에 공개햐였다.

http://jsfiddle.net/SDa2B/4/ (영어)

http://jsfiddle.net/wu7zq/ (내가 한글 번역)

이쯤에서 가상 스크롤이 뭔지 알아보자면,

사용자는 아무렇지도 않게 스크롤을 하는데, 스크롤을 하면서 개발자는 스크롤한 위치에 따라 컨텐츠 표시를 대응한다.

이게 가상 스크롤이라고 한다.

작년 웹 디자인 트랜드를 주름잡았던 패럴랙스 스크롤도 가상 스크롤에 해당되며,

SlickGrid 에서 스크롤한 위치만 보여주는 기술도 가상 스크롤이다.

이놈의 영감을 체험해보려면 바로 엑셀 프로그램이 있다.

엑셀은 수백만 행의 데이터를 똥컴에서도 랙없이 보여주는 기술을 가지고 있다.

만약 수백만 행이 렌더링 된 상태였다면 똥컴은 수백만 행에 대한 메모리를 이기지 못하고 뻗고도 남는다.

HTML도 마찬가지로, 눈에 보이는 모든 요소는 메모리에 담게 되며, 그래픽 처리를 하게 된다. 어느 프로그램이나 마찬가지.

그래서 HTML이던 자바던 닷넷이던 씨뿔뿔이던 다 이런 보이는 곳에 대한 대응은 안할래야 안할 수가 없다.

특히, 3D FPS 게임에서 보이는 곳만 렌더링 하는 것이 성능에 엄청난 차이를 보이기 때문에 민감할 수밖에 없다.

이런 류로 중요한 것이다.

제이쿼리 그리드 플러그인인 DataTable 도 한 업체의 도움을 받아 대량의 행도 아무렇지도 않게 보여줄 수 있는 가상 스크롤링을 구현하였다.

이 글을 통해 어떤 원리로 작동되는지 소개되어 있다. (조만간 번역해주겠다.)

https://datatables.net/blog/Introducing_Scroller_-_Virtual_Scrolling_for_DataTables

이리하여 웹 앱이라는 것이 어떤건지 아주 그냥 재대로 실감나게 한 한주가 되었다.

이제 와이프랑 놀아줘야겠다. 내 아내가 지금 삐친 상태라 오늘은 여기까지.

composite / 2013년 7월 27일 / 미분류 / 0 Comments

[javascript] 문자열을 자스 코드로 평가하는 짓거리.

여러분은 문자열을 자스 코드로 평가하는 짓거리를 하는 방법을 들라 하면 대표적으로 eval 들겁니다. 

제목이 이따구냐 들어와봤는데 eval 만 들어도 “아” 할거에요. 

근데.. 문자열을 자스 코드로 바꾸는 방법은.. 의외로 다양합니다. 

IE 전용 방법으로는 document.execScript 메서드가 있습니다. 

new Function(arg1,arg2,argN…,functionBody) 에서 functionBody 가 문자열이어도 함수가 만들어지며 자스 코드로 됩니다. 속살은 네이티브이니 eval 쓰는지 알 턱은 없지만.. 

setTimeout(functionBody,millisecond) 함수에 문자열을 코드로 집어넣는거. 옛날에 자스 해봤다면 쉽게 접해봤을 겁니다. 무서운건 지금도 setTimeout 에다가 문자열 집어넣는 선배님도 봤습니다. 우웩. 

네. eval 은 이미 많이 알려진 “악마”고 차기 ECMA 표준에서 뺄거란 얘기가 무성하게 흘러나왔죠. 

eval의 특징은 해당 스코프의 문자열을 자스 코드로 변환하여 실행하는 특징을 가지고 있습니다. 

스코프 뚫리면 보안은 뭐.. 말안해도 섬뜩할겁니다. 

그러다가 jQuery 에서 globalEval 메서드가 있는겁니다. 이녀석의 특징은 일단 문자열을 자스로 평가하는데 스코프를 무조건 최상위인 window로 잡는 특징이 있습니다. 일단 보안 측면에서는 다행이긴 한데 문자열을 자스 코드로 평가하다니.. 

그러다가 globalEval 메서드를 까봤습니다. 

globalEval: function( data ) { 

    if ( data && rnotwhite.test( data ) ) { 

        // We use execScript on Internet Explorer 

        // We use an anonymous function so that context is window 

        // rather than jQuery in Firefox 

        ( window.execScript || function( data ) { 

            window[ “eval” ].call( window, data ); 

        } )( data ); 

    } 

}, 

window 스코프를 가리키는 eval 악마를 보실 수 있습니다.으헝헝. 

이녀석이 왜 있냐구요? 이녀석도 쓰입니다. ajax 에서 스크립트 불러올때 그 스크립트 실행하기 위해 존재하는 메서드죠. 

그런데 말입니다. 

그런데.. 저는 의아해 했습니다. 좀 더 안전하게 스크립트를 실행하는 다른 방법이 있을까. 

그래서 여러가지 실험을 해봤습니다. 아까 new Function 에서 문자열 받아내는거 아시죠? 

그걸 이용해 봤습니다. 

new Function(“console.log(this);”)(); 

이렇게 해봐서 콘솔 봤더니 this 는 window를 가리킵니다. 

그리고 

function foo(){ 

    new Function(“console.log(this)”)(); 

new foo(); 

이렇게도 해봤더니 this는 여전히 window를 가리켰습니다. 

불여우, 크롬, IE 6,8,9,10 모두 같은 결과가 나왔습니다. 

그렇다면 jquery globalEval을 이렇게 꾸며도 무방할것 같다는 생각이 들었습니다. 

globalEval: function( data ) { 

    if ( data && rnotwhite.test( data ) ) { 

        return void new Function(data)(); 

    } 

}, 

게다가 new Function 은 인자도 받을 수 있습니다. (IE는 모르겠지만) 

스코프는 항상 최상위인 window 를 가리킵니다. 

처음엔 이렇게도 생각해봤습니다. 

globalEval: function( data ) { 

    if ( data && rnotwhite.test( data ) ) { 

        return void setTimeout(data,0); 

    } 

}, 

이렇게 하면 IE의 메모리 누수를 막을 수 있을 것 같은 느낌도 들어서죠. 

이번엔 더 거대하게 생각을 해봤습니다. 아예 스크립트 태그를 만들어 버리는 것도요. 

var script = document.createElement(‘script’); 

script.innerHTML=code+’\n’+//자스 코드 넣고 

    ‘var scripts=document.getElementsByTagName(‘script’);\n’+ 

    ‘document.documentElement.removeChild(scripts[scripts.length-1])’;//스크립트 실행후 DOM 삭제 

document.documentElement.appendChild(script); 

이것저것 생각해봤습니다. 

여러분은 타 스크립트를 가져올때 어떤 방법이 가장 좋을까요? 

물론 원격지 스크립트라면 script 태그가 진리겠죠. 

일단 생각해봅시다. 같은 도메인 안에서 한다고 가정하고. 원격 스크립트를 실행하는 방법이죠. 

동적으로 불러와야 한다는 전제 하에. 

  1. 스크립트 파일을 동적으로 만들어 script 태그 하나 만들어 포함시킨다. 

  2. 스크립트 파일을 Ajax로 불러오고 jQuery globalEval 등으로 실행시킨다. 

  3. 내가 테스트한 방법을 써본다 

<

p>

동적 스크립트 실행. 이대로 괜찮은가? 

참으로 어처구니 없는 일이 아닐 수 없습니다.

composite / 2013년 7월 20일 / 미분류 / 0 Comments

jQuery Paging Plugin

업데이트: 제이쿼리 페이징 플러그인 0.2.0 업데이트! 아래 설명 쌩까고 Github 으로 신속히 이동하라!

실무에 많이 쓰지만 은근히 빡센 페이징. 동적 페이징에 머리 짜매고 계신가? 여기 종결자가 있다.

jQuery Paging Plugin!

가볍다. 2KB밖에 안되며 gzip 압축 시 1KB도 안될 것이다.

빠르다. 페이징 외 쓰잘데기 없는 효과나 부가기능 따위는 없다.

쉽다. 한줄이면 페이징 초기화가 끝난다. 서버에서 불러와야 할 거는 현재 페이지와 총 페이지 수, 그뿐이다.

동적이던 정적이던 다 된다. 전통 방식 게시판이던 ajax 로 만든 게시판이던 입맛에 맞게 쓸 수 있다.

오픈소스다. 당신이 죽쓰던 밥쓰던 상관않는 MIT 라이센스다. 물론 더 좋은 방법 있으면 공유하는 것은 미덕!

사용법?

$(‘#paging’).paging({current:5,max:50}); //총 50 페이지 중 5 페이지로 시작하는 페이징을 불러올 것이다.

이거덕분에 프로젝트 잘되서 제작자한테 커피 한잔 쏘고 싶으면 ukjinplant at hotmail dot com 으로 연락해도 된다.

그럼 다운로드는?

소스(개발용) 다운로드 | 최적화(실무용) 다운로드 | 프로젝트 홈페이지

페이징 방식이 여러가진데 이 페이징 플러그인의 롤모델이 뭐인지 궁금하면 여기여기 를 클릭하여 확인해보라.

jQuery.Paging

jQuery를 위한 간단한 페이징.

사용법 : $('#paging').paging({max:50});

속성 :
item : 페이징 요소 태그명, 기본값 "a".
itemClass : 페이징 요소 중 페이지 수 CSS 클래스, 기본값 "paging-item".
itemCurrent : 현재 페이지를 나타내는 CSS 클래스이며 페이징 요소와 중첩됨, 기본값 "selected".
format : 페이지를 나타낼 내용, 기본값 "[%d]".
sideClass : 다음 또는 이전 버튼 CSS 클래스, 기본값 "paging-side".
next : 다음 버튼 내용. 기본값 "[{5}&gt;]" ("[>]")
prev : 이전 버튼 내용. 기본값 "[{4}&lt;]" ("[<]")
first : 첫 페이지 내용. 기본값 "[1&lt;&lt;]"
last : 마지막 페이지 내용. 기본값 "[&gt;&gt;{6}]"
length : 페이지 표시할 개수. 기본값 10.
max : 최대 표현할 페이지 수. 기본값 1.
current : 현재 페이지 정의. 기본값 1.
href : a 태그일 때 링크 주소를 정의. 기본값 "#%d"
append : true 설정 시, 기존 내용을 삭제하지 않고 페이징을 포함시킴. 기본값 false.
event : 기본 이벤트 활성화. 새로고침 없이 동적으로 페이징 초기화됨. ajax에 유용. 기본값 true.
>event=true 일 때 가능한 이벤트 정의.
onclick : 페이징 버튼 클릭 시 호출. false 반환 시 동적으로 페이지가 바뀌지 않음. 동적 페이징을 원하지만
                  href로 인한 링크 이동을 원하지 않을 경우 이벤트 메서드인 event.stopPropagation() 호출.
onprev : 이전 버튼 초기화 시 이벤트. 'this' 는 이전 버튼 요소를 가리킴.(plain DOM. not jQuery!)
onnext : 다음 버튼 초기화 시 이벤트. 'this' 는 다음 버튼 요소를 가리킴.(plain DOM. not jQuery!)
onitem : 각 페이지 버튼 초기화 시 이벤트. 'this' 는 각 페이지 버튼 요소를 가리킴.

치환자 (format,next,prev,href,first,last 속성 전용)
{0} = 클릭 시 페이지
{1} = 페이지 길이
{2} = 처음 페이지
{3} = 마지막 페이지
{4} = 이전 파트의 마지막 페이지
{5} = 다음 파트의 처음 페이지
{6} = 맨 마지막 페이지

판올림 내역
0.1.0 : 초기 버전
0.1.5 :
처음 페이지 및 마지막 페이지 추가. 내용에 치환자 적용 가능.
'append' 옵션 추가 : true 설정 시 기존 내용이 삭제되지 않고 포함됨.
{6} 치환자는 마지막 페이지(max 값과 동일) 를 가리킴
0.1.6 : first 또는 last 내용에 false 설정시 만들지 않도록 기능 추가.

composite / 2012년 10월 11일 / Piss Development / 11 Comments