私の質問はまさにそれですが、コンテキストで選択オブジェクトを調べ、anchorNodeとfocusNodeを比較し、それらが異なる場合は、最初の共通の親要素を見つけます。
var selected = window.getSelection();
var anchor = selection.anchorNode;
var focus = selection.focusNode;
if ( anchor != focus ) {
// find common parent...
}
私の質問はまさにそれですが、コンテキストで選択オブジェクトを調べ、anchorNodeとfocusNodeを比較し、それらが異なる場合は、最初の共通の親要素を見つけます。
var selected = window.getSelection();
var anchor = selection.anchorNode;
var focus = selection.focusNode;
if ( anchor != focus ) {
// find common parent...
}
JSライブラリがないと仮定して、次のようなことを試してみます。
function findFirstCommonAncestor(nodeA, nodeB, ancestorsB) {
var ancestorsB = ancestorsB || getAncestors(nodeB);
if(ancestorsB.length == 0) return null;
else if(ancestorsB.indexOf(nodeA) > -1) return nodeA;
else if(nodeA == document) return null;
else return findFirstCommonAncestor(nodeA.parentNode, nodeB, ancestorsB);
}
このユーティリティの使用:
function getAncestors(node) {
if(node != document) return [node].concat(getAncestors(node.parentNode));
else return [node];
}
if(Array.prototype.indexOf === undefined) {
Array.prototype.indexOf = function(element) {
for(var i=0, l=this.length; i<l; i++) {
if(this[i] == element) return i;
}
return -1;
};
}
次に、を呼び出すことができますfindFirstCommonAncestor(myElementA, myElementB)
。
//ライブラリやindexOfがなくても、かなり単純なはずです。
document.commonParent= function(a, b){
var pa= [], L;
while(a){
pa[pa.length]=a;
a= a.parentNode;
}
L=pa.length;
while(b){
for(var i=0; i<L; i++){
if(pa[i]==b) return b;
}
b= b.parentNode;
}
}
この質問と受け入れられた回答は非常に古いため、より最新のDOMAPIであるRangeを使用することをお勧めします。
function findFirstCommonAncestor(nodeA, nodeB) {
let range = new Range();
range.setStartBefore(nodeA);
range.setEndAfter(nodeB);
// There's a compilication, if nodeA is positioned after
// nodeB in the document, we created a collapsed range.
// That means the start and end of the range are at the
// same position. In that case `range.commonAncestorContainer`
// would likely just be `nodeB.parentNode`.
if(range.collapsed) {
// The old switcheroo does the trick.
range.setStartBefore(nodeB);
range.setEndAfter(nodeA);
}
return range.commonAncestorContainer;
}
そのためのDOMAPIがかなりあります:compareDocumentPosition
これがその方法です:
/**
* Returns closest parent element for both nodes.
*/
function getCommonParent(one, two){
let parent = one.parentElement;
if(one === two) { //both nodes are the same node.
return parent;
}
const contained = Node.DOCUMENT_POSITION_CONTAINED_BY;
let docpos = parent.compareDocumentPosition(two);
while(parent && !(docpos & contained)) {
parent = parent.parentElement;
docpos = parent.compareDocumentPosition(two);
}
return parent;
}