简体   繁体   English

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

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

Edit: I think I got the solution! 编辑:我想我已经解决了! I want to try and fix this myself before I ask for further help = ) 我想尝试自己解决此问题,然后再寻求更多帮助=)

First script inhibits the second one from functioning as the click event from the first one overides the second one. 第一个脚本禁止第二个脚本用作第一个脚本的单击事件,从而覆盖第二个脚本。 Because the second one does not function it is impossible to open the drop down menu to select a list item to trigger the first scripts click. 由于第二个脚本不起作用,因此无法打开下拉菜单以选择列表项来触发第一个脚本单击。

What I tried was replacing all return false statements with event.stopPropagation(). 我试图用event.stopPropagation()替换所有返回的false语句。 Didnt work however. 但是没有工作。 Tried re-ordering my scripts but that failed as well. 尝试重新排序我的脚本,但是也失败了。 I was thinking of making my second script target another parent div but that didnt work either.I also tried event.stopImmediatePropagation() and .bind methods. 我当时想让我的第二个脚本针对另一个父div,但这也没有用。我还尝试了event.stopImmediatePropagation()和.bind方法。

Any idea? 任何想法?

First script that makes the drop down function. 第一个执行下拉功能的脚本。 Contains click event. 包含点击事件。

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

    });

Second script that does the filtering, also contains click event: 第二个脚本进行过滤,还包含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 structure 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>

This doesn't really solve your problem but I was bored while drinking my coffee and felt like helping you write your dropdown plugin a little nicer 这并不能真正解决您的问题,但是我在喝咖啡时很无聊,感觉就像是在帮助您更好地编写下拉插件

My comments below are inline with code. 我在下面的评论与代码一致。 For uninterrupted code, see DropDown complete paste . 有关不间断的代码,请参见DropDown完整粘贴


We start with your standard jQuery wrapper (function($){ ... })(jQuery) 我们从您的标准jQuery包装器开始(function($){ ... })(jQuery)

(function($) {

  // dropdown constructor
  function DropDown($elem) {

First we'll make some private vars to store information. 首先,我们将创建一些私有变量来存储信息。 By using this.foo = ... we expose things (probably) unnecessarily. 通过使用this.foo = ...我们(可能)不必要地暴露了事物。 If you need access to these vars, you can always create functions to read them. 如果您需要访问这些变量,则始终可以创建函数来读取它们。 This is much better encapsulation imo. 这是更好的封装imo。

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

Now we'll define our event listeners and functions those event listeners might depend on. 现在,我们将定义事件监听器以及这些事件监听器可能依赖的功能。 What's nice here is that these functions don't have to access everything via this.* or as you were writing obj.f.* etc. 这里的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);
    }

Here's some property descriptors to read the index and value 这是一些属性描述符,用于读取indexvalue

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

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

Lastly, let's track each instance of DropDown in an array so that the user doesn't have to define a special listener to deactivate each 最后,让我们跟踪数组中每个DropDown实例,以便用户不必定义特殊的侦听器即可停用每个

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

This is the array we'll use to track instances 这是我们用来跟踪实例的数组

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

This event listener deactivate each "registered" instance of DropDown 此事件侦听器停用DropDown的每个“已注册”实例

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

Here's the document listener defined right in the plugin! 这是插件中定义的文档监听器! The user no longer has to set this up 用户不再需要设置它

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

Might as well make it a jQuery plugin since everything in our DropDown constructor relies upon jQuery. 最好将其设为jQuery插件,因为DropDown构造函数中的所有内容都依赖jQuery。 This let's the user do var x = $("foo").dropdown(); 这让用户执行var x = $("foo").dropdown();

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

Close the wrapper 关闭包装纸

})(jQuery);

Now here's how you use it 现在这是你的用法

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

  // get the value
  f.value;

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

Anyway, yeah I know this doesn't really help you with your click listeners, but I hope this is still useful information to you. 不管怎样,是的,我知道这对您的点击侦听器并没有真正帮助,但是我希望这对您仍然有用。 Off to the Post Office now! 现在去邮局!

I think you're going to need to simplify this to figure out what's going on. 我认为您将需要简化此过程以弄清楚发生了什么。 There's actually not enough information to see what elements the events are being attached to here. 实际上,没有足够的信息来查看事件在此处附加的元素。

For argument's sake, open the console and try the following: 为了论证,打开控制台并尝试以下操作:

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

Then click in the page. 然后单击页面。 You'll see that both events are triggered. 您会看到两个事件都被触发。 It might well be that your code is actually attaching the events to different elements (you don't say anywhere). 很有可能您的代码实际上是将事件附加到不同的元素上(您在任何地方都没有说)。 If that's the case then you need to understand how event bubbling works in the DOM. 如果真是这样,那么您需要了解事件冒泡在DOM中的工作方式。

When you trigger an event, say a click on an element, that event will fire on that element, and then on it's parent, then grandparent etc all the way to the root node at the top. 当您触发事件时,例如单击某个元素,则该事件将在该元素上触发,然后在其父元素上触发,然后在祖父母,外祖父母等一直指向顶部的根节点。

You can change this behaviour by calling functions in the event itself. 您可以通过在事件本身中调用函数来更改此行为。 evt.stopPropagation tells the event to not bubble up to the ancestor nodes. evt.stopPropagation告诉事件不冒泡到祖先节点。 evt.preventDefault tells the browser not to carry out the default behaviour for a node (eg, moving to the page specified in the href for an A tag). evt.preventDefault告诉浏览器不要对节点执行默认行为(例如,移动到href中为A标签指定的页面)。

In jQuery, return false from an event handler is a shortcut for, evt.preventDefault and evt.stopPropagation . 在jQuery中,从事件处理程序return falseevt.preventDefaultevt.stopPropagation的快捷方式。 So that will stop the event dead in its tracks. 这样一来,事件就不会停止。

I imagine you have something like: 我想你有这样的事情:

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

If the thing that handles event_one_on_here calls stopPropagation then event_two_on_here will never even know it has happened. 如果处理event_one_on_here的事物调用stopPropagation则event_two_on_here甚至都不会知道它已发生。 Calling stopPropagation explicitly, or implicitly ( return false ) will kill the event before it travels to the parent node/event handler. 显式或隐式调用stopPropagationreturn false )将在事件传播到父节点/事件处理程序之前终止该事件。

UPDATE: In your case the issue is that the handler on .filter-buttons a is stopping the propagation (so #f doesn't get to run its handler). 更新:在您的情况下,问题是.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