2011-02-11 109 views
0

我試圖創建一個插件方式的下拉菜單。我很熟悉將自己編寫爲解決方案,但是我從未創建過插件,所以我正在努力學習如何做到這一點,因此提升了我作爲jQuery開發人員的水平。jQuery插件創作,幫助點擊事件(下拉菜單)

我試圖創建基本的下拉功能。你有一個鏈接。你點擊它,鏈接出現下拉菜單。您單擊鏈接(文檔)外的鏈接菜單消失。

我在走開的部分遇到了麻煩。我試圖將它綁定到document.click,但當然顯示菜單,然後隱藏它,因爲沒有什麼能確保它必須先顯示。我該怎麼做呢?

我該如何做到這一點,使菜單隻顯示後,如果你點擊它之外隱藏?

的application.js

jQuery(document).ready(function($){ 
    $("ul.drop-down").sillyDropDown(); 
    // failed attempt (shows and hides). Probably should go in plugin anyway. 
    // $(document).click(function(){ 
    // $("ul.drop-down").sillyDropDown('hide'); 
    // }); 
}); 

silly_drop_down.js

(function($){ 

    var methods = { 

    init : function(options){ 
     return this.each(function(){ 
     var $this = $(this); 
     var selector = $(this).children()[0]; 
     var link = $(selector); 
     link.bind('click.silly', methods.show); 
     }); 
    }, 
    show : function() { 
     var $this = $(this); 
     var menu = $this.siblings("ul"); 
     menu.slideDown("slow"); 
    }, 
    hide : function(){ 
     var $this = $(this); 
     var menu = $this.children("ul"); 
     menu.slideUp("slow"); 
    } 
    }; 

    $.fn.sillyDropDown = function(method){ 
    if (methods[method]) { 
     return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 
    } else if (typeof method === 'object' || ! method) { 
     return methods.init.apply(this, arguments); 
    } else { 
     $.error('Method ' + method + ' does not exist on jQuery.sillyDropDown'); 
    } 
    }; 

})(jQuery); 

的HTML,如果它的事項

<ul id="project-settings" class="drop-down"> 
    <li> 
    <a href="#"> 
     Settings 
     <img src="/images/iconic/white/cog_alt_16x16.png" class="stale"> 
     <img src="/images/iconic/orange/cog_alt_16x16.png" class="hover"> 
    </a> 
    </li> 
    <ul style="display: none;"> 
    <div class="pointer"></div> 
    <li class="first"> 
     <a href="#">Settings...</a> 
    </li> 
    <li> 
     <a href="#">Collaborators...</a> 
    </li> 
    <li> 
     <a href="#">Comments...</a> 
    </li> 
    <hr> 
    <li> 
     <a href="#">Delete Project</a> 
    </li> 
    </ul> 
</ul> 

編輯(我意識到我問過類似的問題)。 我的確在application.js中

$("ul.drop-down").sillyDropDown(); 
    $(document).bind("click.silly", function(e){ 
    var nav = $("ul.drop-down"); 
    var target = $(e.target); 
    if (target.closest("ul.drop-down").length < 1){ 
     nav.sillyDropDown('hide'); 
     return; 
    } 
    }); 

這做工作如下。但是,在application.js中執行它似乎並不高雅 - 我將如何在插件內處理這個問題?

注意:我可能會有多個ul.drop-down實例 - 我是否在執行中缺少某些東西來處理此問題?到目前爲止,我的測試中只有一個。

另外,我將如何使它,如果我點擊下拉內的鏈接,我可以強制菜單隱藏(這將是一個模式彈出窗口)。

中的application.js

$("ul.drop-down ul li a").click(function(e){ 
    $("ul.drop-down ul").hide(); 
    return; 
    }); 

加入這個現在感覺又非常unelegant和可能應該在其他地方放。請教育我!

回答

0

我會將菜單關閉操作綁定到$(window).click,然後在下拉菜單中單擊事件時添加e.stopPropogation()。這樣可以防止點擊從DOM樹進一步冒泡到窗口元素。

或者只是使用菜單的blur事件。認爲即使在非輸入元素上也可以工作。

+0

我不喜歡$(窗口)。點擊? – 2012-01-27 21:50:17

+0

爲了模糊工作,我需要菜單在呈現時接收焦點 - 如果它是通過單擊父項(幸運的是這裏是案例)打開它的作品。但它不是這樣在我的情況下,並試圖讓它專注於$(myitem).click()或.focusin()不適合我:-( – 2012-01-27 21:54:51

0

下面是一個例子:http://jsfiddle.net/5tgGq/1/。最重要的部分是在init

init: function(options) { 
     return this.each(function() { 
      var self = this; 
      $(this).click(methods.show); 
      $(document).click(function(e) { 
       if ($(self).has(e.target).length === 0) { 
        methods.hide.apply(self); 
       } 
      }); 
     }); 
    }, 

希望有所幫助。我敢肯定,你也應該確定多個元素,因爲你只使用showhide方法來處理已經編輯過的元素each

編輯:這裏是有兩個列表的例子:因爲當時什麼,如果一些其它部件也做e.stopPropagation()http://jsfiddle.net/5tgGq/3/