在Javascript中,我想确定一个元素,比如一个A
元素,是否存在于给定范围/ textRange中。目的是确定用户的当前选择是否包含链接。我正在构建一个富文本编辑器控件。
range对象有一个commonAncestorContainer(W3C)或parentElement()(Microsoft)方法,它返回范围内所有元素的最接近的公共anscestor。但是,在A
元素的元素内部查找将不起作用,因为这个共同的祖先也可能包含不在范围内的元素,因为范围可以从父节点开始或结束。
你将如何实现这一目标?
答案 0 :(得分:5)
selection.containsNode怎么样? https://developer.mozilla.org/en/DOM/Selection/containsNode
类似的东西:
var selection = window.getSelection();
var range = selection.getRangeAt(0);
var result = $('a', range.commonAncestorContainer).filter(function() {
return selection.containsNode(this);
});
console.log(result);
答案 1 :(得分:3)
我最终选择了这样的解决方案:
var findinselection = function(tagname, container) {
var
i, len, el,
rng = getrange(),
comprng,
selparent;
if (rng) {
selparent = rng.commonAncestorContainer || rng.parentElement();
// Look for an element *around* the selected range
for (el = selparent; el !== container; el = el.parentNode) {
if (el.tagName && el.tagName.toLowerCase() === tagname) {
return el;
}
}
// Look for an element *within* the selected range
if (!rng.collapsed && (rng.text === undefined || rng.text) &&
selparent.getElementsByTagName) {
el = selparent.getElementsByTagName(tagname);
comprng = document.createRange ?
document.createRange() : document.body.createTextRange();
for (i = 0, len = el.length; i < len; i++) {
// determine if element el[i] is within the range
if (document.createRange) { // w3c
comprng.selectNodeContents(el[i]);
if (rng.compareBoundaryPoints(Range.END_TO_START, comprng) < 0 &&
rng.compareBoundaryPoints(Range.START_TO_END, comprng) > 0) {
return el[i];
}
}
else { // microsoft
comprng.moveToElementText(el[i]);
if (rng.compareEndPoints("StartToEnd", comprng) < 0 &&
rng.compareEndPoints("EndToStart", comprng) > 0) {
return el[i];
}
}
}
}
}
};
其中getrange()是我的另一个函数,用于将当前选择作为范围对象。
要使用,请将其称为
var link = findselection('a', editor);
编辑器是设计模式iframe中的contenteditable元素或主体。
答案 2 :(得分:2)
这对于做跨浏览器的屁股来说有点痛苦。你可以使用我的Rangy库,这对于这个任务可能有点过分,但确实使它更直接,适用于所有主流浏览器。以下代码假定只选择了一个范围:
var sel = rangy.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
var links = range.getNodes([1], function(node) {
return node.tagName.toLowerCase() == "a" && range.containsNode(node);
});
}
答案 3 :(得分:0)
我使用的代码适用于IE / Chrome / FF :(我用它来选择表格中的行&lt; tr&gt;)
// yourLink is the DOM element you want to check
var selection = window.getSelection().getRangeAt(0)
var node = document.createRange()
node.selectNode(yourLink)
var s2s = selection.compareBoundaryPoints(Range.START_TO_END, node)
var s2e = selection.compareBoundaryPoints(Range.START_TO_START, node)
var e2s = selection.compareBoundaryPoints(Range.END_TO_START, node)
var e2e = selection.compareBoundaryPoints(Range.END_TO_END, node)
if ((s2s != s2e) || (e2s != e2e) || (s2s!=e2e))
console.log("your node is inside selection")
答案 4 :(得分:0)
对于搜索到的元素上的 range ,我写的内容很有用。 (但仅限于这种情况!)
首先,我编写了一个函数,该函数返回在范围内找到的Node:getNodeFromRange(rangeObject)。使用此函数,编写返回所需节点的函数已经很容易了:findTagInRange(tagName)。
function getNodeFromRange(range) {
if(range.endContainer.nodeType==Node.ELEMENT_NODE) {
return range.endContainer;
}
if(range.endContainer.nodeType==Node.TEXT_NODE) {
return range.endContainer.parentNode;
}
else {
// the 'startContainer' it isn't on an Element (<p>, <div>, etc...)
return;
}
}
function findTagInRange(tagName, range) {
var node = getNodeFromRange(range);
if(node && typeof(node.tagName)!='undefiend' && node.tagName.toLowerCase()==tagName.toLowerCase()) {
return $(node);
}
return;
}
然后我可以如下使用它:
var link = findTagInRange('A', range);
我看到您已经解决的范围的确定。 :)