开发者

Deselecting an element in jQuery

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 t开发者_如何学Gohis.


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 :)


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
});


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;
});


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:

  • carefully updating the global variable all the time
  • bugs that arise of "global" state getting out of sync with "DOM" state


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.


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.


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'); 

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