2017-08-29 162 views
1

這可能是一個愚蠢的問題。我知道我有點綠。 我的任務是修改這個舊的舊系統的導航。有兩個導航欄。第二個只有搜索按鈕。我被要求刪除第二個導航欄,並用顯示搜索功能的下拉菜單替換它。由於這個系統的時代,我受限於我可以改變的東西。我可以編寫的JS沒有任何限制。他們在Adobe ColdFusion系統上運行jQuery 1.11.1(兩個月前他們從1.3.2升級)多個同時發生的事件javascript

第一:當單擊目標時,mouseenter和click事件都會觸發。鼠標首先發射。這會在敏銳觀看者看到的桌面上產生問題,但在移動設備上會產生可怕的可用性問題。答:從我的理解中,鼠標事件不會發生在移動設備上,而是爲我執行。而B:由於mouseenter事件先運行,它會在處理click事件之前激活closeDropDown函數。在closeDropDown運行時,其.on('click', f(...eventstuff...))會聽到用於觸發openDropDown函數的打開單擊,因此下拉不會打開。

以下是功能。 console.log用於檢查什麼時候運行。

function openDropDown(){ 
    $('div.dropdown').parent().on('click.open mouseenter', function(event){ 

     $subject = $(this).find('.dropdown-menu') 
     // console.log(event.type, $subject, "first o"); 

     if(!$subject.is(":visible")){ 
      // console.log($subject, 'second o'); 

      $subject.show() 
     }else { 
     if(event.type == 'click'){ 
      // console.log('third o'); 

      $subject.toggle() 
     } 
    } 

    closeDropDown($subject) 
    // console.log('open complete'); 
}) 
} 


function closeDropDown($x){ 
    // console.log('first c'); 

    $(document).on("click.close",function(e){ 
     // console.log("second c", e.type, "this type"); 

     if(!$(e.target).closest(".dropdown-menu").parent().length){ 
      // console.log("third c"); 

      if($x.is(":visible")){ 
       // console.log('forth c'); 
       $x.hide() 
      } 
     } 

     $(document).off("click.close") 
     // console.log('complete close'); 
    }) 
} 

openDropDown() 
onSearchClick() 

