Reputation: 1959
I have a collection of span
elements. In the code I have a global variable that represents the "selected" object. Using the click
event when a span
is clicked I reset the object's class, reset the global variable, then set the object to the variable and change its class (to make it "highlighted"). This effectively toggles selection when clicking an object.
var currentItem = null;
$( ".item" ).click( function() {
if( $( this ).hasClass( "selected" ) ) {
$( this ).removeClass( "selected" )
currentItem = null;
} else {
if( $( ".item" ).hasClass( "selected" ) ){
$( ".item" ).removeClass( "selected" )
}
$( this ).addClass( "selected" );
currentItem = $( this );
}
} );
What I'd like to be able to do is unselect when clicking on an empty area of the page. I tried creating a click event on the body
object, but that overrode the span
click event so nothing was selected. I'm a complete jQuery noob and not sure where to go with this.
Upvotes: 1
Views: 4912
Reputation: 886
Too much code, we can do it easier:
"use strict";
/*global $*/
$(function () {
$('html').live('click', function (e) {
$('.item.selected').removeClass('selected');
var $t = $(e.target);
if ($t.hasClass('item')) {
$t.addClass('selected');
}
});
});
Using 'html' to bind event is better due body can be not 100% height, for example. And clicking on empty area return not expected result.
We do not need global object, as this script guarantees that we have only one selected span and we can refer to it with:
$('.item.selected');
Upvotes: 0
Reputation: 322492
Your idea to place the click event on the body
is fine.
You just need to be aware that clicking on any descendants of body
will cause the click event to bubble up to body
, and fire that handler.
You need to stop that propagation in your span
event handler.
$( ".item" ).click( function(event) {
event.stopPropagation();
...
jQuery Docs
event.stopPropagation()
http://api.jquery.com/event.stopPropagation/
EDIT:
Another valid alternative would be to simply return false at the end of the handler.
$( ".item" ).click( function() {
// Your code...
return false;
});
Upvotes: 2
Reputation: 630409
Use event.stopPropagation()
in your current handler so that click
doesn't bubble up to the <body>
, triggering it's handler as well, then your approach works, like this:
var currentItem = null;
$(".item").click(function(e) {
if($(this).hasClass("selected")) {
$(this).removeClass("selected")
currentItem = null;
} else {
$(".item.selected").removeClass("selected");
currentItem = $(this).addClass("selected");
}
e.stopPropagation();
});
$(document).click(function() {
$(".item.selected").removeClass("selected");
});
You can view a demo here, one suggestion though, if only one element can be selected
do you need to keep track of it? If lookup cost isn't a factor, you could aways find the currentItem
by doing $(".item.selected")
, simplifying this code quite a bit. I'm not sure how you're using currentItem
, just an option you have :)
Upvotes: 7
Reputation: 338208
You don't necessarily need a global variable since your DOM holds that state info, too.
// de-select old selection and select new item
$(".item").click( function(evt) {
$(".item.selected").removeClass("selected");
$(this).addClass("selected");
evt.stopPropagation();
});
// de-select everything
$("body").click( function() {
$(".item.selected").removeClass("selected");
});
// your currently selected element can be retrieved by this anytime:
$(".item.selected")[0]
Not tracking state twice (in the DOM and in a global variable) spares you two headaches:
Upvotes: 1
Reputation: 19098
In addition to the answers stated (unless I missed this), you needn't attach the click() event to the body when the page loads -- you can simply do it after the item is selected. Not that it hurts since you're stopping propagation, but in my view its more "correct" to only activate/set an event handler for the duration in which it is relevant.
Upvotes: 0
Reputation: 3823
Create a click on the html element $("html")
and return it as false whenever you do what you need to do. The body could not extend the whole page if you're doing some sizing with CSS with it. Here's an example:
$("html").click( function(e) {
e.stopPropagation()
});
Edit
Yeah. forgot about stopPropagation()
. Changed code to read that. Should still use the html element as the listener, however.
Upvotes: 0
Reputation: 195992
You did well setting a click event on the body
. BUt you must also tell the span click event to stop the propagation of the event..
$( ".item" ).click( function(event) {
event.stopPropagation();
//your code
});
Upvotes: 5