jQuery 插件创作,点击事件帮助(下拉菜单)

发布于 2024-10-16 20:10:33 字数 3071 浏览 1 评论 0原文

我正在尝试以插件方式创建一个下拉菜单。我熟悉自己编写解决方案的脚本,但我以前从未创建过插件,因此我正在尝试学习如何执行此操作,从而提高我作为 jQuery 开发人员的水平。

我正在尝试创建基本的下拉功能。你有一个链接。单击它,会出现一个链接下拉菜单。您单击链接(文档)外部,链接菜单就会消失。

我在离开的部分遇到了麻烦。我尝试将其绑定到 document.click 但当然会显示菜单然后隐藏它,因为没有什么可以确保它必须首先显示。我该怎么做?

如何使菜单仅在您单击菜单外部时显示后才隐藏?

application.jssilly_drop_down.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');
  // });
});

编辑

(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;
  });

再次感觉,非常不优雅,可能应该放在其他地方。请赐教!

I'm trying to create a drop-down menu in a plugin manner. I'm familiar with scripting myself to solutions but I've never created a plugin before so I'm trying to learn how to do this, and therefore raising my level as a jQuery developer.

I'm trying to create basic drop down functionality. You have a link. You click it, a drop down of links appear. You click outside of the link (the document) the menu of links goes away.

I'm having trouble on the go away part. I tried to bind it to document.click but of course that shows the menu and then hides it, as there is nothing making sure it has to be shown first. How do I do this?

How do I make it so that the menu only hides after it is shown if you click outside of it?

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);

the html if it matters

<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>

edit (I realized I asked similar question in past).
I did the following in 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;
    }
  });

This does the job. However it doesn't seem elegant to do it in application.js - How would I handle this inside the plugin?

Note: I'll probably have multiple instances of ul.drop-down - Am I missing something in my implementation to take care of this? So far only have one in my tests.

Also, how would I make it so that if I click a link inside the drop down I can force the menu to hide (this would be a modal popup for example).

added this for now in application.js

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

Feels again, very unelegant and should probably be put somewhere else. Educate me please!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

装迷糊 2024-10-23 20:10:33

我会将菜单关闭操作绑定到 $(window).click,然后在下拉列表自己的点击事件中添加 e.stopPropogation()。这可以防止点击在 DOM 树中进一步向上冒泡到窗口元素。

或者只使用菜单的 blur 事件。认为这甚至适用于非输入元素。

I would bind the menu close action to $(window).click, then in the dropdown's own click event add e.stopPropogation(). That prevents the click from bubbling further up the DOM tree to the window element.

Or just use the menu's blur event. Think that'd work even on non-input elements.

梦在深巷 2024-10-23 20:10:33

这是一个示例: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);
                }
            });
        });
    },

希望有帮助。我很确定您也应该可以接受多个元素,因为您只对已经 eachshowhide 方法代码>编辑。

编辑:这是一个包含两个列表的示例: http://jsfiddle.net/5tgGq/3/

Here's an example: http://jsfiddle.net/5tgGq/1/. The important part is in 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);
                }
            });
        });
    },

Hope that helps. I'm pretty sure you should be ok with multiple elements as well, since you're only using the show and hide methods for elements you already eached.

EDIT: here's an example with two lists: http://jsfiddle.net/5tgGq/3/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文