Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

レガシーなウェブシステムのSELECTタグを使いやすくするJavascript(ブックマークレット)

久しぶりにブックマークレット

困りごと

うちの会社には、スーパーなレガシーシステムがありまして、、、
HTMLで作られているWebシステムなのですが、<select>がめっちゃ長いんですよ。選択肢が50とか100とかあります。資格の名前とか事業所の一覧とか、似たような名前が多くて地獄です。

画面で入力する身としては、たまったもんじゃありません。目で見て選択するなんて無理です。

ということで、レガシーシステムに息を吹き込むブックマークレットを作りました。

使うもの

  • Javascript
  • jQuery

レガシーシステムが相手なので、jQueryで楽させてもらいます。

コード

こんな感じになりました。コメント入れて60行くらい。
さすがにレガシーといえど、jQueryを使ってコード書きました。

select-filter.js
void ((function (f) {
  if (window.jQuery && jQuery().jquery > '2.0') {
    console.log('use jquery');
    f(jQuery);
  } else {
    console.log('load jquery');
    var script = document.createElement('script');
    script.src = '//code.jquery.com/jquery-3.5.1.slim.min.js';
    script.onload = function () {
      var $ = jQuery.noConflict(true);
      f($);
    };
    document.body.appendChild(script);
  }
})(
  function ($, undefined) {
    $('select').each(function (i, select) {
      //selectにidが無ければ、nameから作り出す
      if (!select.id) {
        select.id = select.name + '_' + i;
      }

      let options = $(select).children('option').length;
      let text = `<input type="text" data-selectid="${select.id}" class="__ft">`;
      let badge = `<span id="${select.id}_hit">${options}</span>/<span>${options}</span>`;

      //textboxを突っ込む
      $(select).before(`${text}  ${badge} <br>`);
    });

    //追加したテキストボックス全てに適用するイベントハンドラ
    $('input.__ft').on('input', function (ev) {

      let selector = '#' + $(this).data('selectid');
      let selectid = $(selector).attr('id');
      console.log(selector);

      let txt = this.value;
      console.log(txt);

      //フィルタした瞬間に選択肢を元に戻すならコメントはずす
      // $(selector).prop("selectedIndex", 0);

      let hit = 0;
      $(selector).children('option').each(function (i, e) {
        if (isDefaultOption(e) || matchOption(e, txt)) {
          $(e).show();
          hit++;
        } else {
          $(e).hide();
        }
      });
      $(`span#${selectid}_hit`).text(hit);
    });

    //デフォルトオプションの判定(システムに合わせて適当に書き換える必要があるかも)
    function isDefaultOption(element) {
      return $(element).val() == '' || $(element).hasClass('default');
    }
    //表示する条件(半角全角の調整など必要なことをやるべし)
    function matchOption(element, input) {
      return $(element).text().indexOf(input) != -1;
    }
  }
))

コードはここにも置いてあります。
https://github.com/kanaxx/kanaxx.github.io/tree/master/bookmarklet/select-filter

コードの説明

:sunflower: 説明するほどのコードじゃないですけど、一応。

$('select')なので、画面にある全ての<select>が対象です。

<select>にidが振られていないようなレガシーシステムの場合のことも考えて、nameの値を元に<select>にidを追加しています。

テキストボックスの真下にある<select>のidをテキストボックスのdata-selectidとして仕込むことで関連を持たせ、class__ftクラスを割り当てる

__ftクラス全体にinputイベントハンドラを登録する

イベントハンドラでselectからoptionを探して、部分一致したものだけshow()する

実行

選択肢が多いページが必要だったので、自分で作りました。
https://kanaxx.github.io/bookmarklet/select-filter/index.html

F12でDevToolを開いて、Consoleにスクリプトを投げ込んでください。

image.png

初期表示はセレクトがあるだけ
image.png

長くてうんざり
image.png

ブックマークレット(スクリプト)を実行
画面内にあるセレクトの上に、テキストボックスが生まれる!
image.png

フィルタ実行
テキストに「都」を入れると「東京都」と「京都府」で2つの選択肢だけになるので、選びやすい。3/48表記は左がマッチした選択肢数、右が選択肢の総数です。テキストボックスから消すと全部元通りです。
image.png

まとめ

程よく汎用的に作ったので、たいていのサイトの選択肢<select>をハックできるはずです。一番上の選択肢を上手に判定する方法が見つからなかったけど。
気に入ったら、ブラウザのブックマークバーに登録してみてください。

参考資料

国の一覧はここを一覧を使わせていただきました。5年前の国名らいし2020年だと変わってるかもしれません。
https://qiita.com/tao_s/items/32b90a2751bfbdd585ea

kanaxx
めんどくさい作業は全てブックマークレットで解決したい
https://kanaxx.hatenablog.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away