我看了幾個帖子,希望一些幫助(如thisthat

總體而言,我知道我需要凝聚我的代碼。我知道一些方法來解決這個問題(添加if(... are we on a mobile device...)或者一些計數器/檢查防止closeDropDown運行時,下拉關閉)

我真的想其他的東西之前持斧瞭解事件偵聽器的基本原理和原因。

雖然關於如何解決這個問題的建議很好,但我期待了解我做錯的基本原理。任何基本指針都非常有幫助。

值得注意的是:我剛纔讀到這個:.is(':visible') not working。我將用.is('visible')重寫代碼。

其他可能有所幫助的事情: 當我的所有console.log處於活動狀態時,這是Chrome開發工具控制檯。 首先,點擊頁面加載.... enter image description here 下拉打開並快速關閉。

第二次點擊.... enter image description here

謝謝!所有的幫助表示讚賞!

回答

1

這是一個相當廣泛的問題。我會盡量簡潔。我不認爲ColdFusion應該在這裏被標記,因爲它似乎只與HTML/CSS/JS有關。

配置事件

首先,我想解決您配置了腳本的方式。 您可能會從查看事件處理examples from jquery中受益。

大多數人會創建類似以下的事件。它只是說,點擊任何ID爲「警報器」的文檔元素,運行警報功能。

// Method 1 
$(document).on(click, "#alerter", function(event){ 
    alert("Hi!"); 
}); 

OR

// Method 2 
$(document).on("click", "#alerter", ClickAlerter); 

function ClickAlerter(event) { 
    alert("Hi!"); 
} 

這兩種方法是完全有效的。然而,這是我的意見第二種方法更具可讀性和可維護性。它將事件委託與邏輯分開。

對於您的代碼,我強烈建議刪除事件分配和邏輯的混合。 (它至少移除一層嵌套)。

順便說一下,您的事件偵聽器似乎沒有正確配置。請參閱the correct syntax以及jQuery中的這個示例。

$("#dataTable tbody").on("click", "tr", function() { 
    console.log($(this).text()); 
}); 

有關多個活動

如果你有一個對象上的多個事件偵聽器,那麼他們將在其註冊的順序發射。 This SO question已經涵蓋了這一點,並提供了一個例子。

但是,這並不意味着在鼠標輸入前會發生點擊。由於鼠標必須逐字輸入元素才能點擊,因此mouseenter的事件將首先被觸發。換句話說,在思考事件的順序時,至少有兩個因素在起作用。

  1. 在瀏覽器將觸發事件
  2. 它們被註冊

因爲這樣的訂單的訂貨,確實沒有這樣的事情「同時」事件,本身。瀏覽器想要觸發事件時會觸發事件,並且它們將按照您分配的順序遍歷事件並激發匹配。

如果您想更改默認事件行爲,則對於這些類型的事件,您始終可以選擇preventDefaultstopPropagation。這將停止瀏覽器的默認操作,並防止事件分別冒泡到父元素。

關於移動鼠標事件

鼠標事件在移動設備完全發生,這不是安全的假設他們不這樣做。 This article非常深入地涵蓋了被解僱的事件的範圍。引述:

「[Y] OU具有設計更先進的觸摸交互時要小心:當用戶使用鼠標將通過單擊事件作出迴應,但是當用戶觸摸屏幕觸摸和點擊。事件發生對於單次點擊的事件順序是:

touchstart 
touchmove 
touchend 
mouseover 
mousemove 
mousedown 
mouseup 
click 

我認爲你會從閱讀這篇文章受益它涵蓋關於移動和非移動環境事件共同的問題和概念。同樣,你的處境相關聲明:

有趣的是,雖然,CSS:懸停僞類可以在某些情況下,觸摸界面被觸發 - 竊聽的元素使它:活躍在手指下降,它還獲取:懸停狀態。 (使用Internet Explorer的:懸停只是效果,而用戶的手指下跌 - 其他瀏覽器保持:懸停在直到下一次點擊或鼠標移動的效果。)

一個例子

我將所有這些概念和made an example on jsFiddle向您展示了其中一些實際操作。基本上,我通過偵聽touchstart事件並在這種情況下以不同的方式處理click來檢測用戶是否在使用觸摸屏。因爲我沒有HTML,所以我不得不建立一個基本的接口。這些都是指令:

  1. 我們需要確定用戶是否具有觸摸屏
  2. 當用戶在按鈕上徘徊,菜單應該會出現
  3. 在移動設備上,當用戶水龍頭按鈕,菜單應該會出現
  4. 我們需要當用戶點擊該按鈕
  5. 離開按鈕應該關閉菜單(移動或以其他方式)外,關閉菜單

正如你所看到的,我創造了我的所有事件在同一個地方:

$(document).on("mouseover", "#open", $app.mouseOver); 
$(document).on("mouseout", "#open", $app.mouseOut); 
$(document).on("click", "#open", $app.click); 
$(document).on("touchstart", $app.handleTouch); 
$(document).on("touchstart", "#open", $app.click); 

我還創建這給了我們更大的靈活性和可讀性的道路對象來包裝所有的邏輯,$app 。下面是它的一個片段:

var $app = $app || {}; 
$app = { 

    hasTouchScreen: false, 

    handleTouch:function(e){ 
    // fires on the touchstart event 
    $app.hasTouchScreen = true; 
    $("#hasTouchScreen").html("true"); 
    $(document).off("touchstart", $app.handleTouch);  
    }, 

    click: function(e) { 
    // fires when a click event occurrs on the button 
    if ($app.hasTouchScreen) { 
     e.stopPropagation(); 
     e.preventDefault(); 
     return; 
    } 

    // since we don't have a touchscreen, close on click. 
    $app.toggleMenu(true); 
    }, 

    touch: function(e) { 
    // fires when a touchstart event occurs on the button 
    if ($("#menu").hasClass("showing")) { 
     $app.toggleMenu(true); 
    } else { 
     $app.toggleMenu(); 
    }  
    } 

}; 
相關問題