利用状況把握拡張機能⑥ - オプションページ②

この記事は利用状況把握拡張機能⑤の続きですので、そちらにも目を通した方が
理解しやすいと思います。
　ここでは、拡張機能に関する新しい概要や知識などはありません。

　前回のページ　→　<a href="https://qiita.com/Hira_B/items/6acd07e5f76150cda476
">利用状況把握拡張機能⑤</a>

　最初　→　<a href="https://qiita.com/Hira_B/items/84fe189a38f43f574502">利用状況把握拡張機能①</a>

## リストのその他の処理
　
### 制限時間
 こちらも制限時間を編集させるためにプルダウンメニューが必要になる。HTMLの方にこちらは記述していないので、プルダウンメニューから全てをJS内で生成していく。処理としては、休止時間と変わらないため割愛するが、ここでプルダウンメニューに関する新たな長い処理が加わる。
　編集した時間はstorageへと保存され、以降はその時間が制限時間等に反映されるが、今のままではプルダウンメニューの数値表記は変わらず、storageの時間との整合性がない状態である。プルダウンメニューの初期選択値を現在のデータと同じになる記述をする。

```javascript:setting.js
const elementSelectHour2 = document.getElementsByClassName("hour2");
const elementSelectMinutes2 = document.getElementsByClassName("minutes2");
selectmenuTime(elementSelectHour2,elementSelectMinutes2,num * 2);

function setSelectMenuTime(i,SiteTimeLimit_W,SiteTimeLimit_H){
    let W_H = document.getElementById("090" + i);
    let W_M = document.getElementById("091" + i);
    let H_H = document.getElementById("080" + i);
    let H_M = document.getElementById("081" + i);
    let A = W_H.options;
    let B = W_M.options;
    let C = H_H.options;
    let D = H_M.options;
    chrome.storage.local.get().then((result)=>{
        const secondsTime   = result.SiteTimeLimit[i] / 60 / 60 ;
        const secondsTime_H = result.SiteTimeLimit_H[i] / 60 / 60;
        const nowHourTime 	= Math.floor(secondsTime);
        const nowMinutesTime 	= secondsTime % 1 * 60;
        const nowHourTime_H 	= Math.floor(secondsTime_H);
        const nowMinutesTime_H 	= secondsTime_H % 1 * 60;
        A[nowHourTime].selected    = true;
        C[nowHourTime_H].selected  = true;
        setMinutesTime(nowMinutesTime,B);
        setMinutesTime(nowMinutesTime_H,D);
    });
    }
    if( MinutesTime  === 0 )//0分
        option[0].selected = true;
    else{
        let index = Math.floor( MinutesTime / 5 );
        option[index].selected = true;
    }
```
　まずは`setAttribute`で生成したブロックリストの制限時間プルダウンメニューのHTML要素とclass属性を取得する。その後はstorageの情報を秒単位から時・分単位に変更してプルダウンメニューの値へと反映する。値に介入するには、プルダウンメニューのid属性からoptionsメソッド、さらにそこからselectedメソッドをtrueにする。

　重要な部分は、document.getElementById("0XY" + i);の四つと、プルダウンメニューのid取得しているがこのidもまた`setAttribute`でid属性をテーブル列の制限時間の時間・分のプルダウンメニュー平日・休日で四つに分けて生成している。そうして上記の関数でブロックリストのプルダウンメニューの値に現在の時間設定を選択させている。

　時間単位はメニューのインデックスと値が同じだったが、分単位はそうできない。値は5分間隔で設計されているので値を5で割りインデックスの総合性を取るように処理を追加している。

　コードを打ち込んだ後、ポップアップでページをいくつかブロックリストに追加をし、設定ページへと移動して動いているかを確認する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657037/36c2f78f-dcfa-6b3e-e6c7-122d9c2e05e9.png)

上の画像のようになった。何もないテーブルに、JSによって一から要素を動的に追加させることが出来た。プルダウンメニューの値を変更してＯＫを押した後にも、storageのデータとプルダウンメニューの初期値が同様に変更されていた。

