2011-11-23 132 views
89

我正在使用jQuery創建自定義單選按鈕,並且出現問題。 當點擊與無線電相關的標籤時,點擊事件觸發兩次,如果我只點擊收音機本身,它工作正常(實際上它不是我點擊的收音機,而是包裝整個輸入和標籤的div)。下面是代碼:jQuery單擊標籤時點擊兩次點擊

的HTML:

<div id="box"> 
    <asp:RadioButtonList ID="RadioButtonList1" runat="server"> 
     <asp:ListItem>RADIO1</asp:ListItem> 
     <asp:ListItem>RADIO2</asp:ListItem> 
     <asp:ListItem>RADIO3</asp:ListItem> 
    </asp:RadioButtonList> 
</div> 

的jQuery:

<script type="text/javascript"> 
     $(function() { 
      $('#box').find('input:radio').each(function (i) { 

      var input = $(this); 
      // get the associated label using the input's id 
      var label = $('label[for=' + input.attr('id') + ']'); 
      // wrap the input + label in a div 
      $('<div class="custom-radio"></div>').insertBefore(input).append(label, input); 

      var wrapperDiv = input.parent(); 

      // find all inputs in this set using the shared name attribute 
      var allInputs = $('input[name=' + input.attr('name') + ']'); 

      // necessary for browsers that don't support the :hover pseudo class on labels 
      label.hover(

      function() { 
       $(this).addClass('hover'); 
      }, function() { 
       $(this).removeClass('hover checkedHover'); 
      }); 

      //bind custom event, trigger it, bind click,focus,blur events 
      wrapperDiv.bind('updateState', function() { 
       if ($(this)[0].children[1].checked) { 
        allInputs.each(function() { 
         var curDiv = $('div > label[for=' + $(this).attr('id') + ']').parent(); 
         curDiv.removeClass('custom-radio-checked'); 
         curDiv.addClass('custom-radio'); 
        }); 
        $(this).toggleClass('custom-radio custom-radio-checked'); 
       } 
       else { 
        $(this).removeClass('custom-radio-checked checkedHover checkedFocus'); 
       } 

      }) 
      .trigger('updateState') 
      .click(function() { console.log('click'); }) 
      .focus(function() { 
       label.addClass('focus'); 
      }).blur(function() { 
       label.removeClass('focus checkedFocus'); 
      }); 
     }); 
     }); 
    </script> 

是否有此行爲的任何解決方案?

回答

101

嘗試增加:

evt.stopPropagation(); 
evt.preventDefault(); 

到.bind()或。點擊(),無論你看到的。另外,將參數evt添加到該函數中,如function(evt) {...

+4

爲什麼會發生這種情況? – chovy

+5

因爲有嵌套的項目。層次結構中的每個項目都會引發事件。 – Jordan

+4

如果你使用它作爲一個複選框,這也是我需要使輸入實際上被檢查:'jQuery('input')。prop('checked',true);' –

8

要解決此問題,請移除標籤上的「for」屬性。點擊標籤也會觸發關聯元素的點擊。 (在你的情況下被解僱點擊事件的兩倍。)

好運

+0

的確是快速解決方案。有人可能會爭辯說,它與標記混亂,但我反駁說,「for」屬性的目的是事件傳播。所以,如果你正在使用另一種機制(jQuery),那麼通過一切手段擺脫「for」。 –

50

綁定click事件的輸入,而不是標籤。當標籤被點擊時 - 事件仍然會發生,因爲,正如達斯汀所說,點擊標籤會觸發輸入點擊。這將允許標籤保持其正常功能。

$('input').click(); 

代替

$('label').click(); 
+6

如果您的標記使用標籤包裝輸入技術,並且只保存了我的理智:o) – Whelkaholism

+2

即使在單選按鈕上,您實際上也應該綁定到「更改」,因爲標籤的文本是可點擊的 - - 他們並不總是單擊單選按鈕本身。 – chovy

+0

如果使用Bootstrapesque'label>輸入'設置,這是答案,而不是答案。將'evt.stopPropagation()'或'evt.preventDefault()'添加到您的代碼中雖然有效,但是當適當的解決方案更清晰和更高效時應該避免這種攻擊。 – pshep123

1

e.preventDefault的問題();是否停止檢查單選按鈕的標籤點擊。

更好的解決方案是簡單地增加一個「被選中」快速檢查,像這樣:

$("label").click(function(e){ 
    var rbtn = $(this).find("input"); 
    if(rbtn.is(':checked')){ 
    **All the code you want to have happen on click** 
    } 
)}; 
+1

一個更簡潔的解決方案就是使用.mouseup而不是.click – yoshyosh

+0

如果您的代碼也將允許用戶取消選擇單選按鈕,則此解決方案不起作用。雙火在這種情況下造成嚴重的麻煩。 – Johncl

9

如果你想使用外部容器作爲掣子元件也可以讓事件冒泡自然並在您的點擊處理程序中測試預期的元素。如果您嘗試爲窗體設置獨特的點擊區域,此場景很有用。

<form> 
<div id="outer"> 
    <label for="mycheckbox">My Checkbox</label> 
    <input type="checkbox" name="mycheckbox" id="mycheckbox" value="on"/> 
</div> 
</form> 
<script> 
$('#outer').on('click', function(e){ 
    // this fires for #outer, label, and input 
    if (e.target.tagName == 'INPUT'){ 
     // only interested in input 
     console.log(this); 
    } 
}); 
</script> 
+1

這對我有用,因爲我仍然希望單選按鈕被選中。我只是不希望事件處理程序對所有事情做兩次。 – chovy

141

我試圖通過增加將上面的解決方案:

evt.stopPropagation(); 
evt.preventDefault(); 

,但沒有奏效。不過加了這個:

evt.stopImmediatePropagation(); 

解決了這個問題!:)

+6

我不知道爲什麼,但你說的話看起來像我的代碼工作。謝謝! – shaosh

+6

完美。這工作得很好!雖然'evt.stopPropagation(); evt.preventDefault();'didn;'t – James111

+1

我只添加了'e.preventDefault();'工作。 – vipin8169

2

我通常使用這個synthax

.off('click').on('click', function() { console.log('click'); }) 

,而不是

.click(function() { console.log('click'); }) 
0

嘗試把觸發要素之外您輸入的標籤,因爲標籤標記模擬點擊,這樣你纔會有永遠不止一個呼叫。

-2

只是想在這裏編鐘,我在WordPress WooCommerce中使用WooCombinator,它使用鏈接看起來像按鈕變化選擇,而不是默認變化下拉選擇器。我想在選定的特定變體上執行一些JQuery代碼,並且這裏的許多答案並沒有停止冒泡效果。

Yoshyosh的嘗試使用mouseup而不是點擊作品的評論像一個魅力,我不敢相信我沒有想到它!謝謝yoshyosh!

+1

這個問題的答案是什麼意思? –

+0

由於這裏的許多解決方案並不適合我,我想提請注意yoshyosh的解決方案,該解決方案未作爲答案發布,而是作爲對另一個答案的評論。你在那裏有點粗魯,夥計。 – CollinHell

1

我的問題有點不同,因爲evt.stopPropagation();evt.preventDefault();不適用於我,我只是最後添加return false;,然後它的工作。

$("#addressDiv").on("click", ".goEditAddress", function(event) { 
    alert("halo"); 
    return false; 
}); 
0

在我的情況下,問題是,我在功能有click事件,並執行函數兩次 ....功能的每次執行創建一個新的單擊事件。 - facepalm -

在將函數外部的click事件移出之後,所有事情都按預期工作! :)