7

假设我有以下 HTML:

<div>
  <span>span text</span> div text <span>some more text</span>
</div>

我想这样做,以便当我单击 span 时,它会触发一些事件(例如,使文本变粗),这很容易:

$('span').click( ... )

但是现在当我点击离开元素时,我想要触发另一个事件(例如,使文本正常重量)。我需要以某种方式检测不在 span 元素内的点击。这与 blur() 事件非常相似,但适用于非 INPUT 元素。我不介意是否仅在 DIV 元素内部检测到此点击,而不是在页面的整个 BODY 中检测到,顺便说一句。

我尝试使用以下内容在非 SPAN 元素中触发事件:

$('div').click( ... ) // triggers in the span element
$('div').not('span').click( ... ) // still triggers in the span element
$('div').add('span').click( ... ) // triggers first from span, then div

另一种解决方案是在点击事件中读取事件的目标。这是以这种方式实现它的示例:

$('div').click(function(e) {
  if (e.target.nodeName != "span")
     ...
});

我想知道是否有像 blur() 这样更优雅的解决方案。

4

6 回答 6

4

根据我的研究,我认为stopPropagation函数是最合适的。例如:

$("#something_clickable a").click(function(e) {
   e.stopPropagation();
})

请参阅如何防止在单击子锚点时触发父级的 onclick 事件?对于类似的问题。

于 2011-12-29T04:50:22.103 回答
3

Your last method should work best even if it's messy. Here's a little refinement:

$('span').click(function() {
    var span = $(this);
    // Mark the span active somehow (you could use .data() instead)
    span.addClass('span-active');

    $('div').click(function(e) {
        // If the click was not inside the active span
        if(!$(e.target).hasClass('span-active')) {
            span.removeClass('span-active');
            // Remove the bind as it will be bound again on the next span click
            $('div').unbind('click');
        }
    });
});

It's not clean, but it should work. No unnecessary binds and this should be foolproof (no false positives etc).

于 2010-01-13T21:27:24.513 回答
1

I came up with a solution to this problem before jQuery was released...

Determine if any Other Outside Element was Clicked with Javascript

document.onclick = function() {
  if(clickedOutsideElement('divTest'))
    alert('Outside the element!');
  else
    alert('Inside the element!');
}

function clickedOutsideElement(elemId) {
  var theElem = getEventTarget(window.event);

  while(theElem != null) {
    if(theElem.id == elemId)
      return false;

    theElem = theElem.offsetParent;
  }

  return true;
}

function getEventTarget(evt) {
  var targ = (evt.target) ? evt.target : evt.srcElement;

  if(targ != null) {
    if(targ.nodeType == 3)
      targ = targ.parentNode;
  }

  return targ;
}
于 2010-01-13T21:25:29.337 回答
1

If you return false from your click handler for the span you'll prevent the event from bubbling, which will keep the div click handler from running.

于 2010-01-13T21:26:04.037 回答
0
$(':not(span)').click(function(){
    //dostuff
})
于 2010-01-13T21:24:58.107 回答
0

Using the tabIndex property, you can actually make arbitrary elements focusable:

var node = document.createElement("span");
node.tabIndex = -1;

node.addEventListener("focus", function () {
    // clicked the element...
}, true);

node.addEventListener("blur", function () {
    // clicked away from the element...
}, true);

Unfortunately, this example probably won't work in IE. I haven't tested it myself, so it might!

Also, a tabIndex of -1 means the element can be clicked on, but can't be focused with the keyboard. You can change it to 0 if you want it to be focusable with Tab or Shift+Tab.

于 2010-10-11T05:01:09.537 回答