1

我正在编写一个用户脚本,它检测“运送到”任意设计的地址表单并解析其内容。为此,我需要找到tr包含地址标签(例如“名称”、“地址 1”等)和相应input字段的表单“行”(可能是元素也可能不是元素)标签。例如,在以下代码段中:

<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元素,因为它们每个都包含一个“名称”标签和一个输入字段。但是,我不想匹配div“MaidenName”标签,因为它的范围比为表内字段找到的匹配范围更广。

我当前查找这些行(通常是div元素而不是元素tr)的算法是:

  • 查找具有适当“名称”标签的所有节点
  • 在每个节点的 DOM 中向上工作,直到找到一个作为输入字段祖先的节点
  • 然后删除我遍历到达那里的孩子,只留下集合的父元素。

从我正在使用的端口翻译,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});

这行得通……但是所有这些遍历和比较开销绝对会破坏我的表现(这可能需要五秒钟或更长时间。)

有什么更好的方法来实现这一点?我认为下面的伪代码会更好,但我可能是错的,我不知道如何实现它:

var filteredSet = $().find(*).hasAnyOf(labelNodes).hasAnyOf(nodesWithAddress);
return filteredSet.hasNoneOf(filteredSet); 
4

2 回答 2

2

更新

我找到了一个更好的解决方案(见修订)我认为这对你来说非常有用。

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;
}

​</p>

现场演示

于 2012-07-27T22:41:36.077 回答
0

概括 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;
于 2012-07-30T18:35:11.460 回答