jQuery special events

Custom clickoutside event: delegation only http://benalman.com/news/2010/03/jquery-special-events/

by bizamajig

HTML

<h1>
    <a href="http://benalman.com/news/2010/03/jquery-special-events/" target="_top">jQuery special events</a>
    &raquo; Custom clickoutside event: delegation only
</h1>

<p class="intro">(click boxes, non-boxes, whatever)</p>

<div id="test">
    <div id="a">
        a
        <div id="b">
            b
            <div id="c">c</div>
            <div id="d">d</div>
        </div>
    </div>
</div>

<div id="nav">
    <a href="#">add / remove #e element</a>
</div>

<div id="log"></div>

CSS

body { font-family: Arial, Helvetica, sans-serif; font-size: 0.8em; }
h1 { font-weight: 700; font-family: "Gill Sans", "Gill Sans MT", Arial, Helvetica, sans-serif; }
h1, a { color: #913D00; }
a:hover { color: #FF7F00; }
h1 { font-size: 120%; margin-bottom: 0.6em; }
.intro { font-style: italic; margin-top: 0.5em; }

#test div {
    border: 1px solid #000;
    margin: 1em 0;
    padding: 0.5em 1em;
}

#a, #b, #e {
    padding-bottom: 0 !important;
}

#log {
    margin-top: 1em;
}

JavaScript

$(function(){
    function log(){
        $('#log').append([].join.call(arguments,', ')+'<br/>');
    };
    
    // Clear the log on click.
    $(document).bind( 'click', function(){ $('#log').empty(); });
    
    // This should fire first.
    $('#test').delegate( 'div', 'clickoutside', function(event){
        var clicked = event.clicked;
        
        log( '1. delegate',
            'clickoutside: #' + event.target.id,
            '(clicked: ' + (clicked.id ? '#' + clicked.id : clicked.tagName) + ')' );
        
        //event.stopPropagation(); // Un-comment to stop propagation (which stops "live" handlers as well).
        //event.stopImmediatePropagation(); // Un-comment to stop immediate propagation.
    });
    
    // This should fire second.
    $('#test').delegate( 'div', 'clickoutside', function(event){
        log( '2. delegate' );
        
        //event.stopImmediatePropagation(); // Un-comment to stop immediate propagation.
    });
    
    // This should fire third.
    $('#test div').live( 'clickoutside', function(event){
        var clicked = event.clicked;
        
        log( '3. live',
            'clickoutside: #' + event.target.id,
            '(clicked: ' + (clicked.id ? '#' + clicked.id : clicked.tagName) + ')' );
        
        //event.stopImmediatePropagation(); // Un-comment to stop immediate propagation.
    });
    
    // This should fire fourth.
    $('#test div').live( 'clickoutside', function(event){
        log( '4. live' );
    });
    
    // Un-comment either of these lines to un-bind event handlers:
    
    //$('#test div').die( 'clickoutside' );
    //$('#test').undelegate( 'div', 'clickoutside' );
    
    // This is just for the "add/remove" link.
    $('a').click(function(){
        var e = $('#e');
        if ( e.length ) {
            e.remove();
        } else {
            $('<div id="e">e<div id="f">f</div><div id="g">g</div></div>').appendTo('#a');
        }
        return false;
   ...