繁体   English   中英

单击来自同一元素上两个脚本的事件?

[英]Click events from two scripts on same element?

编辑:我想我已经解决了! 我想尝试自己解决此问题,然后再寻求更多帮助=)

第一个脚本禁止第二个脚本用作第一个脚本的单击事件,从而覆盖第二个脚本。 由于第二个脚本不起作用,因此无法打开下拉菜单以选择列表项来触发第一个脚本单击。

我试图用event.stopPropagation()替换所有返回的false语句。 但是没有工作。 尝试重新排序我的脚本,但是也失败了。 我当时想让我的第二个脚本针对另一个父div,但这也没有用。我还尝试了event.stopImmediatePropagation()和.bind方法。

任何想法?

第一个执行下拉功能的脚本。 包含点击事件。

    function DropDown(el) {
        this.f = el;
        this.placeholder = this.f.children('span');
        this.opts = this.f.find('ul.dropdown > li');
        this.val = '';
        this.index = -1;
        this.initEvents();
    }
    DropDown.prototype = {
        initEvents : function() {
            var obj = this;

            obj.f.on('click', function(event){
                $(this).toggleClass('active');
                return false;
            });

            obj.opts.on('click',function(){
                var opt = $(this);
                obj.val = opt.text();
                obj.index = opt.index();
                obj.placeholder.text(obj.val);
            });
        },
        getValue : function() {
            return this.val;
        },
        getIndex : function() {
            return this.index;
        }
    }

    $(function() {

        var f = new DropDown( $('#f') );

        $(document).click(function() {
            // all dropdowns
            $('.filter-buttons').removeClass('active');
        });

    });

第二个脚本进行过滤,还包含click事件:

jQuery(document).ready(function(e) {
    var t = $(".filter-container");
    t.imagesLoaded(function() {
        t.isotope({
            itemSelector: "figure",
            filter: "*",
            resizable: false,
            animationEngine: "jquery"
        })
    });
    $(".filter-buttons a").click(function(evt) {
  var n = $(this).parents(".filter-buttons");
        n.find(".selected").removeClass("selected");
        $(this).addClass("selected");
        var r = $(this).attr("data-filter");
        t.isotope({
            filter: r
        });
    evt.preventDefault();
});
    $(window).resize(function() {
        var n = $(window).width();
        t.isotope("reLayout")
    }).trigger("resize")
});

html结构

<div id="f" class="filter-buttons" tabindex="1">
                    <span>Choose Genre</span>
                    <ul class="dropdown">
                        <li><a href="#" data-filter="*" class="selected">All</a></li>
                        <li><a href="#" data-filter=".electronic">Electronic</a></li>
                        <li><a href="#" data-filter=".popular">Popular</a></a></li>
                    </ul>
                </div>

这并不能真正解决您的问题,但是我在喝咖啡时很无聊,感觉就像是在帮助您更好地编写下拉插件

我在下面的评论与代码一致。 有关不间断的代码,请参见DropDown完整粘贴


我们从您的标准jQuery包装器开始(function($){ ... })(jQuery)

(function($) {

  // dropdown constructor
  function DropDown($elem) {

首先,我们将创建一些私有变量来存储信息。 通过使用this.foo = ...我们(可能)不必要地暴露了事物。 如果您需要访问这些变量,则始终可以创建函数来读取它们。 这是更好的封装imo。

    // private vars
    var $placeholder = $elem.children("span");
    var $opts    = $elem.find("ul.dropdown > li")
    var value    = "";
    var index    = -1;

现在,我们将定义事件监听器以及这些事件监听器可能依赖的功能。 这里的obj.f.*是,这些函数不必通过this.*或在编写obj.f.*等时访问所有内容。

    // private functions
    function onParentClick(event) {
      $elem.toggleClass("active");
      event.preventDefault();
    }

    function onChildClick(event) {
      setValue($(this));
      event.preventDefault();
    }

    function setValue($opt) {
      value = $opt.text();
      index = $opt.index();
      $placeholder.text(value);
    }

这是一些属性描述符,用于读取indexvalue

    // properties for reading .index and .value
    Object.defineProperty(this, "value", {
      get: function() { return value; }
    });

    Object.defineProperty(this, "index", {
      get: function() { return index; }
    });

最后,让我们跟踪数组中每个DropDown实例,以便用户不必定义特殊的侦听器即可停用每个

    // track each instance of
    DropDown._instances.push(this);
  }

这是我们用来跟踪实例的数组

  // store all instances in array
  DropDown._instances = [];

此事件侦听器停用DropDown的每个“已注册”实例

  // deactivate all
  DropDown.deactiveAll = function deactiveAll(event) {
    $.each(DropDown._instances, function(idx, $elem) {
      $elem.removeClass("active");
    });
  }

这是插件中定义的文档监听器! 用户不再需要设置它

  // listener to deactiveAll dropdowns
  $(document).click(DropDown.deactiveAll);

最好将其设为jQuery插件,因为DropDown构造函数中的所有内容都依赖jQuery。 这让用户执行var x = $("foo").dropdown();

  // jQuery plugin
  $.fn.dropdown = function dropdown() {
    return new DropDown($(this));
  };

关闭包装纸

})(jQuery);

现在这是你的用法

$(function() {
  var x = $('#f').dropdown();

  // get the value
  f.value;

  // get the index
  f.index;
});

不管怎样,是的,我知道这对您的点击侦听器并没有真正帮助,但是我希望这对您仍然有用。 现在去邮局!

我认为您将需要简化此过程以弄清楚发生了什么。 实际上,没有足够的信息来查看事件在此处附加的元素。

为了论证,打开控制台并尝试以下操作:

$(document).on('click', function() { console.log('first'); return false; });
$(document).on('click', function() { console.log('second'); return false; });

然后单击页面。 您会看到两个事件都被触发。 很有可能您的代码实际上是将事件附加到不同的元素上(您在任何地方都没有说)。 如果真是这样,那么您需要了解事件冒泡在DOM中的工作方式。

当您触发事件时,例如单击某个元素,则该事件将在该元素上触发,然后在其父元素上触发,然后在祖父母,外祖父母等一直指向顶部的根节点。

您可以通过在事件本身中调用函数来更改此行为。 evt.stopPropagation告诉事件不冒泡到祖先节点。 evt.preventDefault告诉浏览器不要对节点执行默认行为(例如,移动到href中为A标签指定的页面)。

在jQuery中,从事件处理程序return falseevt.preventDefaultevt.stopPropagation的快捷方式。 这样一来,事件就不会停止。

我想你有这样的事情:

<div event_two_on_here>
    <a event_one_on_here>
</div>

如果处理event_one_on_here的事物调用stopPropagation则event_two_on_here甚至都不会知道它已发生。 显式或隐式调用stopPropagationreturn false )将在事件传播到父节点/事件处理程序之前终止该事件。

更新:在您的情况下,问题是.filter-buttons a上的处理程序正在停止传播(因此#f无法运行其处理程序)。

$(".filter-buttons a").click(function(evt) {
    // your code here...

    // Don't do this - it stops the event from bubbling up to the #f div
    // return false;

    // instead, you'll probably just want to prevent the browser default
    // behaviour so it doesn't jump to the top of the page ('url/#')
    evt.preventDefault();
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM