Skip to content

Instantly share code, notes, and snippets.

@roflsunriz
Last active April 16, 2025 04:54
Show Gist options
  • Save roflsunriz/31e3b65acd467e4d852423dc178d3c9b to your computer and use it in GitHub Desktop.
Save roflsunriz/31e3b65acd467e4d852423dc178d3c9b to your computer and use it in GitHub Desktop.
fanbox_floating_menu : Fanboxのページ移動用フローティングメニューを追加
// ==UserScript==
// @name Fanbox Floating Menu
// @namespace fanboxFloatingMenu
// @version 1.4
// @description Fanboxのページ移動用フローティングメニューを追加
// @author roflsunriz
// @match https://*.fanbox.cc/posts/*
// @grant none
// @updateURL https://gist.githubusercontent.com/roflsunriz/31e3b65acd467e4d852423dc178d3c9b/raw/fanbox_floating_menu.user.js
// @downloadURL https://gist.githubusercontent.com/roflsunriz/31e3b65acd467e4d852423dc178d3c9b/raw/fanbox_floating_menu.user.js
// @icon https://www.google.com/s2/favicons?sz=64&domain=fanbox.cc
// ==/UserScript==
(function() {
'use strict';
// フローティングメニューを作成する関数
function createFloatingMenu(originalMenu) {
const menu = originalMenu.cloneNode(true);
menu.classList.add('floating-menu');
menu.style.position = 'fixed';
menu.style.left = '0';
menu.style.top = '50%';
menu.style.transform = 'translateY(-50%)';
menu.style.zIndex = '1000';
menu.style.backgroundColor = 'rgba(255, 255, 255, 0.9)';
menu.style.padding = '10px';
menu.style.borderRadius = '0 5px 5px 0';
menu.style.boxShadow = '2px 2px 5px rgba(0,0,0,0.2)';
menu.style.display = 'flex';
menu.style.flexDirection = 'column';
menu.style.gap = '10px';
// 各リンクと特定のdiv要素のスタイルを調整
const links = menu.querySelectorAll('a, div[class*="FooterLinks__PrevPostWrapper-sc-"], div[class*="FooterLinks__NextPostWrapper-sc-"]');
links.forEach(link => {
link.style.padding = '5px 10px';
link.style.borderRadius = '3px';
link.style.textDecoration = 'none';
link.style.color = '#333';
link.style.transition = 'background-color 0.2s';
// ホバー時のスタイル
link.addEventListener('mouseenter', () => {
link.style.backgroundColor = 'rgba(0,0,0,0.1)';
});
link.addEventListener('mouseleave', () => {
link.style.backgroundColor = 'transparent';
});
});
return menu;
}
function waitForMenu(selector, timeout = 5000) {
return new Promise((resolve, reject) => {
const startTime = Date.now();
const checkInterval = 100;
const checkMenu = () => {
const menu = document.querySelector(selector);
if (menu) {
resolve(menu);
} else if (Date.now() - startTime >= timeout) {
reject(new Error('メニューが見つかりません'));
} else {
setTimeout(checkMenu, checkInterval);
}
};
checkMenu();
});
}
window.addEventListener('load', async function() {
try {
// メニューが表示されるまで最大5秒待つ
const originalMenu = await waitForMenu('[class*="FooterLinks__Wrapper-sc-"]');
// 初期メニューを作成
const menu = createFloatingMenu(originalMenu);
document.body.appendChild(menu);
// ページの変化を監視する
const observer = new MutationObserver((mutations) => {
// メニュー以外の変化だけを処理
const isMenuChange = mutations.some(mutation =>
Array.from(mutation.addedNodes).some(node =>
node.classList && node.classList.contains('floating-menu')
)
);
if (!isMenuChange) {
// 監視を一時停止
observer.disconnect();
// 既存のメニューを削除
const oldMenu = document.querySelector('.floating-menu');
if (oldMenu) oldMenu.remove();
// 新しいメニューを作成
const newMenu = createFloatingMenu(originalMenu);
document.body.appendChild(newMenu);
// 監視を再開
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false
});
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false
});
} catch (error) {
// メニューが見つからない場合の代替処理
alert('フローティングメニューを表示できませんでした。ページを再読み込みしてください。');
}
});
})();
@roflsunriz
Copy link
Author

Rawボタンを押してTampermonkeyにインストール。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment