Question

Why doesn't this work? The label is inside the .item parent. I don't want to put it outside of block elements as it wouldn't be valid.

So I'm trying to simulate a label click:

$(".item").click(function(){
    $(this).find("label").click();
});

Edit: It's supposed to trigger the label and check a radio.

<script type="text/javascript">
    $(document).ready(function () {
        $(".item").click(function() {
            $(this).find("label").click();
        });
    }); 
</script>


<div class="item">
    <h4>Item</h4>
    <ul>                
        <li>Description</li>
    </ul>
     <div class="radio-container">
        <div class="radio-stack">
            <input type="radio" class="styled" id="item1">
        </div>
        <label for="item1">$100</label>
    </div>
</div>
Was it helpful?

Solution

Since this label is attached to some input (using the for attribute), you could try something like:

var inputID = $(this).find("label").attr("for");
$('#' + inputID).click();

However you should be careful: since your input is inside the div with the .item class, simulating a click in the radio will trigger your custom handler again, causing an infinite loop. If possible, just set the radio checked attribute to true instead of simulating a click:

$('#' + inputID).attr("checked",true);

(Working example at jsFiddle)

Otherwise, you'll need to find a way to exclude that radio from the .item selector to avoid that infinite loop.

Update: after struggling a little with not selectors, unsuccessfully, I came up with a quick and dirty hack: use a global (to the ready closure) variable to control whether or not a simulated click is happening:

var updating = false;
$(".item").click(function() {
    if ( !updating ) {
        var inputID = $(this).find("label").attr("for");
        updating = true;
        $('#' + inputID).click();
        updating = false;
    }
});

Working example here. IMO Ayman Safadi's answer is better, but if you have trouble making it work cross-browsers this alternative could be used as a starting point.

OTHER TIPS

To strictly answer your question, it's not working because it's causing an infinite loop of "clicks", and your browser just kills the event silently.

Run this demo, and look at your JS console: http://jsfiddle.net/bRyR3/

The div is capturing the label click event. In other words, JavaScript interprets your logic like this:

When you click on .item, trigger the label "click" event.

label is inside .item, therefore if label is clicked, so is .item.

When you click on .item, trigger the label "click" event.

label is inside .item, therefore if label is clicked, so is .item.

When you click on .item, trigger the label "click" event.

label is inside .item, therefore if label is clicked, so is .item.

etc...

Working on actual solution.


Solution

$('.item').on('click', function(e) {
    console.log('click');
    $('label', $(this)).trigger('click');
});

$('.item label').on('click', function(e) {
    e.stopPropagation();
});

​ This will stop .item from capturing label's click event.

Working demo: http://jsfiddle.net/bRyR3/1/

Since this question & answer pops up when looking for a solution, there is a third way to solve this issue:

JQuery allows for custom parameters to be sent to the on() event handlers, by using trigger()

See https://api.jquery.com/trigger/

This means, it's possible to avoid an endless loop by simply telling the event handler that the current event is 'artificial':

$( document ).on( 'click touch', '.item', function( event, artificial ) {
     if( artificial ) return;
     
     $(this).find("label").trigger( 'click', [ true ] );
} );

This has the advantage of not stopping propagation (or relying on it), while also not fumbling around with different input types (checkboxes, radios, texts, etc). It just simulates a click on the label without any additional work on our side or any endless loops.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top