DOM操作でesaのliタグをソートするChrome拡張機能を作ってみた話

ブログ一覧へ
画像:メイン画像

こんにちは!システムエンジニアチーム所属の江口です。

 

弊社ではナレッジベースとしてesa.ioを活用しています。とても便利なのですが、アプリの思想的な狙いがあるようで、ナビゲーションのliタグはポストが多い順で並んでいます。

 

社内で「名前順にしたい」という要望があったので、DOM操作の勉強がてらChrome拡張機能に組み込んでみました!  

 

説明画像:esaソート再現動画

 

 

 

 

1.任意のディレクトリに自作拡張機能のファイルを作成

 

 ディレクトリ構成は下記の通りです。

ここではesa-sort配下のそれぞれのファイル(background.js・manifest.json・script.js)を編集していきます。

 

  esa-sort
  ├── background.js
  ├── manifest.json
  └── script.js

 

 

ファイルの編集 

 

background.js

//拡張機能のiconをクリックした際に発火するようスタンバイしています。
chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.tabs.sendMessage(tab.id, "action");
});

 


manifest.json

  {
  "name": "esa-sort",
  "description": "esaのnavのリストを名前順にソートします。",
  "version": "1.0.4",
  "manifest_version": 2,
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  "browser_action": {
  },
  "content_scripts": [{
    "//": "esa.ioのみ有効になるように設定",
    "matches": ["https://*.esa.io/*"],
    "js": ["script.js"]
  }],
  "permissions": [
    "tabs"
  ]
}

 

 

script.js

//background.jsのsendMessageをトリガーに呼び出されます。
chrome.extension.onMessage.addListener(function(request) {
    if (request == "action") {
      //一番最初に見るべきulをクラス属性で決め打ちします。
      let ul = document.querySelector('nav.navbar-side > ul');
      sortByName(ul);
    }
});

//メインの関数です。渡されたulを元にその子要素のliを処理していきます。
function sortByName(ul) {
  $obj =  [].slice.call(ul.childNodes).map(function(child){
    if (child.tagName == "LI") {
      //li > a > spanに名前が格納されているので、この値をvalueとします。
      let value = child.querySelector('a > span').textContent.trim();
      //esaの仕様だと思われますが、大量の(no category)が出てくるので、これは削除します。
      if (value == "(no category)") {
        child.remove();
      } else {
        //valueとdomを紐つけて$objに返します
        return { value: value, dom: child };
      }
    }
  });

  //$objを名前順にして、appendChildでdomに反映します。
  $obj.sort(compare).forEach(function(child){
    if (child != undefined && ul.appendChild(child.dom) != undefined) {
      ul.appendChild(child.dom);
    }
  });

  for (var i = 0; i < ul.childNodes.length; i++) {
    if (ul.childNodes[i].nodeName == "LI") {
      let li = ul.childNodes[i];
      for (var j = 0; j < li.childNodes.length; j++) {
        if (li.childNodes[j].nodeName == "UL") {
          //再帰的にsortByNameを呼び出します。
          sortByName(li.childNodes[j]);
        }
      }
    }
  }
}

//aとbを名前順で比較します
function compare(a, b) {
  const nameA = a.value.toUpperCase();
  const nameB = b.value.toUpperCase();
  let comparison = 0;
  if (nameA > nameB) {
    comparison = 1;
  } else if (nameA < nameB) {
    comparison = -1;
  }
  return comparison;
}

 

 

2.自作拡張機能を読み込む

 

 

 Chromeのメニューバーより ウィンドウ拡張機能をクリックし〔その他ツール〕→〔拡張機能〕を選択します。

選択すると、2枚目の画像のように拡張機能のメニューが表示されます。

 

 

画面左上に〔パッケージ化されていない拡張機能を読み込む〕ボタンが表示されているので、こちらをクリック。

さっそく、さきほど作った拡張機能をインストールしてみましょう!

 

  

 

 

3.読み込んだ拡張機能を実行してみよう!

 

 

無事インストールが完了すると、Chromeの右上に拡張機能のアイコンが表示されます。

esa.ioにログインし、拡張機能アイコンをクリックしてみましょう!

 

before

 

after

見事にesaのPostの順番が名前順に変更されました!

 

 

現状ではesa.ioでしか動かない機能ですが、サイト毎にulとliと名前のパターンを設定してLocalStrageに保存しておけば色んなサイトに使いまわせるかな〜なんて思っています。

(もし要望があれば作るかも?? )

今回の実装でDOMの理解と、更なる興味が広がりました!

 

Contact Us

ediplexでは一緒に働く仲間を募集しています。
ediplexでは一緒に働く仲間を募集しています。
気になった方はぜひ一度会社に遊びに来てください。