Greasemonkey で、既存のページに複数ある radioボタンのうち、隣にある「カテゴリ」を現すテキストの同じものだけ、チェックするボタンを作りたいと思っています。


現在のHTML
==================
<tr><td>
<div><a class="title" title="HOGE">HOGE</a></div>
</td>
<td>カテゴリA</td>
<td>
<input checked="checked" value="1" name="12345_flag" type="radio"><label>ON</label>
<input value="0" name="12345_flag" type="radio"><label>OFF</label>
</td>
</tr>
==================
このような ON OFF radioボタンが 30個くらい並んでおり、
カテゴリAと書いている部分が、AからCぐらいまであり、
たとえば、「カテゴリB」だけ ON になるボタン というものを
Greasemonkey を使って実装したいと考えています。

やり方の方針としましては、
どうにかして カテゴリA の部分のテキストを解析し、
それに対応する input radio に class="カテゴリA" とかの要素を追加し、
class="カテゴリA" を一斉に ON OFF する Javascriptボタンを最後に付け加える。

こんな流れかと思いますが、そもそもカテゴリAの部分を取得できるのかどうか。
id や class がついていないため、どうなのかと。
そもそも実現可能か、可能であれば、どこを調べればよいか。
ご教授願いします。

回答の条件
  • 1人3回まで
  • 登録:
  • 終了:2011/04/24 05:40:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:Cherenkov No.1

回答回数1504ベストアンサー獲得回数493

ポイント60pt

カテゴリ名を自動で取得して、それぞれをONにするボタンを追加するデモを書いてみました。

多分そのままグリモンにすれば動くと思います。

demo: http://jsfiddle.net/L6Rmp/


  • カテゴリ名があるに特徴的なclassやidがなかったり想定できない場合は、DOMを手がかりにXPathを使って取得する。
  • 今回はradioboxを持つ(軸)にclassを付けて、カテゴリにマッチするチェックボックスをclick()するようにした。

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script>
onload = function() {
  // radiobox生成(質問に関係ない)
  var tr = document.querySelector('tr');
  for(var i=0; i<9; i++) {
    var tr2 = tr.cloneNode(true);
    tr2.querySelector('td').textContent = "カテゴリ"+["A","B","C","D"][Math.floor(Math.random()*4)];
    var radios = tr2.querySelectorAll('[type="radio"]');
    radios[0].name = radios[1].name = i + 2 + "_flag";
    tr.parentNode.appendChild(tr2);
  }
  
  
  //-----ここからグリモン-----
  //radioにclassを付ける
  var catList = [];
  var cat = document.evaluate('//td[input[@type="radio"]]', document, null, 7, null);
  for (var i=0, n=cat.snapshotLength; i<n; i++) {
    var catName = document.evaluate('preceding-sibling::td', cat.snapshotItem(i), null, 9, null).singleNodeValue.textContent;
    cat.snapshotItem(i).parentNode.querySelector('input[type="radio"]').parentNode.classList.add(catName);
    
    //カテゴリ名の収集
    if(catList.indexOf(catName) == -1)
      catList.push(catName);
  }

  //ボタン追加
  var div = document.createElement('div');
  div.setAttribute('style', 'position:fixed; bottom: 20px; left: 10px;');
  catList.forEach(function(e) {
    var btn = document.createElement('button');
    btn.textContent = e;
    btn.addEventListener('click', function() {
      Array.forEach(document.querySelectorAll('input[type="radio"]'), function(f) {
        if (f.parentNode.classList.contains(e))
          f.parentNode.querySelector('input[type="radio"][value="1"]').click();
        else
          f.parentNode.querySelector('input[type="radio"][value="0"]').click();
      });
      
    }, false);
    div.appendChild(btn);
  });
  document.body.insertBefore(div, document.body.firstChild);
  //-----ここまで-----
}
</script>
</head>
<body>
<form>
<table>
<tr>
<td>カテゴリA</td>
<td>
<input checked="checked" value="1" name="1_flag" type="radio"><label>ON</label>
<input value="0" name="1_flag" type="radio"><label>OFF</label>
</td>
</tr>
</table>
<input type="submit" value="submit">
</form>
</body>
</html>
  • id:Cherenkov
    修正
    カテゴリ名がある<td>に特徴的なclassやidがなかったり想定できない場合は、DOMを手がかりにXPathを使って取得する。今回はradioboxを持つ<td>(軸)にclassを付けて、カテゴリにマッチするチェックボックスをclick()するようにした。

    if(catList.indexOf(catName) == -1)

    if (catList.every(function(e) { return e !== catName; })) {
  • id:Cherenkov
    if (!catList.some(function(e) { return e == catName; })) {
    こっちのほうがよかったです。
  • id:Cherenkov
    うまく動きましたか?
  • id:subweb
    色々実装ありがとうございます。

    ちょっと苦手分野なので、現在確認しております。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません