语法:
YAHOO.util.Dom.isAncestor(haystack, needle)
YAHOO.util.Dom.inDocument(el)
YUI的源码里使用 haystack(草堆) 和 needle(针) 作为参数名,体现了YUI开发人员的幽默感。look for a needle in a haystack 正是大海捞针的意思。
isAncestor() 方法用来判断 haystack 元素是否是 needle 元素的父节点。它在鼠标参与的一些交互中非常有用。
我们都知道 mouseover 和 mouseout 事件,它们不方便之处在于,当鼠标在容器上滑动时,可能多次触发 mouseover 和 mouseout 事件,这增加了我们编码的复杂度。
IE支持mouseenter 和 mouseleave 事件,它们只在鼠标移到或移出容器时才触发。但其他浏览器并不支持这两个事件。但是,使用 inAncestor() 方法可以帮助我们模拟实现。看下面的例子:
//HTML 结构
<div id="demo-container">
<ul id="demo-ul">
<li id="child_1"><span><span><b><b>child 1</b></b></span></span></li>
<li id="child_2"><span><span><b><b>child 2</b></b></span></span></li>
<li id="child_3"><span><span><b><b>child 3</b></b></span></span></li>
</ul>
</div>
<div id="msg"></div>
//JS
$E.onDOMReady(function() {
var container = $('demo-container');
var msgbox = $('msg');
//模拟 mouseenter 事件
var mouseEnterHandler = function(ev) {
//relatedTarget 在mouseover事件中指向鼠标从该处移过来的元素
var rt = $E.getRelatedTarget(ev);
//如果rt 不是container本身,同时也不是container的子元素,那么就是 Enter 的情况
if (rt !== container && !$D.isAncestor(container, rt)) {
msgbox.innerHTML += 'Entering ...';
}
msgbox.innerHTML += 'Mouse Over ...';
}
//模拟 mouseleave 事件
var mouseLeaveHandler = function(ev) {
msgbox.innerHTML += 'Mouse Out ...';
//relatedTarget 在mouseout事件中指向鼠标移动到的元素
var rt = $E.getRelatedTarget(ev);
//如果rt 不是container本身,同时也不是container的子元素,那么就是 Leave 的情况
if (rt !== container && !$D.isAncestor(container, rt)) {
msgbox.innerHTML += 'Leaving ...';
}
}
$E.on(container, 'mouseover', mouseEnterHandler);
$E.on(container, 'mouseout', mouseLeaveHandler);
});
TBra 中的TB.widget.SimplePopup 组件正是采用了上例中的实现。
isAncestor() 方法还衍生 inDocument() 方法,该方法用来判断一个元素是否存在于DOM树中,其实它就是简单的调用 isAncestor() 方法,看它的源码:
/**
* Determines whether an HTMLElement is present in the current document.
* @method inDocument
* @param {String | HTMLElement} el The element to search for
* @return {Boolean} Whether or not the element is present in the current document
*/
inDocument: function(el) {
return this.isAncestor(document.documentElement, el);
},

