jQuery, 자주 묻는 질문들

(문제) class나 ID를 통해 어떻게 항목을 선택할 수 있나요?

아래의 코드는 ID가 #myDivId인 항목을 선택합니다.

$('#myDivId');

아래는 myCssClass라는 class 이름을 갖는 요소를 선택합니다.

$('.myCssClass');

(문제) 이 DOM 요소를 가지고 있을때, 이를 이용해 요소를 어떻게 선택하나요?

아래의 코드는 ID가 foo인 DOM 요소를 가지고, 이 요소에 포함된 모든 요소를 선택하고 있습니다.

var myDomElement = document.getElementById('foo');
$(myDomElement).find('a');

(문제) 특정 class가 지정되어져 있는 요소인지 확인은 어떻게 하나요?

아래의 코드처럼 hasClass를 사용하면 됩니다.

$( "div" ).click(function() {
    if ( $( this ).hasClass( "protected" ) ) {
        $( this )
            .animate({ left: -10 })
            .animate({ left: 10 })
            .animate({ left: -10 })
            .animate({ left: 10 })
            .animate({ left: 0 });
    }
});

또한 아래처럼 요소의 상태 확인이 가능한 is 함수를 사용해서도 가능합니다.

if ( $( "#myDiv" ).is( ".pretty.awesome" ) ) {
    $( "#myDiv" ).show();
}

is 함수는 선택된 요소가 숨김 상태인지를 다음처럼 확인할 수 있습니다.

if ( $( "#myDiv" ).is( ":hidden" ) ) {
    $( "#myDiv" ).show();
}

(문제) 선택 요소가 있는지 확인은 어떻게 하나요?

선택자로 얻은 결과에 대해 .length 속성으로 아래처럼 확인할 수 있습니다. length 속성은 선택자에 의해 몇개의 요소가 선택되었는지에 대한 개수를 반환합니다.

if ( $( "#myDiv" ).length ) {
    $( "#myDiv" ).show();
}

(문제) 토글(toggled)되어진 요소의 상태를 어떻게 결정할 수 있나요?

요소가 숨겨져 있는지에 확인하는 것은 :visible과 :hidden 선택자를 사용해 파악이 가능하다.

var isVisible = $( "#myDiv" ).is( ":visible" );
var isHidden = $( "#myDiv" ).is( ":hidden" );

가시성에 기반해 요소에 대한 간단한 조작을 하고자 한다면, 단지 선택자에서 :visible이나 :hidden을 사용합니다. 아래이 코드를 보시기 바랍니다.

$( "#myDiv:visible" ).animate({
    left: "+=200px"
}, "slow" );

(문제) 폼 요소에 대해 비활성화/활성화는 어떻게 하나요?

아래의 코드처럼 prop 함수를 사용해 폼 요소를 활성화 하거나 비활성화 할 수 있습니다.

// Disable #x
$( "#x" ).prop( "disabled", true );

// Enable #x
$( "#x" ).prop( "disabled", false );

(문제) 체크박스 또는 라디오버튼에 대한 체크나 언체크는 어떻게 하나요?

아래의 코드처럼 prop 함수를 사용해 체크 여부를 결정할 수 있습니다.

// Check #x
$( "#x" ).prop( "checked", true );

// Uncheck #x
$( "#x" ).prop( "checked", false );

(문제) 선택된 option의 텍스트 값은 어떻게 얻나요?

선택 요소는 일반적으로 얻을 수 있는 2가지 값이 있습니다. 첫번째는 서버로 보내지는 값이며, 아래처럼 간단히 얻을 수 있습니다.

$( "#myselect" ).val();
// => 1

두번째는 선택된 요소의 텍스트 값인데요. 예를들어 아래와 같은 코드와 같다고 합시다.


아래의 코드를 통해 선택된 option의 텍스트 값을 얻을 수 있습니다.

$( "#myselect option:selected" ).text();
// => "Mr"

(문제) 10개의 항목 리스트 중 3번째 요소의 텍스트값을 변경하기는?

:eq() 선택자 또는 eq 함수를 사용해 원하는 항목을 선택할 수 있습니다. 아래는 eq 함수를 사용한 경우입니다.

var thirdLink = $( this ).find( "li a" ).eq( 2 );
var linkText = thirdLink.text().replace( "foo", "bar" );
thirdLink.text( linkText );

