获取满足两个不同后代选择器标准的“最深”元素
Posted
技术标签:
【中文标题】获取满足两个不同后代选择器标准的“最深”元素【英文标题】:Getting the "deepest" elements that meet two different descendant selector criteria 【发布时间】:2012-07-26 15:02:57 【问题描述】:我正在编写一个用户脚本,它检测“运送到”任意设计的地址表单并解析其内容。为此,我需要找到包含地址标签(例如“名称”、“地址 1”等)和相应的“行”(可能是也可能不是 tr
元素)的表单input
该标签的字段。比如在下面的sn-p中:
<div>
<label>MaidenName</label>
<table><tbody>
<tr>
<td><label>FirstName</label></td>
<td><input value = "Bob"></td>
</tr>
<tr>
<td><label>LastName</label></td>
<td><input value = "Smith"></td>
</tr>
<tr>
<td><label>CompanyName</label></td>
<td><input value = "Ink Inc"></td>
</tr>
</tbody></table>
</div>
我想匹配所有tr
元素,因为它们每个都包含一个“名称”标签和一个输入字段。但是,由于“MaidenName”标签的原因,我不想匹配 div
,因为它的范围比在表内的字段中找到的匹配范围更广。
我当前查找这些行(通常是 div
元素而不是 tr
元素)的算法是:
从我正在使用的端口翻译,JQuery javascript 将如下所示:
// set up my two lists
var labelNodes = getLabelNodes();
var nodesWithAddress =
$().find("input[type='text']:visible, select:visible");
var pathToCommonParents = getLabelNodes()
.parentsUntil(nodesWithAddressChildren.parents()).parent();
// keep the highest-level nodes, so we only have the common paths -
//not the nodes between it and the labels.
return combinedNodeSet.filter(
function (index) return $(this).find(combinedNodeSet).length == 0);
这行得通...但是所有这些遍历和比较开销绝对会破坏我的性能(这可能需要 5 秒 或更长时间。)
什么是更好的实现方式?我认为下面的伪代码会更好,但我可能是错的,我不知道如何实现它:
var filteredSet = $().find(*).hasAnyOf(labelNodes).hasAnyOf(nodesWithAddress);
return filteredSet.hasNoneOf(filteredSet);
【问题讨论】:
在这种情况下,标签和输入周围是否总是存在类似td
的元素?
总是一些元素,但是环绕元素的嵌套深度和标签名称会有所不同。
【参考方案1】:
更新
我找到了一个更好的解决方案(请参阅修订版)我认为这对您来说非常有效。
function getMySpeacialElements()
var aSpeacialElements = [];
$("label").each(function()
var oParent = $(this).parent(),
oSpeacial = oParent.parent();
oSpeacial.children("*").each(function()
if ($(this).children("input").length)
aSpeacialElements.push(oSpeacial[0]);
);
);
return aSpeacialElements;
Live DEMO
【讨论】:
谢谢。我敢肯定,如果我坐下来五分钟,我就能弄清楚这是如何工作的,但是未来的 SO 读者(更不用说我自己)可能会从对正在发生的事情的概述中受益。 他查看页面上的每个标签,当它迭代时,标签被设置为父标签。然后他查看所有的孩子并找到那些是输入的孩子。一旦找到输入,他就会将该元素推送到数组中。非常好的方法。【参考方案2】:概括 micha 的答案,以便它可以以独立于页面的方式(不同的标签和嵌套级别)查看:
var labelNodes = getLabelNodes();
var returnNodes = $();
var regexAncestors = labelNodes.parent();
while (regexAncestors.length)
regexAncestors = regexAncestors.not("body");
var commonParentNodes = regexAncestors.has("input[type='text']:visible, select:visible");
returnNodes.add(commonParentNodes);
regexAncestors = regexAncestors.not(commonParentNodes).parent();
return returnNodes;
【讨论】:
以上是关于获取满足两个不同后代选择器标准的“最深”元素的主要内容,如果未能解决你的问题,请参考以下文章