jQuery custom events example
"Cowboy" Ben Alman http://benalman.com/news/2010/02/jquery-custom-events/
by Ben Alman
HTML
<!--
jQuery Custom Events - "Cowboy" Ben Alman
http://benalman.com/news/2010/02/jquery-custom-events/
-->
<h1>Custom events example</h1>
<div id="error"></div>
<div class="widget" id="widget_a">
<div class="widget-head">
<h2>Widget A</h2>
<a href="#" class="close">X</a>
</div>
<div class="widget-body">
<p>
This is sample widget A. It can be removed without constraints.
</p>
</div>
</div>
<div class="widget" id="widget_b">
<div class="widget-head">
<h2>Widget B</h2>
<a href="#" class="close">X</a>
</div>
<div class="widget-body">
<p>
This is sample widget B. It cannot be removed unless its checkbox is checked.
</p>
</div>
<div class="widget-footer">
<label>
<input type="checkbox" name="can_remove" value="1">
Allow widget removal?
</label>
</div>
</div>
<div class="widget" id="widget_c">
<div class="widget-head">
<h2>Widget C</h2>
<a href="#" class="close">X</a>
</div>
<div class="widget-body">
<p>
This is sample widget C. It cannot be removed unless all preceding widgets have also been removed.
</p>
</div>
</div>
<div id="admin_control">
<h2>Widget admin control</h2>
<p><a href="#" class="widget_a_remove">Remove widget A</a></p>
<p><a href="#" class="widget_b_remove">Remove widget B</a></p>
<p><a href="#" class="widget_c_remove">Remove widget C</a></p>
</div>
CSS
body {
font-size: 80%;
font-family: Arial, Helvetica, sans-serif;
}
h1, h2 {
font-weight: 700;
font-family: "Gill Sans", "Gill Sans MT", Arial, Helvetica, sans-serif;
}
h1 {
color: #C4884F;
font-size: 150%;
margin-bottom: 0.6em;
}
h2 {
font-size: 120%;
font-weight: 700;
}
#error {
display: none;
color: #c00;
border: 2px solid #c00;
background: #fcc;
padding: 0.5em;
position: absolute;
top: 5px;
left: 10px;
right: 10px;
z-index: 100;
}
.widget {
border: 2px solid #C4884F;
background: #FDEBDC;
margin-bottom: 0.6em;
position: relative;
}
.widget .close {
position: absolute;
top: 0.2em;
right: 0.5em;
line-height: 0.9em;
padding: 0.1em;
font-weight: 700;
color: #C4884F;
background: #FDEBDC;
border: 1px solid #C4884F;
text-decoration: none;
}
.widget .close:hover {
color: #fff;
background: #f00;
border-color: #fff;
}
.widget-head {
padding: 0.2em 0.5em;
color: #fff;
background: #C4884F;
}
.widget-body {
padding: 0.5em 0.5em;
}
.widget-footer {
padding: 0.2em 0.5em;
border-top: 1px solid #C4884F;
}
#admin_control {
margin-top: 2em;
}
#admin_control h2 {
margin-bottom: 0.6em;
}
JavaScript
// Bind a default handler for the custom "remove" event, to display error messages.
var message_id;
$(document).bind( 'remove', function(event){
var message = 'Widget could not be removed, ' + event.error_message;
// Show the error message.
$('#error').stop( true ).text( message )
removeAttr( 'style' ).fadeIn( 'fast' );
// Fade error message out after 2 seconds.
message_id && clearTimeout( message_id );
message_id = setTimeout(function(){
$('#error').fadeOut( 'fast' );
}, 2000 );
});
// Bind widget A's custom "remove" event.
$('#widget_a').bind( 'remove', function(event){
// Remove widget A from the DOM.
$(this).remove();
// Stop the event from bubbling up the DOM tree.
event.stopPropagation();
});
// Bind widget B's custom "remove" event.
$('#widget_b').bind( 'remove', function(event){
var can_remove = $(this).find('input[name=can_remove]:checked').length;
if ( !can_remove ) {
event.error_message = 'removal checkbox must be checked first.'
} else {
// Remove widget A from the DOM.
$(this).remove();
// Stop the event from bubbling up the DOM tree.
event.stopPropagation();
}
});
// Bind widget C's custom "remove" event.
$('#widget_c').bind( 'remove', function(event){
var can_remove = $(this).prevAll('.widget').length === 0;
if ( !can_remove ) {
event.error_message = 'all preceding widgets must be closed first.'
} else {
// Remove widget A from the DOM.
$(this).remove();
// Stop the event from bubbling up the DOM tree.
event.stopPropagation();
}
});
// When a widget 'X' close link is clicked, trigger the
// 'remove' event for that widget.
$('.widget .close').bind( 'click', function(event){
$(this).closest('.widget').trigger('remove');
});
// Admin control logic. Nice and dumb, the way we like it.
$('#admin_control').each(function(){
...