From 4cc58cab0537b8055d96720422d0784bf1fca24e Mon Sep 17 00:00:00 2001 From: Koh Minami Date: Sun, 26 Apr 2020 20:53:08 +0900 Subject: [PATCH] =?UTF-8?q?[feature]=20=E6=8C=87=E5=AE=9A=E3=81=97?= =?UTF-8?q?=E3=81=9F=E3=82=BF=E3=82=B0=E3=82=92=E4=B8=8A=E4=BD=8D=E3=81=AB?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=99=E3=82=8B=E6=A9=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/popup.css | 147 +++++++++++++++++++++++++----------------- html/popup.html | 36 +++++++---- js/popup.js | 168 +++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 249 insertions(+), 102 deletions(-) diff --git a/css/popup.css b/css/popup.css index 0d891a5..c1fee15 100644 --- a/css/popup.css +++ b/css/popup.css @@ -1,89 +1,118 @@ #ndHiddenBlocker { - margin: 0px; - width: 200px; - height: 200px; + margin : 0px; + width : 240px; + background : #DDE0F1; /* デフォルト背景色 */ + font-family : "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", "メイリオ", Meiryo, sans-serif; +} + +#ndHiddenBlocker main { + padding-left : 15px; + padding-bottom : 15px; +} + +/* === ヘッダー ============================== */ +#ndHiddenBlocker .topBox { + width : 240px; + height : 40px; + background : #726C9F; +} +#ndHiddenBlocker .topText { + text-align : center; + color : white; + font-size : large; + padding : 8px; +} + +/* === 見出しテキスト ============================== */ +#ndHiddenBlocker .text { + font-size : 12px; + margin : 12px 0 6px; + font-weight : 700; + color : #565656; } /* === ボタンを表示するエリア ============================== */ #ndHiddenBlocker .switchArea { - line-height : 48px; /* 1行の高さ */ - letter-spacing : 0; /* 文字間 */ - text-align : center; /* 文字位置は中央 */ - font-size : 21px; /* 文字サイズ */ - - position : relative; /* 親要素が基点 */ - margin : auto; /* 中央寄せ */ - width : 114px; /* ボタンの横幅 */ - background : #fff; /* デフォルト背景色 */ + display : inline-block; /* 横に並べる */ + letter-spacing : 0; /* 文字間 */ + text-align : center; /* 文字位置は中央 */ + font-size : 12px; /* 文字サイズ */ + position : relative; /* 親要素が基点 */ + margin-right : 8px; + margin-bottom : 8px; } /* === チェックボックス ==================================== */ #ndHiddenBlocker .switchArea input[type="checkbox"] { - display : none; /* チェックボックス非表示 */ + display : none; /* チェックボックス非表示 */ } /* === チェックボックスのラベル(標準) ==================== */ #ndHiddenBlocker .switchArea label { - display : block; /* ボックス要素に変更 */ - box-sizing : border-box; /* 枠線を含んだサイズ */ - height : 48px; /* ボタンの高さ */ - border : 2px solid rgba(0, 0, 0, 0.36); /* 未選択タブのの枠線 */ - border-radius : 24px; /* 角丸 */ - cursor : pointer; + display : block; /* ボックス要素に変更 */ + box-sizing : border-box; /* 枠線を含んだサイズ */ + height : 30px; /* ボタンの高さ */ + border-radius : 15px; /* 角丸 */ + border-width : 0; + cursor : pointer; + padding : 7px 15px; + background-color : transparent; + letter-spacing : 0.04rem; + user-select : none; } /* === チェックボックスのラベル(ONのとき) ================ */ #ndHiddenBlocker .switchArea input[type="checkbox"]:checked +label { - border-color : #6666ff; /* 選択タブの枠線 */ + background-color : #726C9F; + color : white; + box-shadow : 0px 2px 5px 2px rgba(0, 0, 0, 0.36) inset; } -/* === 表示する文字(標準) ================================ */ -#ndHiddenBlocker .switchArea label span:after { - content : "OFF"; /* 表示する文字 */ - padding : 0 0 0 28px; /* 表示する位置 */ - color : rgba(0, 0, 0, 0.36); /* 文字色 */ +/* === タグ登録エリア ============================== */ +#ndHiddenBlocker .registerArea { } -/* === 表示する文字(ONのとき) ============================ */ -#ndHiddenBlocker .switchArea input[type="checkbox"]:checked + label span:after { - content : "ON"; /* 表示する文字 */ - padding : 0 28px 0 0; /* 表示する位置 */ - color : #6666ff; /* 文字色 */ +#ndHiddenBlocker .registerArea input[type="text"] { + border-width : 1px solid rgba(0, 0, 0, 0.36); + padding : 4px 8px; + font-size : 12px; + border : 2px solid #ddd; /*枠線*/ + border-radius : 3px; /*ボックス角の丸み*/ + box-sizing : border-box; /*横幅の解釈をpadding, borderまでとする*/ + width : 156px; } -/* === 丸部分のSTYLE(標準) =============================== */ -#ndHiddenBlocker .switchArea #swImg { - position : absolute; /* 親要素からの相対位置*/ - width : 40px; /* 丸の横幅 */ - height : 40px; /* 丸の高さ */ - background : rgba(0, 0, 0, 0.36); /* カーソルタブの背景 */ - top : 4px; /* 親要素からの位置 */ - left : 4px; /* 親要素からの位置 */ - border-radius : 20px; /* 角丸 */ - transition : .2s; /* 滑らか変化 */ +#ndHiddenBlocker .registerArea button { + border-width : 1px solid rgba(0, 0, 0, 0.36); + padding : 2px 10px; + font-size : 12px; + border : 2px solid #ddd; /*枠線*/ + border-radius : 3px; /*ボックス角の丸み*/ + background-color : #726C9F; + color : white; + cursor : pointer; } -/* === 丸部分のSTYLE(ONのとき) =========================== */ -#ndHiddenBlocker .switchArea input[type="checkbox"]:checked ~ #swImg { - transform : translateX(66px); /* 丸も右へ移動 */ - background : #6666ff; /* カーソルタブの背景 */ +#ndHiddenBlocker .registerArea ul { + list-style-type : none; + margin : 5px 0; + padding : 0; } -#ndHiddenBlocker .text { - text-align: center; - font-size: medium; - font-family: sans-serif; +#ndHiddenBlocker .registerArea ul li { + display : inline-block; + border : 2px solid #726C9F; + border-radius : 5px; + background-color : white; + padding : 0 4px; + margin : 4px 2px 2px 0px; + font-size : 10px; + cursor : pointer; + user-select : none; } -#ndHiddenBlocker .topBox { - width: 200px; - height: 40px; - background : #6666ff; +#ndHiddenBlocker .registerArea small { + font-size : 12px; + color : #666666; + margin-top : 5px; } -#ndHiddenBlocker .topText { - text-align: center; - color: azure; - font-size: large; - padding: 10px; - font-family: 'Roboto', sans-serif; -} \ No newline at end of file diff --git a/html/popup.html b/html/popup.html index 4e68921..0aa9762 100644 --- a/html/popup.html +++ b/html/popup.html @@ -8,25 +8,35 @@ +
- ND hidden Blocker + ND Hidden Blocker
-
鍵ルームを非表示にする
-
- - -
-
+
-
満室ルームを非表示にする
-
- - -
-
+
非表示にするルームを選択
+
+ + +
+
+ + +
+ +
上位に表示するタグを登録
+
+ + +
    + ※登録タグをクリックすると登録解除 +
    + +
    
    +    
    diff --git a/js/popup.js b/js/popup.js index 5f2dc94..0409971 100644 --- a/js/popup.js +++ b/js/popup.js @@ -1,8 +1,12 @@ ////////////////////////////////////////////////////////////////////////////////// -// Constants +// Constants and Global Variables const PEOPLE_MAX = 5; const EID_CHECKBOX_LOCKEDROOM = 'cbLockedRoom' const EID_CHECKBOX_NO_VACANCY_ROOM = 'cbNoVacancyRoom' +const EID_TEXT_REGISTER = 'textRegister' +const EID_BUTTON_REGISTER = 'btnRegister' +const EID_LIST_TAG = 'listTag' +var LocalStorageCache = null; ////////////////////////////////////////////////////////////////////////////////// // Convenience Functions @@ -15,12 +19,30 @@ const EID_CHECKBOX_NO_VACANCY_ROOM = 'cbNoVacancyRoom' function setLocalStorageObject(key, value, func) { let objToSet = {}; objToSet[key] = value; - chrome.storage.sync.set(objToSet, function(){ + chrome.storage.sync.set(objToSet, function () { console.log(`Set an object to the local storage: { ${key} : ${value} }`); func(); }); } +/** + * ページをリロードする + */ +function reloadPage() { + chrome.tabs.getSelected(null, function (tab) { + const code = 'window.location.reload();'; + chrome.tabs.executeScript(tab.id, { code: code }); + }); +} + +/** + * タグをリストに追加 (見た目だけ) + * @param {String} tag + */ +function addTagToList(tag) { + $(`#${EID_LIST_TAG}`).append(`
  • ${tag}`); +} + /** * チェックボックスの状態が変更されたときのイベント */ @@ -28,18 +50,56 @@ function onChangedCheckboxStatus() { // Local Storage を更新してページをリロード const key = $(this).attr('id'); const value = $(this).prop("checked"); - setLocalStorageObject(key, value, function () { - chrome.tabs.getSelected(null, function (tab) { - const code = 'window.location.reload();'; - chrome.tabs.executeScript(tab.id, { code: code }); - }); - }); + setLocalStorageObject(key, value, reloadPage); +} + +/** + * タグ登録ボタンがクリックされたときのイベント + */ +function onClickTagRegisterButton() { + const inputElem = $(`#${EID_TEXT_REGISTER}`); + const tag = inputElem.val(); + if (!tag) { return; } + + // テキストフィールドの中を空にする + inputElem.val(''); + + // ul 要素を追加(タグリスト) + addTagToList(tag); + + // Local Storage にタグを保存 + let tagsArray = LocalStorageCache[EID_LIST_TAG]; + if (!tagsArray) { tagsArray = []; } + if (tagsArray.indexOf(tag) === -1) { + tagsArray.push(tag); + } + setLocalStorageObject(EID_LIST_TAG, tagsArray, reloadPage); +} + +/** + * 登録済みタグがクリックされたときのイベント + */ +function onClickRegiteredTag() { + const tag = $(this).data('tag'); + if (!tag) { return; } + + // タグをリストから削除 + $(this).remove(); + + // Local Storage からタグを削除 + let tagsArray = LocalStorageCache[EID_LIST_TAG]; + if (!tagsArray) { tagsArray = []; } + const indexToRemove = tagsArray.indexOf(tag); + if (indexToRemove !== -1) { + tagsArray.splice(indexToRemove, 1); + } + setLocalStorageObject(EID_LIST_TAG, tagsArray, reloadPage); } /** * DOM を編集して部屋のリストを絞り込む * @param {Object} conditions - */ + */ let isFirstTime = true; function filterRoomBox(conditions) { if (!$('#moreroom').length) { return; } @@ -54,9 +114,8 @@ function filterRoomBox(conditions) { clearInterval(intervalId); - // Counter for debug - let lockedRoomCount = 0; - let noVacancyRoomCount = 0; + // for sorting + let highPriorityRooms = []; $('.roomItem').each(function (index, element) { @@ -65,8 +124,7 @@ function filterRoomBox(conditions) { const imgPath = $(element).find('img').prop('src'); if (imgPath.match(/_lock/)) { $(element).css('display', 'none'); - lockedRoomCount++; - // return; カウント用にあえてリターンしない + return; } } @@ -76,16 +134,50 @@ function filterRoomBox(conditions) { const peopleNum = parseInt(peopleStr.replace(/[^0-9]/g, '')); if (peopleNum === PEOPLE_MAX) { $(element).css('display', 'none'); - noVacancyRoomCount++; - // return; カウント用にあえてリターンしない + return; + } + } + + // listTag - 登録タグのついている部屋を上位に表示 + const listTagCondition = conditions[EID_LIST_TAG]; + if (listTagCondition) { + if ($(element).data('sorted')) { + // 既にソートされた Room は何もしない + } else { + // まだソートされていない Room + let containsAtLeastOne = false; // 該当タグが最低 1 つ含まれているか + const roomTagElems = $(element).find('.roomtag'); + for (let i = 0; i < roomTagElems.length; i++) { + const roomTagElem = $(roomTagElems[i]); + const targetTag = roomTagElem.text(); + listTagCondition.forEach(tag => { + if (targetTag.indexOf(tag) !== -1) { + containsAtLeastOne = true; + roomTagElem.css('border-color', '#ff1493'); + return; + } + }); + } + if (containsAtLeastOne) { + // ソート対称 + highPriorityRooms.unshift(element) + $(element).data('sorted', 1); + } else { + // ソート非対称 + $(element).data('sorted', 0); + } } } }); + const roomBox = $('#containerRoom > ul')[0]; + for (let i = 0; i < highPriorityRooms.length; i++) { + // 先頭に移動 + $(roomBox).prepend(highPriorityRooms[i]); + } + if (isFirstTime) { - console.log('RoomBox was filtered:'); - console.log('Locked Room: ' + !!conditions[EID_CHECKBOX_LOCKEDROOM] + ` (${lockedRoomCount} rooms)`); - console.log('No Vacancy Room: ' + !!conditions[EID_CHECKBOX_NO_VACANCY_ROOM] + ` (${noVacancyRoomCount} rooms)`); + console.log('RoomBox was filtered.'); isFirstTime = false; } @@ -96,21 +188,25 @@ function filterRoomBox(conditions) { // Initializer $(function () { - // 初期化対象チェックボックスの Element ID - const targetElemIds = [ - EID_CHECKBOX_LOCKEDROOM, - EID_CHECKBOX_NO_VACANCY_ROOM - ]; - // 対応するフィルター条件 let filterConditions = {}; + // 初期化要素に関連した Local Storage のキー + const storageKeys = [ + EID_CHECKBOX_LOCKEDROOM, + EID_CHECKBOX_NO_VACANCY_ROOM, + EID_LIST_TAG + ]; + // Local Storage から直近の値を取得して View を更新 - chrome.storage.sync.get(targetElemIds, function (result) { + chrome.storage.sync.get(storageKeys, function (result) { console.log('Current local storage object is below:'); console.log(result); - targetElemIds.forEach(elemId => { + LocalStorageCache = result; + + // 各チェックボックスの初期化 + [EID_CHECKBOX_LOCKEDROOM, EID_CHECKBOX_NO_VACANCY_ROOM].forEach(elemId => { // 対象の条件を false で初期化 filterConditions[elemId] = false; @@ -132,14 +228,26 @@ $(function () { filterConditions[elemId] = localStorageVal; }); + // タグリストの初期化 + const savedTagList = result[EID_LIST_TAG]; + filterConditions[EID_LIST_TAG] = []; + if (savedTagList) { + savedTagList.forEach(tag => { addTagToList(tag); }); + filterConditions[EID_LIST_TAG] = savedTagList; + } + + // タグ登録ボタンのイベントをバインド + $(`#${EID_BUTTON_REGISTER}`).on('click', onClickTagRegisterButton); + + // ul 要素(タグリスト)のイベントをバインド + $(document).on("click", `#${EID_LIST_TAG} li`, onClickRegiteredTag); + // 実際に指定された条件で部屋のリストをフィルターする filterRoomBox(filterConditions); // 非同期更新用に 200 [sec] 毎にフィルターをかけなおすようにしておく setInterval(function () { - targetElemIds.forEach(elemId => { - filterRoomBox(filterConditions); - }); + filterRoomBox(filterConditions); }, 200); }); }); \ No newline at end of file