Adds combobox and related buttons to save searches
// ==UserScript==
// @name BHD Saved Searches
// @namespace Violentmonkey Scripts
// @version 1.1
// @description Adds combobox and related buttons to save searches
// @author CodeX0
// @match *://beyond-hd.me/library*
// @exclude *://beyond-hd.me/library/title*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
(function() {
'use strict';
if (document.getElementById('bhd-search-manager')) {
return;
}
GM_addStyle(`
#bhd-search-manager {
display: flex;
align-items: center;
gap: 8px;
margin-left: 2%;
margin-top: 10px;
}
#bhd-search-select {
width: 200px !important;
padding: 6px 10px !important;
border-radius: 4px !important;
border: 1px solid #766d61 !important;
}
.bhd-search-btn {
background: #555c63 !important;
color: white !important;
border: none !important;
border-radius: 4px !important;
padding: 6px 12px !important;
cursor: pointer !important;
font-size: 13px !important;
white-space: nowrap;
}
.bhd-search-btn.delete {
background: #800101 !important;
}
.bhd-search-btn:hover {
opacity: 0.9;
}
`);
class SearchManager {
constructor() {
this.searches = GM_getValue('librarySearches', []);
}
addSearch(name, url) {
const cleanUrl = url.split('#')[0];
if (this.searches.some(search => search.name === name || search.url === cleanUrl)) {
return false;
}
this.searches.push({ name, url: cleanUrl });
GM_setValue('librarySearches', this.searches);
return true;
}
deleteSearch(name) {
const initialLength = this.searches.length;
this.searches = this.searches.filter(search => search.name !== name);
if (this.searches.length !== initialLength) {
GM_setValue('librarySearches', this.searches);
return true;
}
return false;
}
getSearches() {
return this.searches;
}
}
class UI {
constructor(searchManager) {
this.searchManager = searchManager;
this.createUI();
}
createUI() {
const container = document.createElement('div');
container.id = 'bhd-search-manager';
this.selectBox = document.createElement('select');
this.selectBox.id = 'bhd-search-select';
const searchBtn = this.createButton('Search', () => this.loadSearch());
const saveBtn = this.createButton('Save', () => this.saveSearch());
const deleteBtn = this.createButton('Delete', () => this.deleteSearch(), 'delete');
const placeholderOption = document.createElement('option');
placeholderOption.value = '';
placeholderOption.textContent = 'Saved Searches';
placeholderOption.disabled = true;
placeholderOption.selected = true;
this.selectBox.appendChild(placeholderOption);
this.updateSelectBox();
container.appendChild(this.selectBox);
container.appendChild(searchBtn);
container.appendChild(saveBtn);
container.appendChild(deleteBtn);
this.addToPage(container);
}
createButton(text, onClick, className = '') {
const btn = document.createElement('button');
btn.className = `bhd-search-btn ${className}`;
btn.textContent = text;
btn.addEventListener('click', onClick);
return btn;
}
addToPage(container) {
const exactContainer = document.querySelector('.bhd-outer > #stickyBar > .text-center');
const targetContainer = exactContainer ||
document.querySelector('#stickyBar .text-center') ||
document.querySelector('.text-center') ||
document.querySelector('.navbar-header');
if (targetContainer) {
if (!targetContainer.querySelector('#bhd-search-manager')) {
targetContainer.appendChild(container);
}
} else {
console.warn('Could not find suitable container for search manager');
}
}
updateSelectBox() {
while (this.selectBox.options.length > 1) {
this.selectBox.remove(1);
}
this.searchManager.getSearches().forEach(search => {
const option = document.createElement('option');
option.value = search.url;
option.textContent = search.name;
this.selectBox.appendChild(option);
});
if (this.selectBox.options.length > 0) {
this.selectBox.selectedIndex = 0;
}
}
saveSearch() {
const currentUrl = window.location.href;
const searchName = prompt('Enter a name for this search:',
`Search ${this.searchManager.getSearches().length + 1}`);
if (searchName && searchName.trim()) {
if (this.searchManager.addSearch(searchName.trim(), currentUrl)) {
this.updateSelectBox();
this.showMessage('Search saved successfully!');
} else {
this.showMessage('This search already exists!', true);
}
}
}
loadSearch() {
const selectedIndex = this.selectBox.selectedIndex;
if (selectedIndex > 0) {
const selectedUrl = this.selectBox.options[selectedIndex].value;
window.location.href = selectedUrl;
} else {
this.showMessage('Please select a search first!', true);
}
}
deleteSearch() {
const selectedIndex = this.selectBox.selectedIndex;
if (selectedIndex > 0) {
const searchName = this.selectBox.options[selectedIndex].text;
if (confirm(`Are you sure you want to delete "${searchName}"?`)) {
if (this.searchManager.deleteSearch(searchName)) {
this.updateSelectBox();
this.showMessage('Search deleted successfully!');
}
}
} else {
this.showMessage('Please select a search to delete!', true);
}
}
showMessage(text, isError = false) {
const msg = document.createElement('div');
msg.textContent = text;
msg.style.position = 'fixed';
msg.style.bottom = '20px';
msg.style.right = '20px';
msg.style.padding = '10px 15px';
msg.style.backgroundColor = isError ? '#e74c3c' : '#2ecc71';
msg.style.color = 'white';
msg.style.borderRadius = '4px';
msg.style.zIndex = '9999';
document.body.appendChild(msg);
setTimeout(() => {
msg.style.transition = 'opacity 0.5s';
msg.style.opacity = '0';
setTimeout(() => msg.remove(), 500);
}, 3000);
}
}
function initializeSearchManager() {
if (!window.location.pathname.includes('/library')) return;
if (document.getElementById('bhd-search-manager')) return;
const searchManager = new SearchManager();
new UI(searchManager);
}
function setupObserver() {
initializeSearchManager();
const observer = new MutationObserver((mutations) => {
let shouldInitialize = false;
if (!document.getElementById('bhd-search-manager')) {
const targetAreas = [
'.bhd-outer > #stickyBar > .text-center',
'#stickyBar .text-center',
'.text-center',
'.navbar-header'
];
shouldInitialize = targetAreas.some(selector => {
const container = document.querySelector(selector);
return container && !container.querySelector('#bhd-search-manager');
});
}
if (shouldInitialize) {
initializeSearchManager();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', setupObserver);
} else {
setupObserver();
}
})();