First, preface
In the Polyfill queryselectorall and write pop-up windows need to determine the position between the two nodes, through jquery we can easily fix, but native JS? Below I will collate various judgment methods for future reference.
Ii. relations between our grandchildren
Html
<div id="ancestor"> <div id="parent"> <div id="son">son</div> </div></div><div id=" Other">other</div>
Common.js
var ancestor = document.getElementById ('ancestor'); var parent = document.getElementById ('parent '); var son = document.getElementById ('son'); var other = document.getElementById ('other');
Method One: Through the Selection object
/** Define and determine the relationship function * @param {htmlelement} parentnode * @param {htmlelement} sonnode*/varhas =function (parentnode, Sonnode) {
if (parentnode = = = Sonnode) return true;
varSelection =window.getselection (); Selection.selectallchildren (parentnode); varret = Selection.containsnode (Sonnode,false); returnret; };//calledConsole.log (Has (ancestor, son));//Display TrueConsole.log (Have (ancestor, other));//Show False
Cons: Only FF support, other browsers are not valid
1. When executing selection.selectallchildren (parentnode) , the content of parentnode will be highlighted and the original highlighted part will be canceled;
2. Under Chrome, Selection.containsnode () constant returns false ;
3. The selection type object under Ie9~11 has no Containsnode method;
4. There is no selection type under ie5.5~8;
About the [object Selection] and [object msselection] types under IE (More on JS Magic Hall: Detailing Selection and msselection types)
1. IE11 only [object Selection] Type
Access method: document.getselection () or window.getselection ()
2. ie9~10 There are two types of [object Msselection] and [object Selection]
Get [Object Msselection]: document.selection
Get [Object Selection]: document.getselection () and window.getselection ()
3. IE5.5~IE8 only [object Msselection] Type
Get way: document.selection
Note: Document.selection is a unique attribute of IE.
method Two: Through the Range object
var has = function (ParentNode, Sonnode) {
if (parentnode = = = Sonnode) return true;
var r1 = Document.createrange (), R2 = Document.createrange (); R1.selectnode (parentnode); R2.selectnode (Sonnode); var startret = r1.compareboundarypoints (Range.start_to_start, R2); var endret = R1.compareboundarypoints ( Range.end_to_end, r2); var ret = Startret = =-1 & & endret = = = 1 return ret;};
Cons: Incompatible ie5.5~8 (supported by ie9+, FF, and Chrome)
1. Ie5.5~8 no document.createrange () method
About [Object Range], [object TextRange], and [object Controlrange] Types
The first thing to be clear is that [object Range] is standard, whereas [object TextRange] and [object Controlrange] are unique to ie.
(Details of "JS Magic Hall: Detailed range, TextRange and Controlrange type")
1. Creating [Object Range] objects with Document.createrange ()
2. Get the [object Range] Object by Window.getselection (). Getrangeat ({unsigned int32} index)
3. Get the [object TextRange] object through the Document.selection.createRange () or Document.selection.createRangeCollection () method and cannot be directly bound to a DOM fragment by the Selectnode method like the Range object content.
Method Three: Through the Contains method
var has = function (parentnode, sonnode) { return parentnode.contains (Sonnode); };
Console.log (Has (ancestor, ancestor));//Returns True
Console.log (Has (ancestor, son));//Returns True
Console.log (Have (ancestor, other));//return False
Advantages : Simple and direct
cons : compatibility issues
Support--chrome, firefox9+, ie5+, opera9.64+ (estimated from 9.0+), safari5.1.7+
--FF not supported
Method Four: Through the Comparedocumentposition method
var has = function (parentnode, Sonnode) {
if (parentnode = = = Sonnode) return true;
var rawret = parentnode.comparedocumentposition (sonnode); var (+ ) ; return ret; };
Comparedocumentposition can be regarded as a big tool to compare the two node position relationship in the standard, not only can judge the relationship between grandchildren, but also can judge other relations OH
var ret = a.comparedocumentposition (B);
The return value of RET means the following:
Bits number Meaning
000000 0 Elements Consistent
000001 1 nodes in different documents (or one outside of the document)
000010 2 node B before node A
000100 4 node A before node B
001000 8 node B contains node A
010000 16 node A contains node B
100000 32 Private use of the browser
Method Five: Recursive traversal
var has = function (ParentNode, Sonnode) {
if (parentnode = = = Sonnode) return true;
var P = Sonnode.parentnode; if (! return false Span style= "color: #000000;" >; else if (P!== ParentNode) { return has (ParentNode, p) ; else { return true ; }}
Pros : All browsers are common
cons : When the node level is deep, the efficiency is low.
Integrated programme I, from Masaki (http://m.cnblogs.com/57731/1583523.html?full=1):
//2013.1.24 by Masaki
function contains (Parentel, El, container) {//whether the first node has a second node//contains method support situation: Chrome+ firefox9+ ie5+, opera9.64+ (estimated from 9.0+), safari5.1.7+ if(Parentel = =el) { return true;
} if(!el | |!el.nodetype | | el.nodetype! =1) { return false; } if(parentel.contains) {returnParentel.contains (EL); } if(parentel.comparedocumentposition) {return!! (Parentel.comparedocumentposition (EL) & -); } varPrEl =El.parentnode; while(prEl && PrEl! =container) { if(PrEl = =Parentel)return true; PrEl=Prel.parentnode; } return false; }
Integrated programme two, from Sizzle (https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L688)
Note: The contains version of Sizzle is contains (Ancestor,ancestor) returns false.
//Element contains another//purposefully does not implement inclusive descendent//as in, a element does not contain itselfContains = Hascompare | | Rnative.test (docelem.contains)?function (A, b) {varAdown = A.nodetype = = =9?a.documentelement:a, Bup= b &&B.parentnode; returnA = = = Bup | | !! (bup && Bup.nodetype = = =1&&(Adown.contains?Adown.contains (BUP): A.comparedocumentposition&& a.comparedocumentposition (BUP) & - )); }: Function (A, b) {if(b) { while((b =B.parentnode)) {if(b = = =a) {return true; } } } return false; };
General Plan Three, my long, smelly version of ^_^
varrnative =/[^{]+\{\s*\[native code\]\s*\}/;varDocel =document.documentelement;varContains = Rnative.test (docel.contains) &&function (ancestor, descendant) {if(ancestor = = = descendant)return true; Ancestor= Ancestor.nodetype = = =9?Ancestor.documentElement:ancestor; returnAncestor.contains (descendant);} ||rnative.test (docel.comparedocumentposition)&&function (ancestor, descendant) {if(ancestor = = = descendant)return true; Ancestor= Ancestor.documentelement | |ancestor; return!! (Ancestor.comparedocumentposition (descendant) & -); } ||rnative.test (Document.createrange)&&function (ancestor, descendant) {if(ancestor = = = descendant)return true; varR1 = Document.createrange (), r2 =Document.createrange (); R1.selectnode (Ancestor.documentelement||ancestor); R2.selectnode (Descendant.documentelement||descendant);
var Startret = r1.compareboundarypoints (range.start_to_start, r2); var endret = r1.compareboundarypoints (range.end_to_end, R2);
var ret = Startret = = =-1 && endret = = = 1;
try{
R1.detach ();
R2.detach ();
}catch (e) {}
return ret;
} ||
function (ancestor, descendant) {
if (ancestor = = = descendant) return true;
var a = Ancestor.documentelement | | Ancestor
var b = (Descendant.documentelement | | descendant) [' ParentNode '];
while (!! b) {
if (a = = B) return true;
b = B.parentnode;
}
return false;
};
Iii. Summary
Respect the original, reprint please specify from: http://www.cnblogs.com/fsjohnhuang/p/3931818.html ^_^ fat son John
JS Magic Hall: Determine node location relationship