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

时间:2014-10-11 15:14:36

标签: javascript jquery jquery-isotope

编辑:我想我得到了解决方案!在我要求进一步的帮助之前,我想尝试自己解决这个问题=)

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

我尝试用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>

2 个答案:

答案 0 :(得分:1)

这并没有真正解决你的问题,但我喝咖啡时感到很无聊,感觉就像帮助你写下你的下拉插件更好一点

我在下面的评论与代码内联。有关不间断的代码,请参阅DropDown complete paste


我们从您的标准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;

现在我们将定义事件监听器和事件监听器可能依赖的函数。这里有什么好处,这些函数不必通过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;
});

无论如何,是的,我知道这对你的点击听众没有什么帮助,但我希望这对你来说仍然是有用的信息。现在去邮局!

答案 1 :(得分:0)

我认为你需要简化这一过程,以弄清楚发生了什么。实际上没有足够的信息来查看事件附加到这里的元素。

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

$(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将永远不会知道它已经发生了。显式或隐式(stopPropagation)调用return 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();
});