LoginSignup
8

More than 5 years have passed since last update.

Chrome extensionでselectのリストをフィルタする

Last updated at Posted at 2015-10-05

会社で使ってるツールでselectの中身(dropdown)が大量に出てくるページがあって、
毎度探すのが辛いので調べました。

で「CHROMEに追加」すれば各ページ内のselectがフィルタできるようになります。

ただ、どのページでも使えるかどうかは怪しいですね。
単純にoptionを絞り込んでるのでselectedIndexで管理するようにjavascript組まれてたらNGだし、
動的に生成されたselectには適用できない動作している気がします。
あと、多くselectが配置されているページでの利用は少し辛いです。

なので試しに遊びで自作してみました。

自作するのに参考にしたページは下記です。
http://qiita.com/suin/items/5e1aa942e654bce442f7

ファイル構成

├icons
│├icon16.png
│├icon48.png
│└icon128.png
├manifest.json
└selectbox-filter.js

iconはいい感じに作ってください。

manifest.json

manifest.json
{
  "name": "Select options filter",
  "version": "0.0.1",
  "manifest_version": 2,
  "description": "selectをCtrl+Clickするとフィルタモードになります",
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  },
  "content_scripts": [
    {
      "matches": [
        "<all_urls>"
      ],
      "js": [
        "selectbox-filter.js"
      ]
    }
  ],
  "web_accessible_resources": [
    "icons/icon16.png"
  ],
  "permissions": [
    "<all_urls>"
  ]
}

content_scriptsに書くとページ操作できるみたいです。
web_accessible_resourcesに記載すると、chrome.extension.getURL()でのURLが使える様子です。

selectbox-filter.js

selectbox-filter.js
(function() {
  'use strict';
  let input = document.createElement('input');
  input.setAttribute('placeholder', 'enter filter keyword');
  input.style.backgroundImage = 'url("' + chrome.extension.getURL('/icons/icon16.png') + '")';
  input.style.backgroundRepeat = 'no-repeat';
  input.style.backgroundPosition = 'right';
  let select;
  //documentのclickにイベント登録
  document.addEventListener('click', function(e) {
    if (e.ctrlKey && e.target.tagName.toLowerCase() === 'select') {//Ctrl+Click かつ selectがClickされた場合フィルタモード開始
      select = e.target;
      input.value = '';
      select.parentElement.insertBefore(input, select);
      input.focus();
    }
  });
  input.addEventListener('keyup', function() {
    let value = input.value;
    let options = select.getElementsByTagName('option');
    let match = value ? function(option) {
      return option.textContent.indexOf(value) > -1;
    } : function(option) {
      return true;
    };
    let dispOpt = [];
    for (var i = 0; i < options.length; i++) {
      if (match(options[i])) {
        options[i].style.display = '';//displayでフィルタ制御
        dispOpt.push(i);
      } else {
        options[i].style.display = 'none';//displayでフィルタ制御
      }
      if (options[i].textContent === value) {//完全一致があったなら選択させる
        select.selectedIndex = i;
      }
    }
    if (dispOpt.length === 1) {//フィルタした結果が1件なら選択させる
      select.selectedIndex = dispOpt[0];
    }
  });
})();

動作

selectをCtrl押しながらClickするとフィルタ用のinputが横に出てきて、入力すると、selectの中身が絞られます。

左から、通常→Ctrl+Clickしたあと→入力した後のselectの状態
スクショ.jpg

やりたかったこと

  • displayでフィルタするのでselectedIndexを汚さない(はず)
  • 一つのselectに対してだけinputを表示するのでページが大きく崩れない。
  • documentのクリックイベントで制御するので追加で配置されたselectでも動作する。

入手

作成したものをwebstoreに公開しました。
https://chrome.google.com/webstore/detail/select-box-filter/ohgdgoglcbcfofphmmnkkdbpffklhjgh

ソースはgithubにあげています。
https://github.com/ota-meshi/chromeextension_selectbox_filter

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8