2026, 새로운 도약을 시작합니다.

제이쿼리 사용자 정의 이벤트 질문입니다. 채택완료

tabMenu1.$tabMenu.on("tabSelect", function(e) {
                tabPanel1.setSelectPanel(e.selectIndex);
            })
tabMenu1.$tabMenu은
tabMenu1 객체의 키값으로 $tabMenu가 소속되어있습니다.
tabMenu1 or $tabMenu 둘중 하나를 지우고 실행하면 실행안됩니다.
var tabMenu1 = tabMenu("#tabMenu1"); 여기서 tabMenu1라는 ID값을 변수에 넣어 초기화했는데요 왜 tabMenu("#tabMenu1")라는 값이 붙어야만 실행이 되는거죠?
$tabMenu는 사용자 정의 이벤트를 만들기 위해서 dispatchSelectEvent()안에 있는$tabmenu.trigger(event)와 함께 꼭 써야하구요
        var tabPanel1 = null;
        $(document).ready(function() {
            // 탭메뉴 코드가 동작할 수 있도록 tabMenu() 함수 호출
            var tabMenu = $("#tabMenu1");
            $tabMenu.on("tabSelect", function(e) {
                tabPanel1.setSelectPanel(e.selectIndex);
            })
            // 탭패널 기능 호출
아래쪽 전체소스코드에서 유사한 부분을 위와같이 수정해도 실행이 안됩니다.
문제점이 뭔지 모르겠습니다. 답변 부탁드립니다.
Copy


 

 

 

 

  

 

.tab-menu { 

     list-style: none; 

     height:80px; 

} 

.tab-menu li { 

    width:99px; 

    height:40px; 

    background-position-y:0; 

    text-indent: -1000px; 

    overflow: hidden; 

    display: inline-block; 

    float:left; 

} 

.tab-menu li:hover { 

     background-position-y: -40px; 

} 

.tab-menu li.select { 

     background-position-y: -80px; 

     height:80px; 

} 

.tab-menu li.menuitem1 { 

     background-image: url(./images/newbtn.bar.1.png);  

} 

.tab-menu li.menuitem2 { 

     background-image: url(./images/newbtn.bar.2.png);  

} 

.tab-menu li.menuitem3 { 

     background-image: url(./images/newbtn.bar.3.png);  

} 

.tab-menu li.menuitem4 { 

     background-image: url(./images/newbtn.bar.4.png);  

} 

.tab-menu li.menuitem5 { 

     background-image: url(./images/newbtn.bar.6.png);  

} 

.tab-contents { 

    position:relative; 

    left:10px; 

    top:10px; 

    width:780px; 

    height:340px; 

    overflow:hidden; 

    background:url(./images/content_bg.png) no-repeat; 

} 

.tab-contents .content{ 

    position: absolute; 

    left:10px; 

    top:10px; 

    display:none; 

} 

.tab-contents .content.select{ 

    display:block; 

} 

 

 

 

var tabPanel1 = null; 

$(document).ready(function() { 

    // 탭메뉴 코드가 동작할 수 있도록 tabMenu() 함수 호출 

    var tabMenu1 = tabMenu("#tabMenu1"); 

    tabMenu1.$tabMenu.on("tabSelect", function(e) { 

        tabPanel1.setSelectPanel(e.selectIndex); 

  }) 

  // 탭패널 기능 호출 

  tabPanel1 = tabPanel(".tab-contents"); 

}); 

// 탭메뉴 기능 구현하기 

function tabMenu(selector) { 

    var $tabMenu = null; 

    var $menuItems = null; 

    // 선택 한 탭메뉴를 저장할 변수 

    var $selectMenuItem = null; 

    // 요소 초기화, tabMenu() 함수 내부에서 사용할 공통 데이터는 모두 이곳에 작성해주세요. 

    function init() { 

        $tabMenu = $(selector); 

        $menuItems = $tabMenu.find("li"); 

  } 

  // 이벤트 등록은 모두 이곳에 작성해주세요. 

  function initEvent() { 

      $menuItems.click(function() { 

          setSelectItem($(this)); 

    }); 

} 

// 선택 메뉴 아이템 만들기 

function setSelectItem($item) { 

    if ($selectMenuItem) { 

        $selectMenuItem.removeClass("select"); 

  } 

  $selectMenuItem = $item; 

  $selectMenuItem.addClass("select"); 

  // 이벤트 발생 

  dispatchSelectEvent(); 

} 

// index번째 메뉴 아이템 선택 

function setSelectItemAt(index) { 

    var $item = $menuItems.eq(index); 

    setSelectItem($item); 

} 

// 이벤트 발생 

function dispatchSelectEvent() { 

    // 이벤트 객체 생성 

    var event = jQuery.Event("tabSelect"); 

    // 이벤트에 담아 보낼 데이터 연결 

    event.selectIndex = $selectMenuItem.index(); 

    event.$selectItem = $selectMenuItem; 

    $tabMenu.trigger(event); 

} 

init(); 

initEvent(); 

return { 

    $tabMenu : $tabMenu, 

    setSelectItemAt : setSelectItemAt 

} 

} 

// 탭패널 기능 구현하기 

function tabPanel(selector) { 

    var $tabPanels = null; 

    var $selectPanel = null; 

    function init(selector) { 

        $tabPanels = $(selector).find(".content"); 

  } 

  function setSelectPanel(index) { 

      if ($selectPanel) { 

          $selectPanel.removeClass("select"); 

    } 

    $selectPanel = $tabPanels.eq(index); 

    $selectPanel.addClass("select"); 

} 

init(selector); 

// 선택기능 리턴 

return { 

    setSelectPanel : setSelectPanel 

} 

} 

 

 

 

 

google 

facebook 

pinterest 

twitter 

path 

 

   

 

 

 

 

 

 

     

 

 

 

 

 

 

 

 

 

 

 



답변 6개

채택된 답변
+20 포인트

일단, 코드는 동작을 합니다.

Copy


// 1.

// tabMenu 함수에서 tab 클릭하면

// 메뉴에 select class 를 추가하고

// select 된 index 와 element 를 담은 이벤트를 trigger 합니다.

// 이때 이 tabMenu 함수는 selector 를 인자로 받죠. html 에서 뭐가 메뉴인지 알아야 하니까..

function tabMenu(selector) {

   ....

}

2. tabMenu 와 tabPanel 을 연결시켜주는 코드는..

Copy


        $(document).ready(function () {

            // 탭메뉴 코드가 동작할 수 있도록 tabMenu() 함수 호출

            var tabMenu1 = tabMenu("#tabMenu1");

            // 탭패널 기능 호출

            var tabPanel1 = tabPanel(".tab-contents");

            tabMenu1.$tabMenu.on("tabSelect", function (e) {

                tabPanel1.setSelectPanel(e.selectIndex);

            });

        });

맞게 하신것 같네요...

로그인 후 평가할 수 있습니다

댓글을 작성하려면 로그인이 필요합니다.

1. $.extend(obj1, obj2, obj3); 이렇게 있으면.. obj3 를 obj2 에 합치고, 그 결과를 다시 obj1 에 합치는 것이니 말씀하신게 맞습니다.
2. 그 부분은 제 실수네요 ^^;;;

Copy
...

// jQuery chainning 을 위해 반환

return this.each(function() {

// $(this) 는 $(메뉴) 에 해당함

$(this).each(function (idx, ele) {

...

// 이것은 그냥.. 이렇게 되야겠네요. this == $('.tabMenu') 입니다.

return this.each(function(idx, ele) {

   ...

};

3. tabMenu1.$tabMenu.on("tabSelect", function(e) {} .. 이건 체이닝이라기 보단.. tabMenu1 의 attribute 에 $tabMenu 가 있는 것입니다.
   말씀하신대로

Copy
tabMenu1 = {

    $tabMenu : $tabMenu,

    setSelectItemAt : setSelectItemAt

};

   이기 때문에, tabMenu1.$tabMenu.on() .. 이렇게 호출할 수 있는 것이 맞습니다.
   따라서 이경우에는 chaining 이 아닙니다. chaining 은 메소드가 자기 자신을 다시 반환함으로써 이어서 다른 함수를 계속 호출할 수 있도록 하는 것입니다.
   $(selector).myTab().setBorder() 처럼 myTab() 안에서 object 자신인 $(selector) 를 반환함으로써 또 다시 setBorder() 를 호출할 수 있도록 하는 것입니다.
   마찬가지로 setBorder()에서도 $(selector) 자신을 반환해서 다른 플러그인을 연속해서 호출 할 수 있도록 하는 것입니다.
로그인 후 평가할 수 있습니다

댓글을 작성하려면 로그인이 필요합니다.

1. $.fn.PLUGIN_NAME = function() {}; jQuery 플러그인 등록하는 방법입니다.

2. $.extend 는 object 들을 merge 하는 함수입니다. https://api.jquery.com/jquery.extend/

3. "아래 onbeforeTabChange가 호출된 이 후에 위에 if문이 호출되는겁니다."

   그 아래에 있는 `onbeforeTabChange` 는 myTab 에 파라미터로 전달되는 인자입니다. 거기서 실행되는게 아니고. extend 함수에 의해서 settings 에 합쳐져서, 플러그인 내에서 호출이 되는거죠. 즉, 이벤트 처리루틴을 함수에 인자로 넘겨주는 것입니다.

간단한 코드로 설명드릴테니 아래를 천천히 읽어보세요.

아래와 같은 HTML 코드가 있다고 하고 코드로 설명을 드려봅니다.

Copy




    제목

    내용





    목록1

    목록2

    목록3



기본적인 jQuery 플러그인을 작성해보겠습니다. $(selector).printOut() 이라고 호출하면 selector 에 해당하는 HTML element 의 내용을 콘솔에 출력하는 것입니다.

Copy




(function($) {

    // `printOut` 이라는 jQuery 플러그인 등록

    $.fn.printOut = function() {

        // HTML element 의 내용을 콘솔에 출력

        console.log(this.html());

    };

})(jQuery);

$(document).ready(function () {

    // `#article` 의 내용을 출력합니다.

    $('#article').printOut();

    #('.lst').printOut(); // 첫번째 .lst 의 내용만 출력됨 T_T;;;

});

모든 .lst 에 대해서 동작하도록 수정해보겠습니다.

Copy


(function($) {

    // `printOut` 이라는 jQuery 플러그인 등록

    $.fn.printOut = function() {

        // 아래의 this는 $('.lst') 와 같습니다.

        // '.lst' 클래스를 갖는 element 들에 대해서 반복문을 돈다고 이해하시면 되겠습니다.

        this.each(function(idx, ele) {

            // 각 .lst ELEMENT 들에 대해서 내용을 화면에 출력

            console.log($(ele).html());

        }

    };

})(jQuery);

$(document).ready(function () {

    // 3개의 LI 의 내용들이 콘솔에 출력됩니다.

    $('.lst').printOut();

});

만약, '.lst' 의 내용을 화면에 출력하고 이어서 다른 플러그인을 호출하고 싶다면 어떻게 하는지 해보겠습니다.

Copy


(function($) {

    // `printOut` 이라는 jQuery 플러그인 등록

    $.fn.printOut = function() {

        // `return` 이 추가되었습니다.

        // 여기서 return 을 하므로, 다음과 같은 호출이 가능합니다.

        // $(selector).printOut().setBorder();

        return this.each(function(idx, ele) {

            console.log($(ele).html());

        }

    };

    // 선택된 HTML Element 에 red border 를 설정하는 플러그인

    $.fn.setBorder = function() {

        return this.each(function (idx, ele) {

            $(ele).css({'border': '1px solid red'});

        });

    };

})(jQuery);

$(document).ready(function () {

    // 3개의 LI 의 내용들이 콘솔에 출력됩니다.

    // 그리고 각 LI 에 border 가 red 로 설정됩니다.

    $('.lst').printOut().setBorder();

});

만약, `setBorder` 플러그인에 색을 지정하고 싶은경우 어떻게 하는지 해보겠습니다.

Copy


(function($) {

    $.fn.printOut = function() {

        return this.each(function(idx, ele) {

            console.log($(ele).html());

        }

    };

    // options 를 파라미터로 받습니다.

    $.fn.setBorder = function(options) {

        // 기본 설정값은 'border_color' 가 'red' 로 되어있습니다.

        // 이 설정을 파라미터로 넘어온 options 와 병합합니다.

        // 즉, 기본값은 'red' 이지만 사용자가 options 를 통해 색을 변경할 수 있습니다.

        let settings = $.extend({

            border_color: 'red'

        }, options);

        return this.each(function (idx, ele) {

            // `settings.border_color` 로 border 를 설정합니다.

            $(ele).css({'border': '1px solid '+settings.border_color});

        });

    };

})(jQuery);

$(document).ready(function () {

    // setBorder 플러그인에 {border_color: 'red'} 를 넘깁니다.

    // 위의 setBorder(options) 의 `options` 가 {border_color: 'red'} 인거죠.

    // 이렇게 하면, 화면에 LI 내용들이 3개 출력되고 각 LI 들에 파란색 border 가 생깁니다.

    $('.lst').printOut().setBorder({border_color: 'blue'});

});

쉬운 예제로 설명드렸습니다. 찬찬히 보시면 아실 수 있을겁니다.
답변으로 드린 예제도 형식은 지금 설명드린 플러그인 작성법에 따른것이므로 이해하실 수 있을겁니다.
화이팅~

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

답변 정말 감사드립니다.
이렇게 자세히 풀이해주시다니 감동입니다.^^
추가 질문이 있습니다.

let settings = $.extend({
border_color: 'red' }, options);
options매개변수와 border_color:red를 합치는건데요
options가 border_color:'red' 보다 뒤에 있어서 결과적으로 뒤에있는 블루색상이 적용되는게 맞는지 궁금합니다.


그리고
// $(this) 는 $(메뉴) 에 해당함
$(this).each(function (idx, ele) {

this.each에서 this = $('.tabMenu')이며
$(this).each(function (idx, ele) {에서 $(this)는 $(메뉴) 에 해당한다고 하셨는데요 어떻게 $(메뉴)가 되는지 모르겠습니다. 정확히 어떤 것인지도 모르겠습니다.


그리고
myTab함수에서

return this.each(function() {
// $(this) 는 $(메뉴) 에 해당함
$(this).each(function (idx, ele) { ~ blah ~ blah~

리턴을 해주기때문에 $('.tabMenu').myTab({ 에서 메소드 체이닝이 가능했던건데요
제가 맨 처음에 올렸던 질문 중에
tabMenu1.$tabMenu.on("tabSelect", function(e) {
여기서도 체이닝이 일어납니다.

function tabMenu(selector) {에서

return {
$tabMenu : $tabMenu 를 객체 키,값을 리턴 해주기 때문에
---------------------------------------------------------
tabMenu 함수는 tabMenu1에 대입되었습니다.
var tabMenu1 = tabMenu("#tabMenu1");
---------------------------------------------------------
tabMenu1에서 .(object access operator)로 접근이 가능했던게 맞지 궁금합니다.

댓글을 작성하려면 로그인이 필요합니다.

사용자 이벤트 처리를 할 수 있도록.. jQuery 플러그인 형태로 만들면..

Copy




    탭 메뉴1

    탭 메뉴2

    탭 메뉴3

    탭 메뉴4

    탭 메뉴5





    탭 컨텐츠 1

    탭 컨텐츠 2

    탭 컨텐츠 3

    탭 컨텐츠 4

    탭 컨텐츠 5





(function($) {

    // JQuery 플러그인에 등록

    // - options: 사용자 지정 옵션

    $.fn.myTab = function(options) {

        // 옵션을 기본 설정과 병합

        let settings = $.extend({

            onBeforeTabChange : null,

            onAfterTabChange : null,

        }, options);

        // 지정된 selector 에 해당하는 모든 elements 들을 순회

        // jQuery chainning 을 위해 반환

        return this.each(function() {

            // $(this) 는 $(메뉴) 에 해당함

            $(this).each(function (idx, ele) {

                // 탭 메뉴 레퍼 (UL)

                let $tabMenu = $(ele);

                // 각 메뉴들 (LI 태그)

                let $menuItems = $tabMenu.find("li");

                // 탭 패널들 (UL 태그의 'data-panel-wrapper' 속성을 읽어와 그 안의 '.tab-panel' 클래스들을 찾음)

                let $tabPanels = $('#' + $tabMenu.data('panel-wrapper')).find('.tab-panel');

                // 메뉴 클릭 이벤트 핸들러

                function setSelectItem($item) {

                    // onBeforeTabChange 가 옵션으로 설정되었다면 호출

                    if (settings.onBeforeTabChange) {

                        settings.onBeforeTabChange($item);

                    }

                    $menuItems.removeClass('select');

                    $item.addClass('select');

                    $tabPanels.removeClass('select');

                    let $clickedPanel = $tabPanels.eq($item.index());

                    $clickedPanel.addClass('select');

                    // onAfterTabChange 가 옵션으로 설정되었다면 호출

                    if (settings.onAfterTabChange) {

                        settings.onAfterTabChange($item, $clickedPanel);

                    }

                }

                // 클릭 이벤트 등록

                $menuItems.click(function () {

                    setSelectItem($(this));

                });

            });

        });

    };

})(jQuery);

$(document).ready(function () {

    $('.tabMenu').myTab({

        // 탭이 클릭된 후 메뉴가 변경되기 바로 직전 호출

        // - $menu : 클릭된 메뉴

        onBeforeTabChange: function($menu) {

            console.log('before tab change : ', $menu);

        },

        // 탭이 클릭된 후 메뉴가 변경된 바로 직후 호출

        // - $menu : 클릭된 메뉴

        // - $panel : 선택된 탭 패널

        onAfterTabChange: function($menu, $panel) {

            console.log('after tab change : ', $menu, $panel);

        }

    });

});



이런식으로 됩니다. 공부하시는데 도움이 되시라고 만들어봤습니다.

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

답변 감사드립니다.
적어주신 소스 실행해보았는데요 어렵습니다. 초보입니다.
먼저 $.fn.myTab 라면 fn는 function 약자인가요? jQuery에서 공식으로 지원하는 키워드인지 궁금합니다.

$.fn.doThing = function() { }; // jQuery.prototype 에 함수 추가라는데요 myTab이면 jquery.prototype인가요?

그리고 제가 아직 책에서 extend 메서드를 못 마주쳤는데요
let settings = $.extend({
settings 변수는 $.extend 블록 내에서만 실행되는거구요
onbefore,onaftertabchange 변수 값에 null이 할당됩니다.

그리고
// onBeforeTabChange 가 옵션으로 설정되었다면 아래 if문이 호출되는 건데요
if (settings.onBeforeTabChange) {

아래 onbeforeTabChange가 호출된 이 후에 위에 if문이 호출되는겁니다.
$(document).ready(function () {
$('.tabMenu').myTab({
// 탭이 클릭된 후 메뉴가 변경되기 바로 직전 호출
// - $menu : 클릭된 메뉴
onBeforeTabChange: function($menu) {
console.log('before tab change : ', $menu);

전체적으로 저에게 난이도가 상이여서 이해가 안됩니다....

끝으로
// $(this) 는 $(메뉴) 에 해당함
29
$(this).each(function (idx, ele) {
$(this)는 $(메뉴)에 해당한다고 하셨는데 어느부분에서 this가 메뉴를 참조하는지 궁금합니다.

쉽게 설명 부탁드립니다.

댓글을 작성하려면 로그인이 필요합니다.

첫번째 질문 부터

=======================

var tabMenu1 = tabMenu("#tabMenu1"); 여기서 tabMenu1라는 ID값을 변수에 넣어 초기화했는데요 왜 tabMenu("#tabMenu1")라는 값이 붙어야만 실행이 되는거죠?

===================

var 뒤에 붙은 tabMenu1은 그냥 변수입니다.  그냥 xx1이라고 바꾸어도 됩니다. (67번째 줄도)

#tabMenu1은 114번째 줄의 tabMenu1입니다.  이것을 둘다 yy2로 바꾸셔도 됩니다.

그리고 tabMenu는 함수명의 tabMenu이고..(66째줄)

67번째줄의 $tabMenu는 75번째줄의 변수입니다. zz3로 바꾸면

id=yy2를 tabMenu라는 함수로 처리한후에 xx1변수에 담아서 xx1안에 있는 변수 zz3를 선택하고 그것의 on event를 선택하는 것 같습니다. 

JQeury가 어렵네요. ㅠㅠ

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

답변 감사드립니다. 제가 xx1,yy2,zz3로 변수명을 변경해보았는데요 적어주신 줄번호가 틀려서 어디에 xx1이 들어가고 zz3이 들어가는지 정확히 모르겠습니다..;

댓글을 작성하려면 로그인이 필요합니다.

약간 소스를 고쳐보면요..

- ul 태그에 탭 패널들을 감싸는 wrapper 의 ID 를 지정 (data-panel-wrapper="tabContent1")

- 각 탭 메뉴들에 연결되는 탭 패널들의 ID 를 지정 (data-panel="pan1" --> 클릭시 '#pan1' 을 선택)

- MyTab 함수에서 selector 를 클래스로 받게되면, 한페이지에 탭이 여러개 있어도 한번에 처리 가능

Copy




    탭 메뉴1

    탭 메뉴2

    탭 메뉴3

    탭 메뉴4

    탭 메뉴5





    탭 컨텐츠 1

    탭 컨텐츠 2

    탭 컨텐츠 3

    탭 컨텐츠 4

    탭 컨텐츠 5





        $(document).ready(function () {

            MyTab('.tabMenu');

        });

        // 탭메뉴 기능 구현하기

        function MyTab(selector) {

            $(selector).each(function(idx, ele) {

                // 탭 메뉴 레퍼 (UL)

                let $tabMenu = $(ele);

                // 각 메뉴들 (LI 태그)

                let $menuItems = $tabMenu.find("li");

                // 탭 패널들 (UL 태그의 'data-panel-wrapper' 속성을 읽어와 그 안의 '.tab-panel' 클래스들을 찾음)

                let $tabPanels = $('#'+$tabMenu.data('panel-wrapper')).find('.tab-panel');

                // 메뉴 클릭 이벤트 핸들러

                function setSelectItem($item) {

                    $menuItems.removeClass('select');

                    $item.addClass('select');

                    $tabPanels.removeClass('select');

                    $tabPanels.eq($item.index()).addClass('select');

                }

                // 클릭 이벤트 등록

                $menuItems.click(function () {

                    setSelectItem($(this));

                });

            });

        }



로그인 후 평가할 수 있습니다

댓글을 작성하려면 로그인이 필요합니다.

답변을 작성하려면 로그인이 필요합니다.

로그인
🐛 버그신고