(문제) jQuery 객체로부터 Native DOM 요소를 어떻게 얻나요?

선택자에 의한 jQuery 객체는 1개 이상의 DOM 요소를 배열처럼 감싼 객체입니다. 이 jQuery 객체에 대한 실제 DOM 요소에 대한 참조를 얻기 위한 방법은 2가지입니다. 첫번째는 배열 표기법으로 아래와 같습니다.

$( "#foo" )[ 0 ]; // document.getElementById( "foo" )와 동일한 코드

2번째 방법은 get 함수로 다음과 같습니다. (첫번째 방법보다 느림)

$( "#foo" ).get( 0 ); 

만약 get 함수에 인자를 지정하지 않고 호출하면, DOM 요소의 실제 배열을 반환합니다.

jQuery의 유틸리티 함수

jQuery의 플러그인 기능 중에 유틸리티 성격의 플러그인을 정리해 봅니다. 정리해 놓으면 딱 필요할때 익숙하게 사용할 수 있겠지요.

먼저 문자열 앞뒤의 공백 문자를 제거해 주는 코드입니다.

var s = '   You are, you will be good.      ';
s = $.trim(s);

다음은 배열의 값이나 객체의 키-값들을 순회하는 each 함수이며, 예제 코드는 아래와 같습니다.

$.each(['foo', 'bar', 'baz'], function (i, v) {
    alert(i + " : " + v);
});

$.each({ foo: 'bar', baz: 'bim' }, function (k, v) {
    alert(k + ' : ' + v);
});

그리고 어떤 값이 배열에 속해 있는지를 검사하는 플러그인입니다.

var myArray = [1, 2, 3, 4, 5];
if ($.inArray(4, myArray) !== -1) {
    alert('found.');
}

다음은 어떤 객체에 또 다른 객체의 키-값을 복사해 주는 플러그인입니다. $.extend의 첫번째 인자는 복사가 되어 값이 저장될 대상 객체입니다. 그리고 두번째 이후의 인자는 복사될 키-값을 담고 있는 객체들입니다. 아래의 코드는 secondObj의 키-값을 firstObj에 복사해 주는 코드인데요. 결국 firstObj.foo는 secondObj.foo의 값으로 변경됩니다. $.extend는 첫번째 인자를 반환하므로 newObject === firstObj는 true입니다.

var firstObj = { foo: 'bar', a: 'b' };
var secondObj = { foo: 'baz' };
var newObject = $.extend(firstObj, secondObj);

alert(firstObj.foo);

if (newObject === firstObj) {
    alert('equal');
}

다음 코드는 함수 호출시 내부의 this를 개발자가 의도한 객체로 하여 함수를 호출하도록 하는 플러그인입니다. 아래의 코드에서 myFunction는 전역 객체인 Window의 소유로 이 함수를 그대로 호출하면 함수 내부에서 this는 Window 객체가 됩니다. 그러나 12번 코드를 통해 myFunction 함수에 대한 내부 this를 myObject로 변경해주는 함수로 myProxyFunction를 생성하고 있습니다. 실제로 이 myProxyFunction를 13번 코드처럼 그대로 호출하면 함수 내부의 this는 myObject가 됩니다. JavaScript의 이벤트 리스너 함수에서 this 객체가 다소 혼란스러울 때가 있습니다. 이 혼란의 시기에 이 플러그인이 해결점이 될 수 있겠습니다.

var myFunction = function () {
    alert(this);
};

var myObject = {
    foo: 'bar',
    toString: function () { return 'myObject'; }
};

myFunction();

var myProxyFunction = $.proxy(myFunction, myObject);
myProxyFunction();

다음은 배열을 순회하면서 원하는 값들로 구성된 배열을 생성하는 플러그인입니다. 7번 코드의 실행을 통해 arr 배열의 요소 객체의 id 속성만으로 구성된 배열을 생성해 반환합니다. 11번 코드는 새롭게 생성된 배열의 값을 확인하는 코드입니다.

var arr = [
    { id: 'a', tagName: 'li' },
    { id: 'b', tagName: 'li' },
    { id: 'c', tagName: 'li' }
];

var result = $.map(arr, function (value, index) {
    return value.id;
});

$.each(result, function (i, v) {
    alert(i + ' : ' + v);
});

다음은 특정 객체의 타입이 무엇인지를 확인하는 플러그인입니다.

alert($.isArray([])); // true
alert($.isFunction(function () { })); // true
alert($.isNumeric(3.14)); // true

alert($.type(true)); // boolean
alert($.type(3)); // number
alert($.type('test')); // string
alert($.type(function () { })); // function
alert($.type([])); // array
alert($.type(null)); // null
alert($.type(/test/)); // regexp
alert($.type(new Date())); date

[Android] 맨날 까먹는 버튼 클릭 이벤트 핸들러 코드

맨날 까먹어 책 찾아 보고.. 인터넷 뒤져보고.. 해서 이 기회에 버튼에 대한 클릭 이벤트 핸들러 코드를 작성하는 것에 대해 정리를 해 놔야겠습니다. 머리가 나쁘니.. 손이 좀 고생을 해야겠지요..

레이아웃에 두개의 버튼이 있다고 가정하겠습니다. id는 각각 viewMode, editMode라고 하면.. 클릭 이벤트에 대한 핸들러 코드를 작성하는 방법에는 2가지가 있습니다. 물론 따져보면 둘다 동일한 방식이기는 하지만 코드 모냥새가 다르므로 다르다고 치겠습니다.

첫번째 방식입니다. 다수의 버튼들에 대한 이벤트 코드를 한자리에 가족같은 분위기로 다스리는 치국평천하 방식이라고 할 수 있겠습니다..

@Override
public void onCreate(Bundle savedInstanceState) {
    findViewById(R.id.viewMode).setOnClickListener(btnClickListener);
    findViewById(R.id.editMode).setOnClickListener(btnClickListener);
}

private Button.OnClickListener btnClickListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        switch(v.getId()) {
            case R.id.viewMode:
                map.setMouseMode(MouseMode.MapViewMode);
                break;

            case R.id.editMode:
                map.setMouseMode(MouseMode.EditMode);
                break;
        }
    }
};

두번째 방식입니다. 이 방식은 각 버튼마다 이벤트 처리 코드를 따라 분리해 두는 방식입니다.

@Override
public void onCreate(Bundle savedInstanceState) {
    ....
    
    findViewById(R.id.viewMode).setOnClickListener(
        new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                map.setMouseMode(MouseMode.MapViewMode);
            }
        }
    );

    findViewById(R.id.editMode).setOnClickListener(
        new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                map.setMouseMode(MouseMode.EditMode);
            }
        }
    );
    
    ....
}

앞서도 말씀드렸지만.. 첫번째나 두번째나 결국 똑 같은 방식입니다..

세번째 방식은 상당히 직관적인 것으로 생각되는데요. 레이아웃을 정의하는 XML에서 터치 이벤트 함수명을 지정하고 간단히 소스코드에서 해당 이벤트 함수를 추가해 주기만 하면 됩니다. 예를 들어서 레이아웃을 정의하는 XML 중 버튼 부분만을 보면..

위의 버튼에 대한 터치 이벤트 함수인 onClickButton은 아래처럼, 해당 뷰를 사용하는 엑티비트의 구현부에 추가하면 됩니다.

public void onClickButton(View v) {
    // 직관적이닷!
}

K-Means 알고리즘 구현

군집화 알고리즘(Clustering Algorithm) 중 K-Means 가 있습니다. K-Means 알고리즘에 대한 설명 이전에, 실제로 구현된 K-Means 알고리즘에 대한 실행 결과를 바로 설명하면서 자연스럽게 K-Means 알고리즘이 무엇인지 설명하겠습니다. 아래는 K-Means 알고리즘을 실행하기 위해 입력한 포인트 데이터입니다. SHP 파일을 통해 입력 받았습니다.

위의 이미지처럼 공간상에 무수히, 주관적 해석이긴 하지만 의미 없이 분포되어 있는 포인트들에 대해서 어떤 연관 관계에 대한 특성을 부여함으로써 몇개로 묶을 수 있는데요. 이처럼 묶는다라는 것을 그룹핑, 클러스터링이라고 합니다. K-Means 알고리즘에서 몇개(K개)로 묶을지를 지정하여 원하는 개수 만큼 클러스터링할 수 있습니다. 아래의 화면은 K-Means 알고리즘을 활용하여 12개의 그룹으로 공간상의 포인트를 묶은 결과입니다.

앞서 포인트를 그룹으로 묶을 때 어떤 관계에 대한 특성을 부여한다고 하였는데요. 위의 화면에서는 그 특성을 거리(Distance)로 하였습니다. 즉, 거리 상으로 가까운 포인트들을 그룹으로 묶는 것입니다.

이처럼 이미 확보한 수 많은 공간상의 데이터를 그룹핑하여 놓는다면, 새로운 포인트에 대해서 어느 그룹에 포함되는지에 대한 해석이 매우 빠르게 분류될 수 있습니다. 이미 확보한 데이터가 많으면 많을 수록, 새로운 데이터에 대한 해석이 보다 더 정확할 수 있겠죠.

아래는 K-Means 알고리즘을 구현한 C# 소스코드이며, 듀라맵(DuraMap-Xr)을 이용하여 K-Means 알고리즘에 필요한 포인트 데이터를 SHP 파일로부터 읽어 들이고 그 결과를 시각화 하였습니다.

Convex-Hull 알고리즘 구현

Convex Hull은 볼록한 껍데기로.. 무수히 많은 포인트를 감싸는 볼록한 영역으로 정의할 수 있습니다. 입력 데이터인 포인트는 SHP 파일로부터 제공받아, 이를 듀라맵에서 그 결과를 표시하도록 하였습니다. 아래는 그 결과 화면입니다.

무수히 많은 작은 포인트를 감싸는 Convex Hull이 반투명한 빨간색 폴리곤으로 표시되어져 있습니다. 이러한 Convex-Hull에 대한 구현에 대해 C# 클래스로 정의했으며 아래와 같습니다.

using System;
using System.Collections.Generic;

namespace tstConvexHull
{
    public class ConvexHull
    {
        public class Point : IComparer
        {
            public double x;
            public double y;

            public Point()
            {
                x = 0.0;
                y = 0.0;
            }

            public Point(double x, double y)
            {
                this.x = x;
                this.y = y;
            }

            public int Compare(Point p1, Point p2)
            {
                if (p1.x == p2.x)
                {
                    return p1.y > p2.y ? 1 : p1.y < p2.y ? -1 : 0;
                }
                else
                {
                    return p1.x > p2.x ? 1 : p1.x < p2.x ? -1 : 0;
                }
            }
        }

        public static double Cross(Point O, Point A, Point B)
        {
            return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);
        }

        public static Point[] Get(Point[] P)
        {
            if (P.Length > 1)
            {
                int n = P.Length, k = 0;
                Point[] H = new Point[2 * n];

                Array.Sort(P, new Point());

                for (int i = 0; i < n; ++i)
                {
                    while (k >= 2 && Cross(H[k - 2], H[k - 1], P[i]) <= 0)
                        k--;
                    H[k++] = P[i];
                }

                for (int i = n - 2, t = k + 1; i >= 0; i--)
                {
                    while (k >= t && Cross(H[k - 2], H[k - 1], P[i]) <= 0)
                        k--;
                    H[k++] = P[i];
                }

                if (k > 1)
                {
                    Point[] NewH = new Point[k - 1];
                    Array.Copy(H, NewH, k - 1);
                    H = NewH;
                }
                return H;
            }
            else if (P.Length <= 1)
            {
                return P;
            }
            else
            {
                return null;
            }
        }
    }
}

실제 위의 Convex-Hull 클래스에 대한 사용은 아래 코드와 같은데요. DuraMap-Xr에서 SHP 파일로부터 점 데이터를 읽어 입력 데이터를 구성하여 Convex-Hull을 실행하고 그 결과로 반투명 빨간색 폴리곤을 추가하는 코드 모두를 나타내고 있습니다.

XrMapLib.ShapeMapLayer lyr = axXr.Layers.GetLayerAsShapeMap("lyr");
XrMapLib.ShapeTable tbl = lyr.ShapeTable;
int cntRows = tbl.RowCount;

ConvexHull.Point[] pts = new ConvexHull.Point[cntRows];

for(int i=0; i

코드를 살짝 설명하면, 1~15번 코드는 SHP 파일로부터 포인트 데이터를 읽어와 Convex-Hull 알고리즘에 입력할 데이터를 준비하는 것이고, 17번 코드가 바로 Convex-Hull의 실행이며 19번 코드부터는 Convex-Hull의 결과를 그래픽 객체로 가시화시켜주는 코드들입니다.