Say I have the following HTML:
<div>
<span>span text</span> div text <span>some more text</span>
</div>
I want to make it so that when I click on span, it will trigger some event (e开发者_如何学C.g. to make the text bold), that's easy:
$('span').click( ... )
But now I when I click away from the element, I want another event to trigger (e.g. to make the text normal weight). I need to detect, somehow, a click not inside the span element. This is very similar to the blur() event, but for non INPUT elements. I don't mind if this click is only detected inside the DIV element and not the entire BODY of the page, btw.
I tried to get an event to trigger in non-SPAN elements with the following:
$('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
Another solution would be to read the event's target inside the click event. Here's an example of implementing it this way:
$('div').click(function(e) {
if (e.target.nodeName != "span")
...
});
I was wondering if there was a more elegant solution like blur() though.
From what I've researched, I think the stopPropagation function is most appropriate. For example:
$("#something_clickable a").click(function(e) {
e.stopPropagation();
})
See How do I prevent a parent's onclick event from firing when a child anchor is clicked? for a similar question.
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).
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;
}
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.
$(':not(span)').click(function(){
//dostuff
})
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
.
精彩评论