From 8928489390c0a79a6cfd7232f7ef96f8cb881add Mon Sep 17 00:00:00 2001 From: ytak01 Date: Mon, 1 Jul 2024 12:49:36 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=E3=81=A4=E3=81=8E=E3=81=9F=E3=81=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content.js | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++ manifest.json | 3 +- 2 files changed, 208 insertions(+), 1 deletion(-) diff --git a/content.js b/content.js index 27f2d9a..c992498 100644 --- a/content.js +++ b/content.js @@ -149,3 +149,209 @@ class VinePlusPlus { // let's rock, baby (new VinePlusPlus()).InstallUI(); + +let exclusionWords = new Array(""); + +window.onload = function() { + + // 商品一覧を取得 + const itemContainer = document.querySelector('#vvp-items-grid'); + if (!itemContainer){ + return; + } + const itemTiles= itemContainer.querySelectorAll('.vvp-item-tile'); + + // 除外ワードを取得 + const exclusionWordStr = localStorage.vine_exclusionWord; + exclusionWords = exclusionWordStr?.split(','); + + createExclusionWordForm(); + + for (const itemTile of itemTiles) { + settingItemTile(itemTile); + } + + checkForSeenItem(); + + unsetGridHeight(); +} + +/** + * indexedDBに接続して、既に確認したことのある商品かチェック + */ +function checkForSeenItem() { + + // indexedDBに接続 + const openReq = indexedDB.open('VineAddon'); + openReq.onupgradeneeded = function(event) { + let db = event.target.result; + + db.createObjectStore('Item', {keyPath: 'asin'}); + } + + openReq.onsuccess = function(event) { + + // Itemオブジェクトストアを開く + let db = event.target.result; + let trans = db.transaction('Item', 'readwrite'); + let itemStore = trans.objectStore('Item'); + + // 画面に表示されている商品をチェック + const itemButtons = document.querySelectorAll('.vvp-details-btn'); + for (const itemButton of itemButtons) { + const asin = itemButton.querySelector('.a-button-input').dataset.asin; + + // DBに登録済か確認 + const getReq = itemStore.get(asin); + getReq.onsuccess = function(event) { + + if (!!event.target.result) { + // 登録済なら背景色を白にする + const itemTile = document.querySelector(`[data-asin="${event.target.result.asin}"]`).parentElement.parentElement.parentElement.parentElement; + itemTileback = itemTile; + if (itemTile.style.backgroundColor != 'gainsboro') { + itemTile.style.backgroundColor = 'white'; + } + } + const itemTile2 = document.querySelector(`[data-asin="${asin}"]`).parentElement.parentElement.parentElement.parentElement; + if (itemTile2.style.backgroundColor == 'snow') { + itemTile2.style.backgroundColor = 'antiquewhite'; + } + } + + // DBにasinを登録 + itemStore.put({asin: asin}); + } + } +} + +/** + * itemTileに色々処理 + */ +function settingItemTile(itemTile) { + + // フルネームを表示するspanを別途追加 + const truncateFull = itemTile.querySelector('.a-truncate-full'); + + // 既に処理済のitemTileの場合、スキップ + if (!truncateFull) { return; } + + let span = document.createElement('span'); + span.textContent = truncateFull.textContent; + itemTile.querySelector('.a-link-normal').append(span); + + // 名前部分の高さ上限を解除 + itemTile.style.maxHeight = null; + + // 既存の名前spanを削除 + truncateFull.remove(); + const truncateCut = itemTile.querySelector('.a-truncate-cut'); + truncateCut.remove(); + + // 除外ワードが含まれているか確認 + for (const exclusionWord of exclusionWords) { + if (exclusionWord) { + if (span.textContent.toLowerCase().includes(exclusionWord.toLowerCase())) { + // 背景色をグレーにして、一番下に並び替える + itemTile.style.backgroundColor = 'gainsboro'; + itemTile.remove(); + document.querySelector('#vvp-items-grid').append(itemTile); + break; + } else { + itemTile.style.backgroundColor = 'snow'; // 背景色を設定(チェック済の商品の場合、後で白に上書きする) + } + } + } +} + +/** + * 除外ワードフォームの作成 + */ +function createExclusionWordForm() { + + // テキストインプット + let input = document.createElement('input'); + input.onblur = onblurExclusionWord; + + // 折りたたみ + let details = document.createElement('details'); + details.style.marginTop = '7px'; + let summary = document.createElement('summary'); + summary.textContent = '除外ワード'; + details.append(summary); + details.append(input); + + // 除外ワード一覧 + let wordContainer = document.createElement('div'); + wordContainer.setAttribute('id', 'vine-addon_word-container'); + wordContainer.style.marginTop = '4px'; + + details.append(wordContainer); + createWordButtons(wordContainer); + + let bsContainer = document.querySelector('.vvp-items-button-and-search-container'); + bsContainer.style.display = 'block' + bsContainer.append(details); +} + +/** + * 除外ワードボタンを生成 + */ +function createWordButtons(wordContainer) { + + // 一覧をクリア + const clone = wordContainer.cloneNode(false); + wordContainer.parentNode.replaceChild(clone, wordContainer); + + // ボタン生成 + for (const exclusionWord of exclusionWords) { + let button = document.createElement('button'); + button.style.margin = '2px'; + button.style.backgroundColor = 'white'; + button.style.border = '1px solid silver'; + button.style.borderRadius = '5px'; + button.textContent = exclusionWord; + button.onclick = onclickWordButton; + clone.append(button); + } +} + +/** + * 除外ワードを登録 + */ +function onblurExclusionWord(event) { + + if (!event.target.value) { + return; + } + + exclusionWords.push(event.target.value); + localStorage.vine_exclusionWord = exclusionWords.join(','); + + createWordButtons(document.querySelector('#vine-addon_word-container')); + + event.target.value = ''; +} + +/** + * 除外ワードを削除 + */ +function onclickWordButton(event) { + exclusionWords = exclusionWords.filter(word => word != event.target.textContent); + + localStorage.vine_exclusionWord = exclusionWords.join(','); + + createWordButtons(document.querySelector('#vine-addon_word-container')); +} + +/** + * 高さの上限設定を解除 + */ +function unsetGridHeight() { + + let grids = document.querySelectorAll('.vvp-item-product-title-container'); + for (let grid of grids) { + grid.style.height = 'auto'; + } +} + diff --git a/manifest.json b/manifest.json index c51048b..3ca7043 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Vine++", - "version": "0.4", + "version": "0.5", "description": "A little helper extension for Amazon Vine users", "author": "Daniel Glazman", "icons": { @@ -21,6 +21,7 @@ , "https://www.amazon.de/vine/vine-items*" , "https://www.amazon.es/vine/vine-items*" , "https://www.amazon.co.uk/vine/vine-items*" + , "https://www.amazon.co.jp/vine/vine-items*" ], "js": ["content.js"] } From 4dc9fce7c0121f2f9c4b4a726d82806201b2b996 Mon Sep 17 00:00:00 2001 From: ytak01 Date: Tue, 2 Jul 2024 07:18:52 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=E3=81=A1=E3=82=87=E3=81=84=E5=A4=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/content.js b/content.js index c992498..a248c22 100644 --- a/content.js +++ b/content.js @@ -200,6 +200,7 @@ function checkForSeenItem() { const itemButtons = document.querySelectorAll('.vvp-details-btn'); for (const itemButton of itemButtons) { const asin = itemButton.querySelector('.a-button-input').dataset.asin; + const itemTile = document.querySelector(`[data-asin="${asin}"]`).parentElement.parentElement.parentElement.parentElement; // DBに登録済か確認 const getReq = itemStore.get(asin); @@ -207,15 +208,13 @@ function checkForSeenItem() { if (!!event.target.result) { // 登録済なら背景色を白にする - const itemTile = document.querySelector(`[data-asin="${event.target.result.asin}"]`).parentElement.parentElement.parentElement.parentElement; - itemTileback = itemTile; if (itemTile.style.backgroundColor != 'gainsboro') { itemTile.style.backgroundColor = 'white'; } } - const itemTile2 = document.querySelector(`[data-asin="${asin}"]`).parentElement.parentElement.parentElement.parentElement; - if (itemTile2.style.backgroundColor == 'snow') { - itemTile2.style.backgroundColor = 'antiquewhite'; + + if (itemTile.style.backgroundColor == 'snow') { + itemTile.style.backgroundColor = 'antiquewhite'; } } From 94f783f589a5fe84b5b65d76a382625c37417f87 Mon Sep 17 00:00:00 2001 From: ytak01 Date: Tue, 2 Jul 2024 19:09:50 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=E3=81=84=E3=82=8D=E3=81=84=E3=82=8D?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/content.js b/content.js index a248c22..a1ed22c 100644 --- a/content.js +++ b/content.js @@ -163,7 +163,10 @@ window.onload = function() { // 除外ワードを取得 const exclusionWordStr = localStorage.vine_exclusionWord; - exclusionWords = exclusionWordStr?.split(','); + if (typeof exclusionWordStr !== "undefined") + { + exclusionWords = exclusionWordStr?.split(','); + } createExclusionWordForm(); @@ -251,6 +254,8 @@ function settingItemTile(itemTile) { for (const exclusionWord of exclusionWords) { if (exclusionWord) { if (span.textContent.toLowerCase().includes(exclusionWord.toLowerCase())) { + span.innerHTML = span.textContent.replaceAll(exclusionWord, '' + exclusionWord + ''); + // 背景色をグレーにして、一番下に並び替える itemTile.style.backgroundColor = 'gainsboro'; itemTile.remove(); @@ -276,7 +281,7 @@ function createExclusionWordForm() { let details = document.createElement('details'); details.style.marginTop = '7px'; let summary = document.createElement('summary'); - summary.textContent = '除外ワード'; + summary.textContent = 'Exclude Word'; details.append(summary); details.append(input); From fa8dd53e936d1c8ee188adb65cb2770273d112bc Mon Sep 17 00:00:00 2001 From: ytak01 Date: Thu, 23 Oct 2025 06:50:26 +0900 Subject: [PATCH 4/4] Refactor VinePlusPlus class and UI installation --- content.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content.js b/content.js index a1ed22c..83d9d8e 100644 --- a/content.js +++ b/content.js @@ -74,7 +74,7 @@ class VinePlusPlus { aSpan.parentNode.parentNode.setAttribute("title", aSpan.textContent.trim()); }); - const navigation = document.querySelector("div[role=navigation]:has(ul.a-pagination)"); + const navigation = document.querySelector(":is(nav, div[role=navigation]):has(ul.a-pagination)"); if (navigation) { const navigationClone = navigation.cloneNode(true); const parent = navigation.parentNode; @@ -359,3 +359,4 @@ function unsetGridHeight() { } } +