如果一个元素被包含在另一个元素中,如何检查Javascript
如何检查一个DOM元素是否是另一个DOM元素的子元素? 有没有内置的方法呢? 例如,像这样的东西:
if (element1.hasDescendant(element2))
要么
if (element2.hasParent(element1))
如果不是那么任何想法如何做到这一点? 它还需要跨浏览器。 我还应该提到,孩子可以嵌套在父母的许多层次上。
使用parentNode
属性应该可以工作。 从跨浏览器的angular度来看,这也是非常安全的。 如果知道这个关系是一个深层次的话,你可以简单地检查一下:
if (element2.parentNode == element1) { ... }
如果孩子可以在父母的任意深处嵌套,则可以使用类似于以下的函数来testing关系:
function isDescendant(parent, child) { var node = child.parentNode; while (node != null) { if (node == parent) { return true; } node = node.parentNode; } return false; }
你应该使用Node.contains
,因为它现在是标准的,并在所有浏览器中可用。
https://developer.mozilla.org/en-US/docs/Web/API/Node.contains
我只是不得不分享“我的”。
虽然在概念上与Asaph的答案相同(从相同的跨浏览器兼容性(即使是IE6)中受益),但它的体积要小得多,而且在尺寸非常大和/或不经常需要的情况下也会派上用场。
function childOf(/*child node*/c, /*parent node*/p){ //returns boolean while((c=c.parentNode)&&c!==p); return !!c; }
或单行( 只有64个字符 ):
function childOf(c,p){while((c=c.parentNode)&&c!==p);return !!c}
和jsfiddle在这里 。
用法:
childOf(child, parent)
返回布尔值true
| false
。
说明:
while
只要条件评估为true
进行评估。
&&
(AND)运算符在评估左侧和右侧后返回此布尔值true / false,但仅在左侧为true ( left-hand && right-hand
)时才返回。
( &&
)的左边是(c=c.parentNode)
。
这将首先将c
的parentNode
赋值给c
,然后AND运算符将计算结果c
作为布尔值。
由于parentNode
在没有父节点的情况下返回null
,并且null
被转换为false
,所以当没有父节点时,while循环将正确停止。
( &&
)的右边是: c!==p
。
!==
比较运算符“ 不完全等于”。 所以如果孩子的父母不是父母(你指定),它的计算结果为true
,但如果孩子的父母是父母,则计算结果为false
。
因此, 如果 c!==p
计算结果为false,那么&&
运算符将返回false
作为while-condition和while循环停止。 (注意,不需要while-body和closing ;
分号是必需的。)
所以当while循环结束的时候, c
是一个节点(不是null
),当它find一个父节点或者它是null
(当循环运行到最后而没有find匹配的时候)。
因此,我们简单地return
这个事实(转换为布尔值,而不是节点): return !!c;
: !
( NOT
运算符)颠倒布尔值( true
变为false
,反之亦然)。
!c
将c
(节点或null)转换为布尔值,然后才可以反转该值。 所以再加一个!
( !!c
)将这个虚假的返回值转换为true(这就是为什么double !!
经常被用来将任何东西转换为布尔值的原因)。
额外:
函数的主体/有效载荷非常小,根据情况(例如,当它不经常使用并且在代码中只出现一次),甚至可以省略函数(包装),并使用while循环:
var a=document.getElementById('child'), b=document.getElementById('parent'), c; c=a; while((c=c.parentNode)&&c!==b); //c=!!c; if(!!c){ //`if(c)` if `c=!!c;` was used after while-loop above //do stuff }
代替:
var a=document.getElementById('child'), b=document.getElementById('parent'), c; function childOf(c,p){while((c=c.parentNode)&&c!==p);return !!c} c=childOf(a, b); if(c){ //do stuff }
看看Node#compareDocumentPosition 。
function isDescendant(ancestor,descendant){ return ancestor.compareDocumentPosition(descendant) & Node.DOCUMENT_POSITION_CONTAINS; } function isAncestor(descendant,ancestor){ return descendant.compareDocumentPosition(ancestor) & Node.DOCUMENT_POSITION_CONTAINED_BY; }
其他关系包括DOCUMENT_POSITION_DISCONNECTED
, DOCUMENT_POSITION_PRECEDING
和DOCUMENT_POSITION_FOLLOWING
。
IE不支持<= 8。
另一个没有提到的解决scheme是:
示例在这里
var parent = document.querySelector('.parent'); if (parent.querySelector('.child') !== null) { // .. it's a child }
元素是否是直接的孩子并不重要,它可以在任何深度工作。
或者,使用.contains()
方法 :
示例在这里
var parent = document.querySelector('.parent'), child = document.querySelector('.child'); if (parent.contains(child)) { // .. it's a child }
您可以使用包含方法
var result = parent.contains(child);
或者你可以尝试使用compareDocumentPosition()
var result = nodeA.compareDocumentPosition(nodeB);
最后一个更强大:它返回一个位掩码结果。
我在网上看到一段精彩的代码,检查一个元素是否是其他元素的子元素。 我不得不使用这个,因为IE不支持java脚本的“.contains”。 希望这也能帮助其他人。
以下是function: –
function isChildOf(ChildObject,ContainerObject) { var retval=false; var curobj; if(typeof(ContainerObject)=="string") { ContainerObject=document.getElementById(ContainerObject); } if(typeof(ChildObject)=="string") { ChildObject=document.getElementById(ChildObject); } curobj=ChildObject.parentNode; while(curobj!=undefined) { if(curobj==document.body) { break; } if(curobj.id==ContainerObject.id) { retval =true; break; } curobj=curobj.parentNode;//move up the hierarchy } return retval; }