2014-01-25 139 views
9

我有一個包含2個事件的輸入元素:焦點和點擊。他們都開啓了相同的幫手功能。如何在焦點和點擊事件觸發時只運行一次函數

當我選項卡,輸入,焦點事件火災和我的助手被運行一次。那裏沒有問題。

當元素已具有焦點,我又點擊它,點擊事件火災和我的助手運行一次。那裏也沒有問題。

但當元素沒有焦點,和我點擊它,這兩項活動火了,我的幫手被運行兩次。我怎樣才能讓這個幫手只運行一次?

我看到這裏一對夫婦類似的問題,但並沒有真正按照自己的答案。我還發現了.live jQuery處理程序,看起來好像它可以工作,如果我有它看狀態類。但似乎應該有一個更簡單的方法。 .one處理程序可以工作,除非我需要這個工作不止一次。

感謝您的幫助!

回答

7

這裏最好的答案會拿出那是不是要觸發兩個不同的事件相同的行動,既可以在同一出現設計用戶行爲,但由於您沒有真正解釋您編碼的整體問題,因此我們無法真正幫助您做法。

一種方法是從觸發同樣的事情兩次保持一個單一的事件是「反跳」的函數調用,並只調用從給定元素的功能,如果它沒有被稱爲最近(例如,可能是從同用戶事件)。您可以通過記錄該元素的最後一次點火時間來完成此操作,並且只在時間長於某個值時才調用該函數。

這裏是你能做到這一點的一種方式:

function debounceMyFunction() { 
    var now = new Date().getTime(); 
    var prevTime = $(this).data("prevActionTime"); 
    $(this).data("prevActionTime", now); 
    // only call my function if we haven't just called it (within the last second) 
    if (!prevTime || now - prevTime > 1000) { 
     callMyFunction(); 
    } 
} 

$(elem).focus(debounceMyFunction).click(debounceMyFunction); 
+0

感謝您的回答。我想過檢查時間,但希望有一種更優雅的方式。儘管代碼示例非常感謝! – dylanized

+0

@dylanized - 我沒有辦法知道給定的點擊也只是觸發了焦點(作爲同一事件序列的一部分)而沒有查看時間。 – jfriend00

+0

@ jfriend00 - 焦點總是首先被調用。焦點總是首先的原因是它會觸發onmousedown,但點擊將要求mousedown和mouseup發生。 –

1

在我看來,你並不需要點擊處理程序。這聽起來像這個事件附加到一個元素,當點擊時獲得焦點並激發焦點處理程序。所以點擊它總是會激發你的焦點處理器,所以你只需要焦點處理器。

如果不是這種情況,那麼很遺憾沒有,有沒有簡單的方法來達到你的要求。添加/刪除焦點上的類,並且只在類不存在時觸發點擊是我能想到的唯一方法。

我有它 - 2個選項

1 - 綁定click處理程序的元素中的焦點回調

2 - 結合焦點和單擊處理程序不同的類,並使用對焦回調添加單擊類,並使用模糊刪除點擊類

+0

感謝您的回答。當輸入ALREADY具有焦點時,我需要該場景的點擊處理程序,但會獲得點擊第二/第三/第四的時間。 – dylanized

+0

我已經添加了一些代碼,你可以嘗試。 –

+0

@LiamBailey不會做任何事情,因爲它在點擊功能之前獲得焦點。 if語句毫無意義。 – m59

1

Live demo (click).

我只是簡單地將標誌設置成門關閉的點擊,當點擊的元素,也是第一次(焦點給出)。然後,如果元素通過Tab鍵獲得焦點,則該標誌也會被刪除,這樣第一次點擊就可以工作。

var $foo = $('#foo'); 

var flag = 0; 
$foo.click(function() { 
    if (flag) { 
    flag = 0; 
    return false; 
    } 
    console.log('clicked'); 
}); 

$foo.focus(function() { 
    flag = 1; 
    console.log('focused'); 
}); 

$(document).keyup(function(e) { 
    if (e.which === 9) { 
    var $focused = $('input:focus'); 
    if ($focused.is($foo)) { 
     flag = 0; 
    } 
    } 
}); 
+0

這不起作用的幾種方法。如果除了Tab鍵或點擊(例如自動對焦,程序焦點等)或者所有鍵都不允許傳播到文檔以外,其他方式設置了焦點。此外,由於此實現使用全局標誌,因此在多個地方使用時不易擴展。 – jfriend00

+0

@ jfriend00你知道這個全球旗幟並不是必要的,但對其餘部分來說很好。 – m59

1

你可以使用它得到真實清除和設置超時。這會引入輕微的延遲,但確保只有最後一個事件被觸發。

$(function() { 
    $('#field').on('click focus', function() { 
    debounce(function() { 
     // Your code goes here. 
     console.log('event'); 
    }); 
    }); 
}); 

var debounceTimeout; 

function debounce(callback) { 
    clearTimeout(debounceTimeout); 
    debounceTimeout = setTimeout(callback, 500); 
} 

這裏的小提琴http://jsfiddle.net/APEdu/

UPDATE

爲了解決其他地方關於使用全局的評論,你可以使doubleBounceTimeout超時與事件處理程序通過一鍵集合。或者您可以將相同的超時傳遞給處理同一事件的任何方法。這樣你可以使用相同的方法來處理任何數量的輸入。

3

這爲我工作:

http://jsfiddle.net/cjmemay/zN8Ns/1/

$('.button').on('mousedown', function(){ 
    $(this).data("mouseDown", true); 
}); 

$('.button').on('mouseup', function(){ 
    $(this).removeData("mouseDown"); 
}); 

$('.button').on('focus', function(){ 
    if (!$(this).data("mouseDown")) 
     $(this).trigger('click.click'); 
}); 

$(".button").on('click.click',evHandler); 

其中我直接從這個偷: https://stackoverflow.com/a/9440580/264498

+0

很好的解決方案。我假設這是有效的,因爲我們在焦點之前排列了mousedown?即如果我們把焦點放在mousedown之前,如果不行? – dylanized

+0

@dylanized我認爲這是可行的,因爲mousedown在點擊之前會聚焦。 mousedown,重點,mouseup。所以當事件是焦點時,它會檢查是否在元素上設置了mousedown標誌。 Tabbing和空格鍵在這裏並不真正起作用。也就是說,我認爲事件在代碼中註冊的順序並不重要,只是它們觸發的順序。 –

+0

我發現的唯一警告是,如果你對輸入進行了詳細的分析,然後離開,它不會清除標誌,打破焦點事件。我試圖在這裏解決這個問題,但這可能與您有關,具體取決於您的文檔結構,您的js以及它的用途: http://jsfiddle.net/cjmemay/zN8Ns/2/ –

0

感謝偉大的討論大家。似乎來自@ jfriend00的反彈解決方案以及Chris Meyers的mousedown解決方案都是處理它的好方法。

我想多一些,也想出了這個解決方案:

// add focus event 
$myInput.focus(function() { 
    myHelper(); 
    // while focus is active, add click event 
    setTimeout(function() { 
     $myInput.click(function() { 
      myHelper(); 
     }); 
    }, 500); // slight delay seems to be required 
}); 

// when we lose focus, unbind click event 
$myInput.blur(function() { 
    $myInput.off('click'); 
}); 

但好像與別人稍微更優雅。我特別喜歡克里斯,因爲它不涉及處理時間。

再次感謝!

+0

如果您打算使用超時,爲什麼不使用我的方法?不需要綁定和解除綁定。 – crad

+0

我同意你的方法更清潔。剛剛添加這個cuz,這似乎是一個可行的選擇。想想我會嘗試mousedown的方法,但如果這不起作用,將使用你的! – dylanized