許可リストの方は制限などの余分な箇所を消し、同じように実装していく。
```javascript:setting.js
for(let i = 0; i < result.AllowingList.length; i++){//許可リスト
    const elementRow = document.createElement("tr");
    const elementCell = document.createElement("td");
    const elementdelete = document.createElement("td");
    const elementSpan = document.createElement("span");
    const spanText = document.createTextNode(result.AllowingList[i]);
    
    elementTableAl.appendChild(elementRow);
    elementRow.appendChild(elementCell);
    elementRow.appendChild(elementdelete);
    elementCell.appendChild(elementSpan);
    elementSpan.appendChild(spanText);
    
    let pointClass = "pointerA";
    
    let elementImage = new Image(20,20);
    let deleteId = "110" + i;

    elementImage.src= "../images/delete.png";
    elementdelete.setAttribute("width","20px");
    elementImage.setAttribute("id",deleteId);
    elementImage.setAttribute("class",pointClass);
    elementdelete.appendChild(elementImage);
}
document.querySelectorAll('.pointerA').forEach(function(tr){
    tr.addEventListener('click',(e)=>{
        deleteList(e.target.id,"AllowingList");
    });
});
```
次にリストを削除する処理も記述していく。
```javascript:setting.js
function deleteList( id,B_A ){
    let n = id % 100;
    chrome.storage.local.get().then((result)=>{
    if( B_A ==="BlockList"){
    let newlist = result.BlockList;
    newlist.splice(n,1);
    　…（省略）
}
```
　Storageからコピーしたデータをsplice関数で一か所削除し、storageへと保存している。nはテーブルの行番号。

許可リストの方は制限などの余分な箇所を消し、同じように実装していく。
完成後の許可リストが下の画像。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657037/badac123-7ece-97fc-881e-d2a1d1a03e62.png)

## グラフ
　最後に、ブラウザの利用状況がわかるグラフを作成する。作成するグラフは三つ。
 - 全てのサイトの利用時間
 - 週の累計利用時間
 - ブロック・許可リスト入りの利用時間と訪問回数
 グラフのCSSとJSはネットからコードを参考にした。
URL: https://1-notes.com/javascript-horizontal-bar-graph/



最初に全てのサイトの利用時間を作成する。
```html:setting.js
let All_data = [];
let copyAll;

for( let i = 0; i < result.All_URL.length; i++){
    
    let A = result.All_URL[i];
    let B;
    if( result.All_Time[i] === undefined )
        B = 0;
    else
        B = result.All_Time[i];
    let AB = { nameAll: "All-" + i, value : B, url : A };
    All_data.push( AB );
}

All_data.sort((firstItem, secondItem)=> secondItem.value - firstItem.value);

copyAll = All_data;
let valueAll = copyAll.map(function(p){
return p.value
});

let thresholdAll = Math.max.apply(null,valueAll);

```
　最初に利用時間データを配列オブジェクトへと全て格納する。その後はソートにより利用時間を基準とした降順に並べ替える。並べ替えた配列がそのままグラフの描画へと利用させる。利用時間の最大値を取得するため、map関数を使っている（リストが降順なので、All_data[0].valueでも可能）。

 データは用意できたため、次からグラフの描画へと移る。
```javascript:setting.js
for (let variable of All_data){
    variable.view_width = 0;
    variable.view_value = 0;
    
    variable.percentage = Math.round(variable.value / thresholdAll * 100);
    
    view_value = setTimeView( variable.value );
    
    document.querySelector('#All_container').insertAdjacentHTML('beforeend', `<div class="graf"><div class ="data-url"><span class="data-name">${variable.url}</span></div><div class="graf-bar-bg"><div class="graf-bar_All" id="${variable.nameAll}"><span>${view_value}</span></div></div></div>`);
}
```
　まずは利用時間の数だけ、グラフ描画用のHTMLを追加する。追加にcreateElementでなく`insertAdjacentHTML`を用いているのは、参考先のコードをそのまま流用したため。
　あとは、グラフをアニメーションで描画させる。

```javascript:setting.js
function updateAll(timestamp) {
    for (let variable of All_data) {
        if (variable.view_width < variable.percentage) {
            variable.view_width = variable.view_width + 2;
            if (variable.view_width > (variable.percentage * 0.8)) {
                variable.view_width = variable.view_width - 1.5;
            }
        }
        document.querySelector(`#${variable.nameAll}`).style.width = variable.view_width + '%';
    }
    if (timestamp <= 2000) {
        window.requestAnimationFrame(updateAll);
    }
}
window.requestAnimationFrame(updateAll);
```
　機能的には必要ないが、視覚的に見やすくなるので。

　次に週の累計利用時間をオブジェクト型変数へと代入する。こちらは元々がオブジェクト型なためObject.keysでキー情報を取得。週の累計データは以下のコードにより取得し、一つ目のグラフと同じようにオブジェクト型変数へと格納しソートする。

```javascript:setting.js
const valueTotal = [];
const Week = ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"];

