jQuery.expr[':'] 확장 및 활용 방법 - jQuery 가상 선택자 사용자 정의
jQuery.expr.pseudos 확장(사용자 정의 방법)과 활용
:hidden
, :visible
과 같은 제이쿼리의 가상 선택자를 사용자가 직접 정의, 확장하는 방법에 대해 알아봅니다.
jQuery.expr.pseudos 확장
사용자 정의 가상 선택자를 확장하는 Sizzle
엔진의 새로운 방법은 jQuery.expr.createPseudo()
메소드를 사용하는 것입니다.
이 메소드는 사용자가 직접 정의한 가상 클래스 선택자에 메타 값을 입력하는 경우에만 사용할 수 있습니다.
아래 코드를 간단히 살펴봅니다.
// jQuery.expr[':'] === jQuery.expr.pseudos
$.expr[':'].btn = $.expr.createPseudo( function(meta){
return function(el) {
console.log(
'--- element ---\n', el,
'\n\n--- meta 값 ---\n', meta
);
}
} );
위 코드에서는 :btn
이라는 가상 선택자를 사용자가 정의한 것입니다.
그리고 <a>
요소가 하나 있는 상태에서 아래와 같이 jQuery의 가상 선택자를 선택하는 것과 동일하게 입력하면..
$('a:btn(play)');
콘솔창(크롬에서 테스트)에는 다음과 같이 출력이 될 것입니다.
--- element ---
<a href></a> 또는 a
--- meta 값 ---
play
expr[':'] 을 어디에 사용하면 유용할까?
그렇다면 위와 같은 방법을 어디에서 사용하면 유용한 것일까요?
예를 들어 요소의 클래스 속성값이 'btn'
이고, 포함하는 문자열이 'play'
인 요소를 찾고자 한다고 가정합시다.
<a class="btn">play</a>
위 요소에 해당되는 대상을 매우 손쉽게 찾고자 가상 선택자를 만들고자 한다면 아래와 같이 코드를 작성할 수 있습니다.
$.expr[':'].btn = $.ex.createPseudo( function(meta){
return function(el) {
return meta ?
el.className.match(/btn/ig) && (el.textContent || el.innerText) === meta :
el.className.match(/btn/ig);
}
} );
위와 같이 작성한 후, 사용자가 정의한 가상클래스 선택자 코드를 작성하여 실행하면 원하는 대상을 찾을 수 있습니다.
즉, 사용자가 원하는 형태로 가상 클래스 선택자를 확장할 수 있다는 것입니다.
$('a:btn(play)').css( 'border', '2px solid red' );
See the Pen $.expr 기초 by jaeheekim (@jaehee) on CodePen.
$.expr[':'] 활용 코드 살펴보기
다음의 코드는 엘리먼트가 inline 요소
(사용자가 block 요소를 inline 요소로 변경했을 경우도 포함) 및 block 요소
인 것을 찾아내어 선택할 수 있는 코드입니다.
/**
* --------------------------------------------
* display: inline 요소를 찾는 sudo Expression
* --------------------------------------------
*/
if (!$.expr[':'].inline) {
$.expr[':'].inline = function(el, index, meta) { // 메타 인자는 :inline() 괄호 안의 인자값을 나타낸다.
return $(el).css('display') === 'inline';
}
}
if (!$.expr[':'].block) {
$.expr[':'].block = function(el, index, meta) {
return $(el).css('display') === 'block';
}
}
다음 아래와 같이 <a>
요소에 클래스와 data-
프로퍼티값이 설정되어 있을 경우에 가상 선택자를 확장하는 예입니다.
<a href="#none" class="btn-01" data-btn="new-anchor">앵커 버튼</a>
$.extend(jQuery.expr[':'], {
button: function(el, index, meta) {
return el.nodeName.toLowerCase() === "a" && el.className.match("btn") && el.dataset.btn === meta[3];
}
});
$("a:button(new-anchor)").css('border', '2px solid red');
$.expr advanced usage
display
속성값으로 가상 선택자를 확장해 보도록 합니다.
/**
* -----------------------------------------
* display sudo Expression 확장 (반복문 처리)
* -----------------------------------------
*/
var display_value = 'inline, block, inline-block, none, list-item'.split(', '),
i = 0,
len = display_value.length,
d_value;
for (; i < len; i++) {
d_value = display_value[i];
// 반복문에서 아래와 같은 코드 작성시에 i 는 전역변수가 되기 때문에 주의가 필요
// 그렇기 때문에 클로저를 이용한다.
// console.log(d_value);
if (!$.expr[':'][d_value]) {
// 클로저를 이용 (반복문을 사용할 시 주의해야 함)
// 첫번째 외부함수가 즉시 실행되면서 인자값으로 d_value 를 넘겨주고
// 첫번째 리턴, 즉 콜백함수가 리턴되면서 $.expr[':'][d_value] 에 담기게 된다.
// 또한 외부함수의 @param d_value 는 지역변수와 같기 때문에 콜백(내부)함수에서 d_value 값을 계속 참조하고 있을 수 있다.
// 다시 말해서, 내부함수의 지역변수가 외부함수의 지역변수를 계속 참조하도록 하는 것이다.
$.expr[':'][d_value] = (function(d_value) { // d_value 는
return function(el) {
return $(el).css('display') === d_value;
}
})(d_value); // 반복문 i 인 display_value[i]를 외부함수에 넘겨준다.
}
}
$('li:inline-block').css('border', '1px solid red');
위의 코드를 아래와 같이 리팩토링해 봅니다.
'use strict';
/**
* display sudo Expression 확장 (반복문 처리)
* jQuery.expr[':'] 확장 - display
* http://www.w3schools.com/cssref/pr_class_display.asp
* --------------------------------
*/
var filter = 'inline, inline-block, block, list-item, table, inline-table, table-caption, table-row, table-cell, table-column, flex, inline-flex'.split(', '),
k = 0,
l = filter.length;
for(; k < l; k++) {
(function(display_value){
$.expr[':'][display_value] = function(el) {
return $(el).css('display') === display_value;
}
})(filter[k]);
}
See the Pen $.expr display 속성값으로 가상 선택자 정의 by jaeheekim (@jaehee) on CodePen.