Вы захотите привязать слушателя событий к телу и проверить элемент, на который нажали, чтобы увидеть, является ли он .selected_li
, или одним из его потомков :
$('body').mouseup(function(e) {
if ($(e.target).closest('.selected_li').length == 0) {
// de-select
}
});
Настоящий трюк здесь использует .closest(".selected_li")
, потому что он обязательно включает случаи, когда вы находитесь над потомком ".selected_li".
Использование .is(".selected_li")
не будет работать, если ваш список выглядит такчто-нибудь вроде этого:
<ul>
<li>Item 1</li>
<li class="selected_li"><i>Item 2</i></li>
<li>Item 3</li>
</ul>
Если вы отпустите кнопку мыши, когда над Item 2 , event.target
будет элементом <i>
, а не <li>
, поэтому .is(".selected_li")
вернет false.Таким образом, мы должны увидеть, является ли цель события или любой из его предков ".selected_li"
, выполнив поиск с помощью .closest()
и проверив, получили ли мы совпадение.
Редактировать: Используя .delegate()
здесь не очень хорошая идея.Это свяжет обработчик события с каждым элементом-потомком <body>
, что очень избыточно, так как событие всегда будет пузыриться до <body>
в любом случае, и вам нужно будет сделать это только один раз.Тем не менее, возможно , но вы должны убедиться, что исключили достаточно - вам нужно исключить ".selected_li" и всех его потомков и всех его предков:
$("body").delegate(":not(.selected_li, .selected_li *, :has(.selected_li))", "mouseup", function(e) {
// de-select
});
Но это приведет к тому, что обработчик событий будет вызываться несколько раз за клик.Если вы отпустите кнопку мыши над следующим абзацем, вы запустите обработчик событий 5 раз.Один раз для каждого из <em>
, <p>
, <div class="section">
, <div id="content">
, <div id="wrapper">
.
<body>
<div id="wrapper">
<div id="content">
<div class="section">
<p><em>Here is a paragraph</em></p>
</div>
</div>
</div>
</body>
Итак, просто привязайте один раз к телу, чтобы обработчик событий вызывался только один раз длянажмите.