let weekAll = [];
let weekdataAll = result.WeekdataArchiveAll;
let AllTotal = [];

for( let i in weekdataAll ){//一週間の中から
    AllTotal.push(0);
    let A = Object.keys( weekdataAll[i] );	//URLの配列取得
    for( let j = 0; j <  Object.keys( weekdataAll[i] ).length;j++ ){
        let B = A[j];
        AllTotal[i] = AllTotal[i] + weekdataAll[i][B];
    }
}

for(let i = 0 ; i < AllTotal.length ; i++){//グラフ用に改造
    let A = Object.keys(weekdataAll[i]);	//URL
    B =  AllTotal[i];
    if(B === undefined )
     B = 0;
    let AB = { nameW: "item_W" + i, value: B};
    weekAll.push( AB );
}
AllTotal.sort((a,b) => (a > b ? -1 : 1 ));
let thresholdWeek = AllTotal[0];
```
　その後は一つ目と同じようにHTMLを追加し、アニメーションを描画する。違いとしてはグラフ色分けや区別のためにclass、id属性の名前が違う程度。


　次に、ブロック・許可リストに重点をおいたグラフを作成する。普通の利用時間との違いは、こちらは訪問回数という別項目が追加させていること。
```javascript:setting.js
for( let i = 0; i < result.BlockList.length; i++){
    let keys = URLs[i];
    let B = weekdata[toWeek][keys];
    if( weekdata[toWeek][keys] === undefined )
        B = 0;
    let C = result.VisitCountB[i];
    let ABC = { nameQ: "item" + i, value : B, url : keys ,visit : C};
    todaydata_24.push( ABC );
}

//閲覧時間の降順ソート
todaydata_24.sort((firstItem, secondItem)=> secondItem.value - firstItem.value);

copyArrQ = todaydata_24;
let value = copyArrQ.map(function(p){
return p.value;
});
// しきい値
let thresholdQ = Math.max.apply(null,value);
```

その後は、リストも同じ要領でアニメーション関数を実装する。こうして、オプションページの機能も一先ず終了。

## 開発終了

　今回は初めて拡張機能の開発を行ったが、初物ゆえかコードを見ていて可読性もないスパゲッティコードに出来上がってしまった。 また、自身の開発工程を記事としてまとめるのも初めてだったため、自分で一から読んで作りの悪い教科書のようなものになってしまったと感じる。
　コードに関しては省略している部分も多く、このままでは自分の拡張機能を試すことも不可能な為、githubの方から省略した所を含め全て記述したソースコードファイルをプライベートですが公開しているので、興味のあるお方はそちらからインストールしていただければ。

利用状況把握拡張機能⑦　ソースコード


　これにて利用状況把握拡張機能の開発、終了です。稚拙な記事でしたがここまで読んでいただきありがとうございました。
 
 ## 関連する記事
 
 - <a href="https://qiita.com/Hira_B/items/84fe189a38f43f574502">利用状況把握拡張機能① - 拡張機能の概要とmanifestの読み込み　</a>
 - <a href="https://qiita.com/Hira_B/items/3978218f8d92c7a92c6c">利用状況把握拡張機能② - storageとContent Script、Service Workerの役割</a>
 - <a href="https://qiita.com/Hira_B/items/7f1160cb274bce2b4292">利用状況把握拡張機能③ - メッセージ送信と制限処理</a>
 - <a href="https://qiita.com/Hira_B/items/8a30109f47d1cef6a61e">利用状況把握拡張機能④ - 拡張機能のdefault_popup</a>
 - <a href="https://qiita.com/Hira_B/items/6acd07e5f76150cda476
">利用状況把握拡張機能⑤ - オプションページとグラフ①</a>
 - <a href="https://qiita.com/Hira_B/items/7fc516607a499298678c">利用状況把握拡張機能⑥ - オプションページとグラフ②　</a> ←現在の記事
 - <a href="https://qiita.com/Hira_B/items/141a0d506c14bbe7a6e5
">利用状況把握拡張機能⑦ - ソースコード</a>