Hitomi.la Language Filter
This commit is contained in:
160
hitomi-language-filter.user.js
Normal file
160
hitomi-language-filter.user.js
Normal file
@@ -0,0 +1,160 @@
|
||||
// ==UserScript==
|
||||
// @name Hitomi.la Language Filter
|
||||
// @namespace https://git.ponywave.de/Akamaru/Userscripts
|
||||
// @version 1.0
|
||||
// @description Filter manga by language on hitomi.la
|
||||
// @author Akamaru
|
||||
// @match https://hitomi.la/*
|
||||
// @grant GM_getValue
|
||||
// @grant GM_setValue
|
||||
// @grant GM_registerMenuCommand
|
||||
// @updateURL https://git.ponywave.de/Akamaru/Userscripts/raw/branch/master/hitomi-language-filter.user.js
|
||||
// @downloadURL https://git.ponywave.de/Akamaru/Userscripts/raw/branch/master/hitomi-language-filter.user.js
|
||||
// @run-at document-idle
|
||||
// ==/UserScript==
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// Available languages
|
||||
const languages = {
|
||||
'all': 'All Languages',
|
||||
'english': 'English',
|
||||
'japanese': 'Japanese',
|
||||
'chinese': 'Chinese',
|
||||
'korean': 'Korean',
|
||||
'spanish': 'Spanish',
|
||||
'french': 'French',
|
||||
'german': 'German',
|
||||
'russian': 'Russian',
|
||||
'italian': 'Italian',
|
||||
'portuguese': 'Portuguese',
|
||||
'thai': 'Thai',
|
||||
'vietnamese': 'Vietnamese',
|
||||
'polish': 'Polish',
|
||||
'indonesian': 'Indonesian',
|
||||
'turkish': 'Turkish'
|
||||
};
|
||||
|
||||
// Get saved language preference (default: english)
|
||||
let selectedLanguage = GM_getValue('selectedLanguage', 'english');
|
||||
|
||||
// Create language selector UI
|
||||
function createLanguageSelector() {
|
||||
const container = document.createElement('div');
|
||||
container.id = 'language-filter-container';
|
||||
container.style.cssText = `
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 10000;
|
||||
background: #fff;
|
||||
border: 2px solid #333;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
|
||||
`;
|
||||
|
||||
const label = document.createElement('label');
|
||||
label.textContent = 'Language: ';
|
||||
label.style.fontWeight = 'bold';
|
||||
|
||||
const select = document.createElement('select');
|
||||
select.style.cssText = `
|
||||
padding: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
margin-left: 5px;
|
||||
`;
|
||||
|
||||
// Add options
|
||||
for (const [code, name] of Object.entries(languages)) {
|
||||
const option = document.createElement('option');
|
||||
option.value = code;
|
||||
option.textContent = name;
|
||||
if (code === selectedLanguage) {
|
||||
option.selected = true;
|
||||
}
|
||||
select.appendChild(option);
|
||||
}
|
||||
|
||||
// Handle language change
|
||||
select.addEventListener('change', function() {
|
||||
selectedLanguage = this.value;
|
||||
GM_setValue('selectedLanguage', selectedLanguage);
|
||||
filterGalleries();
|
||||
});
|
||||
|
||||
container.appendChild(label);
|
||||
container.appendChild(select);
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
// Filter galleries based on selected language
|
||||
function filterGalleries() {
|
||||
// Find all gallery items (both classes used on the site)
|
||||
const galleries = document.querySelectorAll('.gallery, .dj, .manga');
|
||||
|
||||
galleries.forEach(gallery => {
|
||||
if (selectedLanguage === 'all') {
|
||||
gallery.style.display = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for language link in format /index-LANGUAGE.html
|
||||
const languageTag = gallery.querySelector('a[href*="/index-"][href$=".html"]');
|
||||
if (!languageTag) {
|
||||
gallery.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
const href = languageTag.getAttribute('href');
|
||||
const langMatch = href.match(/\/index-([^.]+)\.html/);
|
||||
|
||||
if (langMatch && langMatch[1]) {
|
||||
const galleryLang = langMatch[1].toLowerCase();
|
||||
if (galleryLang === selectedLanguage) {
|
||||
gallery.style.display = '';
|
||||
} else {
|
||||
gallery.style.display = 'none';
|
||||
}
|
||||
} else {
|
||||
gallery.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Register menu command for quick access
|
||||
GM_registerMenuCommand('Change Language Filter', function() {
|
||||
const newLang = prompt('Enter language code:\n' +
|
||||
Object.entries(languages).map(([code, name]) => `${code} - ${name}`).join('\n'));
|
||||
if (newLang && languages[newLang]) {
|
||||
selectedLanguage = newLang;
|
||||
GM_setValue('selectedLanguage', selectedLanguage);
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize
|
||||
function init() {
|
||||
createLanguageSelector();
|
||||
filterGalleries();
|
||||
|
||||
// Watch for dynamic content loading
|
||||
const observer = new MutationObserver(function(mutations) {
|
||||
filterGalleries();
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for page to load
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user