任意に設計された住所フォームの「出荷先」を検出し、その内容を解析するユーザースクリプトを作成しています。これを行うにはtr
、アドレスのラベル( "Name"、 "Address1"など)とそれに対応するinput
フィールドの両方を含むフォーム "rows"(要素である場合とそうでない場合があります)を見つける必要があります。鬼ごっこ。たとえば、次のスニペットでは次のようになります。
<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を上に向かって作業します
- 次に、そこに到達するためにトラバースした子を削除し、セットの親要素のみを残します。
私が作業しているポートから変換すると、JQueryJavascriptは次のようになります。
// 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);