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