이벤트 라이브러리
DOM이 준비된 다음에 페이지의 이미지와 스타일시트를 내려받는다.
DOMContentLoaded는 페이지의 이미지와 스타일시트를 내려받기 전에 실행된다.
사용자가 페이지와 상호작용을 하기 전에 항상 DOMContentLoaded가 먼저 호출된다.
모든 브라우저가 DOMContentLoaded 이벤트를 지원하지 않는다. jQuery는 ready() 함수로 기능을 추상화
컨텍스트 변경
브라우저에서 제공하는 addEventListener()를 이용하면 기존의 지역 컨텍스트가 대상 HTML 엘리먼트
컨텍스트로 바뀐다.
jQuery의 proxy() 함수 패턴을 사용한다.
예)$("signinForm").submit($.proxy(function(){ /* ... */ }, this));
이벤트 위임
이벤트 버블링 방식은 일반적으로 자식의 이벤트를 검사할 수 있도록 부모에 리스너를 추가한다.
jQuery의 delegate() 함수에 자식 셀렉터, 이벤트 타입, 핸들러를 넘겨줘서 이벤트를 위임할 수 있다.
예)
// 모든 <li> 엘리먼트에 리스너를 추가하는 방식
$("ul li").click(function(){ /* ... */ });
// 한 개의 이벤트 리스너만 추가한다.
$("ul").delegate("li", "click", /* ... */);
이벤트 위임을 사용하면 동적으로 자식을 엘리먼트에 추가해도 추가한 자식의 이벤트가 이미 있다.
커스텀 이벤트
jQuery에서는 trigger() 함수로 커스텀 이벤트를 발생시킬 수 있다.
예)
// 커스텀 이벤트 바인드
$(".class"). bind on("refresh.widget", function(){});
// 커스텀 이벤트 발생
$(".class").trigger("refresh.widget");
trigger() 함수에 인자를 추가해서 이벤트 핸들러로 데이터를 전달할 수 있다.
$(".class"). bind on("frob.widget", function(event, data){
console.log(data);
});
$(".class").trigger("frob.widget", 5);
커스텀 이벤트와 jQuery 플러그인
사용자가 리스트 항목을 클릭하면 해당 항목에 활성 클래스를 추가하고 다른 항목의 활성 클래스 제거
<ul id="tabs">
<li data-tab="users">Users</li>
<li data-tab="groups">Groups</li>
</ul>
<div id="tabContent">
<div data-tab="users">USERS</div>
<div data-tab="groups">GROUP</div>
</div>
<style>
.active{background-color: #b0c4de;}
</style>
<script type="text/javascript">
$(function(){
$("ul#tabs").tabs("#tabContent");
})(jQuery);
</script>
<script type="text/javascript">
$.fn.tabs = function(control){
var element = $(this);
control = $(control);
element.find("li").bind("click", function(){
element.find("li").removeClass("active");
$(this).addClass("active");
var tabName = $(this).attr("data-tab");
control.find(">[data-tab]").removeClass("active");
control.find(">[data-tab='"+tabName+"']").addClass("active");
});
element.find('li:first').addClass('active');
return this;
};
</script>
수정 -> delegate(), on()
<script type="text/javascript">
$.fn.tabs = function(control){
var element = $(this);
control = $(control);
element.delegate("li", "click", function(){
// 탭 이름을 얻는다.
var tabName = $(this).attr("data-tab");
// 탭을 클릭하면 커스터 이벤트가 발생한다.
element.trigger("change.tabs", tabName);
});
// 커스텀 이벤트를 바인드한다.
element.bind on("change.tabs", function(e, tabName){
element.find("li").removeClass("active");
element.find(">[data-tab='" + tabName + "']").addClass("active");
});
element.bind on("change.tabs", function(e, tabName){
control.find(">[data-tab]").removeClass("active");
control.find(">[data-tab='"+tabName+"']").addClass("active");
});
// 첫 번째 탭 활성화 - 초기값
var firstName = element.find("li:first").attr("data-tab");
element.trigger("change.tabs", firstName);
return this;
};
</script>
DOM 이외의 이벤트
사용자 이벤트 핸들러 라이브러리를 생성할 수 있다.
발행자/구독자 이벤트 핸들러 패턴 (http://en.wikipedia.org/wiki/Publish/subscribe)
발행자가 특정 채널로 메세지를 발행하면 채널을 구독하는 구독자는 발생자가 새 메세지를 발행했다는
알림을 수신한다.
var PubSub = {
subscribe: function(ev, callback){
// _callbacks 오브젝트가 없으면 새로 만든다.
var calls = this._callbacks || (this._callbacks = {});
// 이벤트 키에 해당하는 배열이 없으면 배열을 만든 다음 콜백을 배열에 추가한다.
(this._callbacks[ev] || (this._callbacks[ev] = [])).push(callback);
return this;
},
publish: function(){
// arguments 오브젝트를 진짜 배열로 바꾼다.
// var args = Array.prototype.slice.call(arguments, 0);
var args = $.makeArray(arguments);
// 이벤트 이름을 포함하는 첫 번째 인자를 추출한다.
var ev = args.shift();
// _callbacks 오브젝트가 없거나 해당 이벤트의 배열을 포함하지 않으면 반환한다.
var list, calls, i, l;
if(!(calls = this._callbacks)) return this;
if(!(list = this._callbacks[ev])) return this;
// 콜백을 호출한다.
for(i = 0, l = list.length; i < l; i++){
list[i].apply(this, args);
}
return this;
}
};
// 사용 예제
PubSub.subscribe("wem", function(){
alert("Wem!");
});
PubSub.publish("wem");