Chrome extension에서 선택 목록 필터링

회사에서 사용하는 도구로 select의 내용 (dropdown)이 대량으로 나오는 페이지가 있고,
매번 찾는 것이 힘들기 때문에 조사했습니다.

에서 "CHROME에 추가"하면 각 페이지 내의 select를 필터링 할 수 있습니다.

다만, 어느 페이지에서도 사용할 수 있을지는 의심스럽네요.
단순히 option을 좁히고 있으므로 selectedIndex로 관리하도록 javascript 짜여져 있으면 NG이고,
동적으로 생성된 select에는 적용할 수 없는 동작하고 있는 것 같습니다.
그리고, 많은 select가 배치되어 있는 페이지에서의 이용은 조금 괴롭습니다.

그래서 시험에 놀이로 자작 해 보았습니다.

자작하는데 참고로 한 페이지는 아래와 같습니다.
ぃ tp // 코 m / 수련 / ms / 5 에 1 아 942 에 654b 442f7

파일 구성


├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 상태


하고 싶었던 일


  • display로 필터링하기 때문에 selectedIndex를 더럽히지 않는다.
  • 하나의 select에 대해서만 input을 표시하기 때문에 페이지가 크게 무너지지 않는다.
  • document의 클릭 이벤트로 제어하기 때문에 추가로 배치된 select에서도 동작한다.

  • 입수



    작성한 것을 webstore에 공개했습니다.
    htps // ch 로메. 오, ぇ. 이 m / ぇ bs 잡아 / 싶은 l / ぇ ct ー ー ボ ー ー ぃ l r / hgd 고 glcbc

    소스는 github에 올리고 있습니다.
    htps : // 기주 b. 코 m / 오타 메시 / ch 로메에 x 텐시 온_세 ct 보 x_ 푸 1 r

    좋은 웹페이지 즐겨찾기