레이블을 클릭하면 jQuery Click이 두 번 실행됩니다.


114

jQuery를 사용하여 사용자 지정 라디오 버튼을 만들고 있는데 문제가 있습니다. 라디오와 관련된 레이블을 클릭하면 클릭 이벤트가 두 번 실행되고 라디오 자체 만 클릭하면 제대로 작동합니다 (실제로 클릭하는 라디오가 아니라 전체 입력 및 레이블을 래핑하는 div). 다음은 코드입니다.

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>

이 동작에 대한 해결책이 있습니까?

답변:


130

추가해보십시오 :

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

.bind () 또는 .click ()에 표시됩니다. 또한 evt함수에 매개 변수 를 추가합니다.function(evt) {...


9
왜 이런 일이 발생합니까?
chovy

8
중첩 된 항목이 있기 때문입니다. 계층 구조의 각 항목은 이벤트를 표시합니다.
Jordan

7
당신이 확인란이를 사용하는 경우,이 또한 실제로 확인하기 위해 입력을 가능하게 나를 위해 필요했다 :jQuery('input').prop('checked', true);
데이비드 싱클레어

6
return false;`evt.stopPropagation (); evt.preventDefault (); ( jQuery )
basil

193

다음을 추가하여 위의 솔루션을 추가해 보았습니다.

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

하지만 작동하지 않았습니다. 그러나 이것을 추가 :

evt.stopImmediatePropagation();

문제를 해결했습니다! :)


6
왜 그런지 모르겠지만 당신이 말한 것은 내 코드에서 작동하는 것처럼 보입니다. 감사합니다!
shaosh apr

8
완전한. 이것은 잘 작동했습니다! 비록 evt.stopPropagation(); evt.preventDefault();didn를, 't
James111

1
오직이 나를 위해 일했다, 나는 성공없이 다른 기능을 시도했다
gardarvalur

1
이 대답은 내 생명을 구했습니다! 감사합니다 : D
Bluetree

1
이것이 제 답이었습니다!
Dyluck

73

클릭 이벤트를 레이블이 아닌 입력에 바인딩하십시오. 레이블을 클릭 할 때-Dustin이 언급했듯이 레이블을 클릭하면 입력에 대한 클릭이 트리거되기 때문에 이벤트가 계속 발생합니다. 이렇게하면 레이블이 정상적인 기능을 유지할 수 있습니다.

$('input').click();

대신에

$('label').click();

10
이 솔루션은 당신의 마크 업이 label-wrapping-the-input 기술을 사용하는 경우에도 작동합니다. 그리고 방금 제 정신을 구했습니다. : o)
Whelkaholism

4
change라벨의 텍스트를 클릭 할 수 있기 때문에 실제로 라디오 버튼에도 바인딩해야 합니다. 항상 라디오 버튼 자체를 클릭하지는 않습니다.
chovy

2
Bootstrapesque label > input설정을 사용하는 경우 이것은 대답이 아니라 대답입니다. 추가 evt.stopPropagation()하거나 evt.preventDefault(), 코드에 효과적인 반면, 적절한 솔루션이 훨씬 깨끗하고 더 효율적이 때 피해야 해킹입니다.
elPastor

와우 단지 와우 와우, 내가 마지막이 도움이 감사를 설명하기위한 많은 연구 만 거의 며칠을 보냈다
오픈 소스 - 개발자

이것은 내 하루를 구했습니다!
gab06

11

외부 컨테이너를 클릭 요소로 사용하려는 경우 이벤트가 자연스럽게 버블 링되도록하고 클릭 핸들러에서 예상되는 요소를 테스트 할 수도 있습니다. 이 시나리오는 양식에 대해 고유 한 클릭 영역의 스타일을 지정하려는 경우 유용합니다.

<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

1
이렇게하면 자녀를 선택할 수 없습니다. BTW, 동일한 기능을 달성하기위한 더 나은 옵션은 다음과 같습니다if (e.target == e.currentTarget) {}
Chicken Soup

9

이 문제를 쉽게 해결하려면 레이블에서 "for"속성을 제거하십시오. 라벨을 클릭하면 관련 요소도 클릭됩니다. (귀하의 경우 클릭 이벤트를 두 번 실행합니다.)

행운을 빕니다


실제로 빠른 솔루션입니다. 마크 업을 엉망으로 만든다고 주장 할 수도 있지만 "for"속성의 목적이 이벤트 전파라고 반박합니다. 따라서 다른 메커니즘 (jquery)을 사용하는 경우 반드시 "for"를 제거하십시오.
Chris Harrington 2014 년

5

저는 보통이 신텍스를 사용합니다

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

대신에

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

5

댓글 안에 베스트 답변이 숨겨져 있습니다.

change라벨의 텍스트를 클릭 할 수 있기 때문에 실제로 라디오 버튼에도 바인딩해야 합니다. 항상 라디오 버튼 자체를 클릭하지는 않습니다. - chovy 1시 45분에서 12월 12일 '13

바이올린은 - 다른 모든 솔루션 것으로 보여 stopPropagation, stopImmediatePropagation, preventDefault, return false- 변경 아무것도 또는 중 하나)이 체크 박스 / 라디오 기능을 파괴하지 않습니다. 또한 이것이 jQuery 문제가 아니라 바닐라 JavaScript 문제임을 보여줍니다.

편집 : 방금 다른 스레드에서 찾은 또 다른 작업 솔루션 onclick은 레이블이 아닌 입력 에 바인딩하는 것입니다. 업데이트 된 바이올린 .


2

솔루션을 추가하여 시도했습니다.

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

하지만 작동하지 않았습니다.

추가하여

evt.stopImmediatePropagation();

문제를 해결했습니다! :)


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

1
이 솔루션은 코드에서 사용자가 라디오 버튼을 선택 취소 할 수 있도록 허용하는 경우에도 작동하지 않습니다. 이 경우 이중 화재로 인해 심각한 문제가 발생합니다.
Johncl

1

내 문제는 조금 다릅니다.는 evt.stopPropagation();evt.preventDefault();나를 위해 작동하지 않기 return false;때문에 결국 추가 하면 작동합니다.

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

1

제 경우 문제는 함수에 클릭 이벤트가 있고 함수가 두 번 실행되었다는 것입니다 . 함수를 실행할 때마다 새로운 클릭 이벤트가 생성됩니다. - 안면 손바닥 -

클릭 이벤트를 함수 외부로 이동 한 후 모든 것이 예상대로 작동했습니다! :)


0

레이블 태그는 클릭을 에뮬레이트하므로 항상 둘 이상의 호출이 발생하므로 트리거 요소 외부에 입력 태그를 넣으십시오.


0

radio_div에 연결된 핸들러를 사용하여 이와 같이 레이블 내부에 라디오를 중첩했기 때문에 동일한 문제가 발생했습니다. 중첩 된 레이블을 제거하면 문제가 해결되었습니다.

<div id="radio_div">
    <label>
       <input type="radio" class="community_radio" name="community_radio" value="existing">
           Add To Existing Community
    </label>
</div>

0

레이블은 확인할 라디오 / 체크 박스를 트리거합니다.

if ($(event.target).is('label')){
    event.preventDefault();
}

특히 레이블이이 동작을 트리거하는 것을 방지합니다.


0

for = "some-id" 속성이 있는 레이블을 클릭하면 새 클릭이 트리거되지만 대상이 존재하고 입력 인 경우에만 해당됩니다. I이었다 하지 e.preventDefault () 또는 물건을 완벽하게 해결할 수 같은 것을, 나는 다음과 같이했다 그래서 :

예를 들어이 구조가 있고 .some-class를 클릭 할 때 이벤트가 필요한 경우

<div class="some-class">
    <input type=checkbox" id="the-input-id" />
    <label for="the-input-id">Label</label>
</div>

작업은 다음과 같습니다.

$(document)
    .on('click', '.some-class', function(e) {
        if(
            $(e.target).is('label[for]')
            &&
            $('input#' + $(e.target).attr('for')).length
        ) {
            // This will trigger a new click so we are out of here
            return;
        }

        // else do your thing here, it will not get called twice
    })
;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.