- // ==UserScript==
- // @name ExHentai Viewer
- // @namespace Violentmonkey Scripts
- // @description manage your favorite tags, enhance searching, improve comic page
- // @description:zh-CN 管理标签,增强搜索,改进漫画页面
- // @match *://exhentai.org/*
- // @match *://e-hentai.org/*
- // @grant GM_setValue
- // @grant GM_getValue
- // @version 1.2.0
- // ==/UserScript==
- /*
- * To-do:
- * 1. preload images?
- */
-
- const currentVersion = '1.2.0';
- const sortFilters = false;
- const $ = selector => document.querySelector(selector);
- const $$ = selector => document.querySelectorAll(selector);
- const create = tag => document.createElement(tag);
- let data = {
- custom_filter: GM_getValue('custom_filter', {}),
- script_config: GM_getValue('script_config', {}),
- tag_pref: GM_getValue('tag_pref', { liked_tags: [], disliked_tags: [] })
- };
-
- init();
-
- function init() {
- // upgrade and load script config
- loadScriptData();
- // router
- const url = window.location.href;
- if (url.includes('/s/')) {
- // comic page
- EHViewer('s');
- } else if (url.includes('/mpv')) {
- // multi page mode
- EHViewer('mpv');
- } else if (url.includes('/g/')) {
- // gallery page
- handleGallery();
- } else if ($('#searchbox')) {
- // add panel below the searchbox
- handleSearchBox();
- } else if (url.includes('/gallerytorrents.php')) {
- // show magnet link
- showMagnetLink();
- }
-
- // add EHV setting button
- let ehvSettingBtn = create('div');
- ehvSettingBtn.innerHTML = '<a href="#">EHV Settings</a>';
- ehvSettingBtn.onclick = createSettingPanel;
- $('#nb').append(ehvSettingBtn);
- $('#nb').style.maxWidth = 'max-content';
-
- // highlight tags
- highlightTags();
- }
-
- function loadScriptData() {
- switch (data.script_config.current_version) {
- // don't break, just go through the flow to upgrade script data by version
- case undefined:
- // just install
- default:
- data.script_config.current_version = currentVersion;
- GM_setValue('custom_filter', data.custom_filter);
- GM_setValue('script_config', data.script_config);
- }
- }
-
- function changeStyle(css, mode, id = 'ehv-style') {
- let cssEl = $('#' + id);
- if (!cssEl) {
- cssEl = create('style');
- cssEl.type = 'text/css';
- cssEl.id = id;
- document.head.append(cssEl);
- }
- switch (mode) {
- case 'add':
- cssEl.innerHTML += css;
- break;
- case 'replace':
- cssEl.innerHTML = css;
- break;
- }
- }
-
- function addBtnContainer() {
- let btnStyle = `
- #ehv-btn-c{
- text-align: center;
- list-style: none;
- position: fixed;
- bottom: 30px;
- right: 30px;
- z-index: 999;
- }
- .ehv-btn {
- line-height: 32px;
- font-size: 16px;
- padding: 2px;
- margin: 5px;
- color: #233;
- position: relative;
- width: 32px;
- height: 32px;
- border: none;
- border-radius: 50%;
- box-shadow: 0 0 3px 0 #0006;
- cursor: pointer;
- user-select: none;
- outline: none;
- background-color: #fff;
- background-repeat: no-repeat;
- background-position: center;
- }
- .ehv-btn:hover{
- box-shadow: 0 0 3px 1px #0005!important;
- }
- .ehv-btn:active {
- top: 1px;
- box-shadow: 0 0 1px 1px #0004!important;
- }`;
- let btnContainer = create('ul');
- btnContainer.id = 'ehv-btn-c';
- document.body.append(btnContainer);
- changeStyle(btnStyle, 'add', 'ehv-btn-c-style');
- return btnContainer;
- }
-
- function addBtn(btn, container) {
- let btnEl = create('li');
- if (btn.icon.startsWith('data:image')) {
- btnEl.style.backgroundImage = "url('" + btn.icon + "')";
- } else {
- btnEl.innerHTML = btn.icon;
- }
- btnEl.classList.add('ehv-btn');
- btnEl.addEventListener(btn.event, btn.cb);
- container.append(btnEl);
- return btnEl;
- }
-
- function EHViewer(mode) {
- const host = window.location.host;
- const svgIcons = {
- autofit:
- 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path d="M8 3V5H4V9H2V3H8ZM2 21V15H4V19H8V21H2ZM22 21H16V19H20V15H22V21ZM22 9H20V5H16V3H22V9Z" fill="rgba(120,120,120,1)"></path></svg>',
- zoomIn: 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path d="M18.031 16.6168L22.3137 20.8995L20.8995 22.3137L16.6168 18.031C15.0769 19.263 13.124 20 11 20C6.032 20 2 15.968 2 11C2 6.032 6.032 2 11 2C15.968 2 20 6.032 20 11C20 13.124 19.263 15.0769 18.031 16.6168ZM16.0247 15.8748C17.2475 14.6146 18 12.8956 18 11C18 7.1325 14.8675 4 11 4C7.1325 4 4 7.1325 4 11C4 14.8675 7.1325 18 11 18C12.8956 18 14.6146 17.2475 15.8748 16.0247L16.0247 15.8748ZM10 10V7H12V10H15V12H12V15H10V12H7V10H10Z" fill="rgba(120,120,120,1)"></path></svg>',
- zoomOut:
- 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path d="M18.031 16.6168L22.3137 20.8995L20.8995 22.3137L16.6168 18.031C15.0769 19.263 13.124 20 11 20C6.032 20 2 15.968 2 11C2 6.032 6.032 2 11 2C15.968 2 20 6.032 20 11C20 13.124 19.263 15.0769 18.031 16.6168ZM16.0247 15.8748C17.2475 14.6146 18 12.8956 18 11C18 7.1325 14.8675 4 11 4C7.1325 4 4 7.1325 4 11C4 14.8675 7.1325 18 11 18C12.8956 18 14.6146 17.2475 15.8748 16.0247L16.0247 15.8748ZM7 10H15V12H7V10Z" fill="rgba(120,120,120,1)"></path></svg>',
- prevPage:
- 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path d="M10.8284 12.0007L15.7782 16.9504L14.364 18.3646L8 12.0007L14.364 5.63672L15.7782 7.05093L10.8284 12.0007Z" fill="rgba(120,120,120,1)"></path></svg>',
- nextPage:
- 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path d="M13.1714 12.0007L8.22168 7.05093L9.63589 5.63672L15.9999 12.0007L9.63589 18.3646L8.22168 16.9504L13.1714 12.0007Z" fill="rgba(120,120,120,1)"></path></svg>',
- reload: 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path d="M5.46257 4.43262C7.21556 2.91688 9.5007 2 12 2C17.5228 2 22 6.47715 22 12C22 14.1361 21.3302 16.1158 20.1892 17.7406L17 12H20C20 7.58172 16.4183 4 12 4C9.84982 4 7.89777 4.84827 6.46023 6.22842L5.46257 4.43262ZM18.5374 19.5674C16.7844 21.0831 14.4993 22 12 22C6.47715 22 2 17.5228 2 12C2 9.86386 2.66979 7.88416 3.8108 6.25944L7 12H4C4 16.4183 7.58172 20 12 20C14.1502 20 16.1022 19.1517 17.5398 17.7716L18.5374 19.5674Z" fill="rgba(120,120,120,1)"></path></svg>',
- gallery:
- 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path d="M5.82843 6.99955L8.36396 9.53509L6.94975 10.9493L2 5.99955L6.94975 1.0498L8.36396 2.46402L5.82843 4.99955H13C17.4183 4.99955 21 8.58127 21 12.9996C21 17.4178 17.4183 20.9996 13 20.9996H4V18.9996H13C16.3137 18.9996 19 16.3133 19 12.9996C19 9.68584 16.3137 6.99955 13 6.99955H5.82843Z" fill="rgba(120,120,120,1)"></path></svg>'
- };
- let css = '';
- let btnContainer = addBtnContainer();
- let currentScale = 1;
- let autofitEnable = true;
-
- switch (mode) {
- case 's':
- css += `
- #i1{
- width:98%!important;
- max-width:98%!important;
- min-width:800px;
- background-color: inherit!important;
- border: none!important
- }
- #img{
- max-width:none!important;
- max-height:none!important;
- background-color: #4f535b!important;
- padding: 8px;
- border: 1px solid #000;
- border-radius: 2px;
- }
- h1, #i2, #i5, #i6, #i7, .ip, .sn{
- display:none!important;
- }
- ::-webkit-scrollbar{
- display:none;
- }
- html{
- scrollbar-width: none;
- }`;
- // add btns
- [
- { icon: svgIcons.autofit, event: 'mousedown', cb: autofit },
- { icon: svgIcons.zoomIn, event: 'mousedown', cb: e => zoomer(zoomInS) },
- { icon: svgIcons.zoomOut, event: 'mousedown', cb: e => zoomer(zoomOutS) },
- { icon: svgIcons.prevPage, event: 'click', cb: prevPage },
- { icon: svgIcons.nextPage, event: 'click', cb: nextPage },
- { icon: svgIcons.reload, event: 'click', cb: e => $('#loadfail').click() },
- { icon: svgIcons.gallery, event: 'click', cb: e => $('div.sb>a').click() }
- ].forEach(v => addBtn(v, btnContainer));
- // handle key events
- document.body.addEventListener('keydown', e => {
- switch (e.key) {
- case '=':
- zoomInS(0.1);
- break;
- case '-':
- zoomOutS(0.1);
- break;
- case ',':
- window.scroll(0, 0);
- break;
- case '.':
- window.scroll(0, window.innerHeight);
- break;
- case '[':
- window.scrollBy(0, -window.innerHeight * 0.3);
- break;
- case ']':
- window.scrollBy(0, window.innerHeight * 0.3);
- break;
- }
- });
- // set scale on page load
- setNewPage();
- // set scale on img load
- let observer = new MutationObserver(setNewPage);
- observer.observe($('#i3'), { attributes: false, childList: true, subtree: false });
- break;
- case 'mpv':
- css += '#pane_images_inner>div{margin:auto;}';
- // add btns
- [
- { icon: svgIcons.zoomIn, event: 'mousedown', cb: e => zoomer(zoomInMpv) },
- { icon: svgIcons.zoomOut, event: 'mousedown', cb: e => zoomer(zoomOutMpv) }
- ].forEach(v => addBtn(v, btnContainer));
- document.body.addEventListener('keydown', e => {
- switch (e.key) {
- case '=':
- zoomInMpv(0.1);
- break;
- case '-':
- zoomOutMpv(0.1);
- break;
- }
- });
- break;
- }
-
- // add style
- if (data.script_config.hide_button) {
- css += `
- #ehv-btn-c{
- padding: 80px 30px 30px 80px;
- bottom: 0!important;
- right: -80px!important;
- transition-duration: 300ms;
- }
- #ehv-btn-c:hover{
- padding: 80px 30px 30px 20px!important;
- right: 0!important;
- }`;
- }
- css += '.ehv-btn{background-color: #44454B!important;}';
- if (host === 'e-hentai.org') {
- // btn color
- css = css.replaceAll('#44454B', '#D3D0D1');
- // page bg & border (for mode 's')
- css = css.replace('#4f535b', '#EDEBDF').replace('1px solid #000', '1px solid #5C0D12');
- }
- changeStyle(css, 'replace', 'ehv-style');
-
- // === functions ===
- function autofit() {
- autofitEnable = true;
- const img = $('#img');
- const imgRatio = img.height / img.width;
- const windowRatio = window.innerHeight / window.innerWidth;
- if (imgRatio > windowRatio) {
- // img thinner than window
- currentScale = (window.innerHeight - 25) / img.height;
- } else {
- //img wider than window
- currentScale = (window.innerWidth - 25) / img.width;
- }
- window.scrollTo(0, 0);
- zoom4S();
- }
- function zoomer(cb) {
- // long press to trigger continuous scaling(zoomTimeout > zoomInterval)
- let zoomInterval = -1;
- let zoomTimeout = setTimeout(function () {
- zoomInterval = setInterval(cb, 100);
- }, 800);
- document.addEventListener(
- 'mouseup',
- e => {
- if (zoomInterval === -1) {
- cb(0.1);
- clearTimeout(zoomTimeout);
- } else {
- clearInterval(zoomInterval);
- }
- },
- { once: true }
- );
- }
- function prevPage() {
- const currentPage = $('.sn>span:first-child').innerText;
- currentPage !== '1' ? $('#prev').click() : alert('This is first page (⊙_⊙)');
- }
- function nextPage() {
- const currentPage = $('.sn span:first-child').innerText;
- const lastPage = $('.sn span:last-child').innerText;
- currentPage !== lastPage ? $('#next').click() : alert('This is last page (⊙ω⊙)');
- }
- function setNewPage() {
- // add page indicator
- let footer = $('#i4 > div:first-child');
- const currentPage = $('.sn span:first-child').innerText;
- const totalPage = $('.sn span:last-child').innerText;
- footer.innerHTML = currentPage + 'P / ' + totalPage + 'P :: ' + footer.innerText + ' :: ';
- // add origin source
- let imgLink = $('#i7>a');
- imgLink ? footer.append(imgLink) : (footer.innerHTML += 'No download');
- if (autofitEnable) {
- autofit();
- } else {
- // inherit the zoom scale of previous page
- zoom4S();
- }
- }
- function zoomInS(pace = 0.02) {
- autofitEnable = false;
- currentScale = 1 + pace;
- zoom4S();
- }
- function zoomOutS(pace = 0.02) {
- autofitEnable = false;
- const img = $('#img');
- currentScale = 1 - pace;
- zoom4S();
- }
- function zoom4S() {
- const img = $('#img');
- // img.style.width = currentScale * 100 + '%';
- img.style.width = img.width * currentScale + 'px';
- img.style.height = 'auto';
- }
- function zoomInMpv(pace = 0.02) {
- const maxWidth = Number($('#pane_images').style.width.replace('px', '')) - 20;
- const originalWidth = Number($('#image_1').style.maxWidth.replace('px', ''));
- currentScale = originalWidth * (1 + pace) < maxWidth ? currentScale + pace : currentScale;
- zoom4Mpv(originalWidth * currentScale);
- }
- function zoomOutMpv(pace = 0.02) {
- const minWidth = 200;
- const originalWidth = Number($('#image_1').style.maxWidth.replace('px', ''));
- currentScale = originalWidth * (currentScale - pace) > minWidth ? currentScale - pace : currentScale;
- zoom4Mpv(originalWidth * currentScale);
- }
- function zoom4Mpv(width) {
- let mpvStyle =
- 'img[id^="imgsrc"], div[id^="image"]{width:mpvWidth!important;height:auto!important; max-width:100%!important;min-width:200px!important}"';
- mpvStyle = mpvStyle.replace('mpvWidth', width + 'px');
- changeStyle(mpvStyle, 'replace', 'custom-width');
- }
- }
-
- function handleGallery() {
- // add searchbox
- let searchBox = create('form');
- searchBox.innerHTML = `
- <p class="nopm">
- <input type="text" id="f_search" name="f_search" placeholder="Search Keywords" value="" size="60">
- <input type="submit" name="f_apply" value="Search">
- </p>`;
- searchBox.setAttribute(
- 'style',
- 'display: none; width: 720px; margin: 10px auto; border: 2px ridge black; padding: 10px;'
- );
- searchBox.setAttribute('action', 'https://' + window.location.host + '/');
- searchBox.setAttribute('method', 'get');
- $('.gm').before(searchBox);
-
- // add btn to show/hide searchbox
- let tbody = $('#taglist > table > tbody');
- tbody.innerHTML += `
- <tr>
- <td class="tc">EHV:</td>
- <td>
- <div id="ehv-panel-btn" class="gt" style="cursor:pointer">show panel</div>
- </td>
- </tr>`;
- $('#ehv-panel-btn').addEventListener('click', e => {
- const t = e.target;
- if (t.innerText == 'show panel') {
- searchBox.style.display = 'block';
- t.innerText = 'hide panel';
- } else {
- searchBox.style.display = 'none';
- t.innerText = 'show panel';
- }
- });
-
- // add panel
- setPanel();
-
- // add gallery tag to searchbox by right-click
- tbody.addEventListener('contextmenu', applyGalleryTag);
-
- function applyGalleryTag(e) {
- const t = e.target;
- if (t.tagName === 'A') {
- e.preventDefault();
- const searchInput = $('#f_search');
- let tag = t.href.split('/').pop().replaceAll('+', ' ');
- filter = `"${tag}" `;
- // add tailing space
- if (searchInput.value.length > 0 && searchInput.value.endsWith(' ') === false) searchInput.value += ' ';
- searchInput.value.includes(filter)
- ? (searchInput.value = searchInput.value.replace(filter, ''))
- : (searchInput.value += filter);
- }
- }
- }
-
- function handleSearchBox() {
- setPanel();
- const ehvPanel = $('#ehv-panel');
- if (data.script_config.hide_panel) {
- ehvPanel.style.display = 'none';
- const a = create('a');
- a.id = 'ehv-panel-btn';
- a.innerText = '[Show EHV Panel]';
- a.setAttribute('href', '#');
- a.setAttribute('style', 'margin-left: 1em;');
- a.addEventListener('click', function () {
- if (ehvPanel.style.display == 'none') {
- ehvPanel.style.display = 'block';
- a.innerText = '[Hide EHV Panel]';
- } else {
- ehvPanel.style.display = 'none';
- a.innerText = '[Show EHV Panel]';
- }
- });
- $$('#searchbox>form>div')[1].append(a);
- } else {
- $('#ehv-panel-btn') && $('#ehv-panel-btn').remove();
- }
- }
-
- function setPanel() {
- const container = $('#f_search').parentNode;
- const searchInput = $('#f_search');
-
- // set style
- const panelCss = `#ehv-panel > input[type="button"]{ margin: 2px; }`;
- let panelStyle = $('#panel-style');
- if (!panelStyle) {
- panelStyle = create('style');
- panelStyle.id = 'panel-style';
- panelStyle.textContent = panelCss;
- document.head.append(panelStyle);
- }
-
- let ehvPanel = $('#ehv-panel');
-
- if (ehvPanel) ehvPanel.remove();
-
- ehvPanel = document.createElement('div');
- ehvPanel.setAttribute('class', 'nopm');
- ehvPanel.setAttribute('id', 'ehv-panel');
- ehvPanel.setAttribute('style', 'padding-top:8px;');
- container.append(ehvPanel);
- // filter buttons
- for (let key in data.custom_filter) {
- let filterBtn = create('input');
- filterBtn.setAttribute('type', 'button');
- filterBtn.setAttribute('value', key);
- filterBtn.setAttribute('title', data.custom_filter[key].toString());
- filterBtn.addEventListener('click', applyFilter);
- filterBtn.addEventListener('contextmenu', removeFilter);
- if (isExist(data.custom_filter[key])) {
- filterBtn.setAttribute('style', 'filter: invert(20%);');
- } else {
- filterBtn.removeAttribute('style');
- }
- ehvPanel.append(filterBtn);
- }
- //new filter button
- let addFilterBtn = create('input');
- addFilterBtn.setAttribute('type', 'button');
- addFilterBtn.setAttribute('value', '+');
- addFilterBtn.addEventListener('click', addFilter);
- addFilterBtn.addEventListener('contextmenu', ehvSetting);
- ehvPanel.append(addFilterBtn);
-
- // enhace apply filter button
- const searchBtn = $('#f_search+input');
- searchBtn.addEventListener('contextmenu', newtabSearch);
- searchBtn.title = 'right click to search in new page';
-
- // === function ===
- function isExist(values) {
- const inputValue = searchInput.value;
- return values.every(v => inputValue.includes(v));
- }
- function applyFilter(e) {
- let t = e.target;
- let key = t.value;
- let values = data.custom_filter[key];
-
- // add tailing space
- if (searchInput.value.length > 0 && searchInput.value.endsWith(' ') === false) searchInput.value += ' ';
-
- if (isExist(values)) {
- values.forEach(v => (searchInput.value = searchInput.value.replaceAll(`"${v}" `, '')));
- t.removeAttribute('style');
- } else {
- values.forEach(v => (searchInput.value += `"${v}" `));
- t.setAttribute('style', 'filter: invert(20%);');
- }
- }
- function addFilter() {
- data.custom_filter = GM_getValue('custom_filter', {}); // get latest filter data
- const input = prompt('Add filter like format below', '[tag] or [name@tag] or [name@tag+tag+tag+tag]');
- const filterStr = input ? input.split('@') : '';
- let key, value;
- if (filterStr.length === 2) {
- key = filterStr[0];
- value = filterStr[1].split('+');
- data.custom_filter[key] = value;
- } else if (filterStr.length === 1 && filterStr[0] !== '') {
- key = value = filterStr[0];
- data.custom_filter[key] = [value];
- } else {
- alert('Invalid input...:(');
- return;
- }
- // sort filters by char codepoint
- if (sortFilters === true) {
- const newFilters = {};
- const sortedKeys = Object.keys(data.custom_filter).sort();
- for (let key of sortedKeys) {
- newFilters[key] = data.custom_filter[key];
- }
- data.custom_filter = newFilters;
- }
- GM_setValue('custom_filter', data.custom_filter);
- setPanel();
- }
- function ehvSetting(e) {
- e.preventDefault();
- data.script_config = GM_getValue('script_config', {}); // sync latest config data
- data.script_config.hide_panel = confirm('hide EHV panel by default?');
- data.script_config.hide_button = confirm(
- 'hide comic page buttons by default? (hover lower right corner to show)'
- );
- GM_setValue('script_config', data.script_config);
- handleSearchBox();
- }
- function removeFilter(e) {
- e.preventDefault();
- data.custom_filter = GM_getValue('custom_filter', {}); // get latest filter data
- if (confirm('Delete this tag?')) {
- let key = e.target.value;
- delete data.custom_filter[key];
- GM_setValue('custom_filter', data.custom_filter);
- setPanel();
- }
- }
- function newtabSearch(e) {
- e.preventDefault();
- const keyword = e.target.previousElementSibling.value;
- const url = `https://${location.host}/?f_search=${keyword}`;
- open(url);
- }
- }
-
- function showMagnetLink() {
- const links = $$('a');
- for (let link of links) {
- if (link.href.endsWith('.torrent')) {
- let magnetLink = create('a');
- let torrentHash = link.href.match(/[\w\d]{40}/)[0];
- magnetLink.href = `magnet:?xt=urn:btih:${torrentHash}&dn=${link.innerText}`;
- magnetLink.innerText = '[MAGNET]';
- link.before(magnetLink);
- let span = create('span');
- span.innerText = ' ';
- link.before(span);
- }
- }
- }
-
- function createSettingPanel() {
- // todo:
- // custom filter editor
- // hide ehv search panel by default
- // hide ehv sidebar buttons by default
- console.log('creating ehv setting panel');
- let container = create('div');
- container.innerHTML = `
- <div id="ehv-setting-panel" style="display: flex; flex-direction: column; gap:.5rem; background-color: #CCCE; border-radius: 3px; box-shadow: 0 0 3px 0 #0008; margin: 5rem auto; padding: 1rem; max-width: 50rem;">
- <span style="color:#233; text-align:left; font-size:12px;">liked tags:</span>
- <textarea id="ehv-liked-tags" style="padding: .5em;" placeholder="enter tags you like here, separated by comma"></textarea>
- <span style="color:#233; text-align:left; font-size:12px;">disliked tags:</span>
- <textarea id="ehv-disliked-tags" style="padding: .5em;" placeholder="enter tags you don't like here, separated by comma"></textarea>
- <div style="text-align: right;">
- <button id="ehv-save-btn">save</button>
- <button id="ehv-cancel-btn">cancel</button>
- <div>
- </div>`;
- container.setAttribute(
- 'style',
- 'background-color: transparent; width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; z-index: 9999'
- );
-
- const likedTagsInput = container.querySelector('#ehv-liked-tags');
- const dislikedTagsInput = container.querySelector('#ehv-disliked-tags');
- const saveBtn = container.querySelector('#ehv-save-btn');
- const cancelBtn = container.querySelector('#ehv-cancel-btn');
-
- // get latest tag_pref value
- data.tag_pref = GM_getValue('tag_pref', { liked_tags: [], disliked_tags: [] });
-
- likedTagsInput.value = data.tag_pref.liked_tags.join(',');
- dislikedTagsInput.value = data.tag_pref.disliked_tags.join(',');
-
- saveBtn.onclick = () => {
- data.tag_pref.liked_tags = likedTagsInput.value.split(',');
- data.tag_pref.disliked_tags = dislikedTagsInput.value.split(',');
- highlightTags(data);
- GM_setValue('tag_pref', data.tag_pref);
- container.remove();
- };
- cancelBtn.onclick = () => container.remove();
-
- document.body.append(container);
- }
-
- function highlightTags() {
- // highlight tags
- let tagEls = $$('.gt, .gtl');
- const likedTags = data.tag_pref.liked_tags;
- const dislikedTags = data.tag_pref.disliked_tags;
-
- for (let tagEl of tagEls) {
- let tagStr = tagEl.firstChild.textContent;
- if (likedTags.includes(tagStr)) {
- tagEl.style.backgroundColor = '#CCE8';
- tagEl.class;
- } else if (dislikedTags.includes(tagStr)) {
- tagEl.style.backgroundColor = '#2338';
- } else {
- tagEl.style.backgroundColor = '';
- }
- }
- }