cosenseリンクのページをshiftキー押下時にマウスホバーでpreviewするUserScript
code:script.js
(function () {
// Scrapboxのプロジェクト名を取得
const currentUrl = window.location.href;
const currentUrlWithoutProtocol = currentUrl.replace("https://", "");
const projectName = currentUrlWithoutProtocol.split("/")1;
// グローバル変数でiframeを追跡
let currentIframe = null;
let isMouseOverIframe = false;
function addHoverEvents() {
const links = document.querySelectorAll(".page a");
links.forEach((link) => {
const href = link.getAttribute("href");
if (
href.startsWith(/${projectName}) ||
href.startsWith(https://scrapbox.io/${projectName})
) {
console.log(href);
link.addEventListener("mouseenter", (event) => {
if (event.shiftKey) {
showPreview(event);
}
});
link.addEventListener("mouseleave", scheduleHidePreview);
}
});
}
async function showPreview(event) {
const link = event.target;
const href = link.getAttribute("href");
let pageTitle;
pageTitle = href.split("/").pop();
// 既存のiframeがあれば削除
removeCurrentIframe();
const iframe = document.createElement("iframe");
iframe.style.width = "1000px";
iframe.style.height = "300px";
iframe.style.position = "absolute";
iframe.style.border = "1px solid #ccc";
iframe.style.backgroundColor = "white";
iframe.style.zIndex = "1000";
// iframeの位置を設定
const rect = link.getBoundingClientRect();
iframe.style.left = ${rect.left}px;
iframe.style.top = ${rect.bottom + window.scrollY}px;
// APIからコンテンツを取得
try {
const response = await fetch(
https://scrapbox.io/api/pages/${projectName}/${pageTitle}/text
);
if (response.status === 200) {
const data = await response.text();
iframe.srcdoc = <pre style="white-space: pre-wrap; word-wrap: break-word;">${data}</pre>;
} else if (response.status === 404) {
iframe.srcdoc = "<p>Empty Page</p>";
} else {
iframe.srcdoc = "<p>Error loading content</p>";
}
} catch (error) {
iframe.srcdoc = "<p>Error loading content</p>";
}
// iframeをページに追加
document.body.appendChild(iframe);
currentIframe = iframe;
// iframeにマウスイベントを追加
iframe.addEventListener("mouseenter", () => {
isMouseOverIframe = true;
cancelHidePreview();
});
iframe.addEventListener("mouseleave", () => {
isMouseOverIframe = false;
scheduleHidePreview();
});
}
// プレビューを非表示にするスケジュール
function scheduleHidePreview() {
clearTimeout(scheduleHidePreview.timeoutId);
scheduleHidePreview.timeoutId = setTimeout(() => {
if (!isMouseOverIframe) {
removeCurrentIframe();
}
}, 300); // 300ミリ秒の遅延を設定
}
// プレビュー非表示のキャンセル
function cancelHidePreview() {
//TODO
// 確かにこれで動くけど
// timeout時間が短すぎると動かなくなるので、要検討
clearTimeout(scheduleHidePreview.timeoutId);
}
// 現在のiframeを削除
function removeCurrentIframe() {
if (currentIframe) {
currentIframe.remove();
currentIframe = null;
isMouseOverIframe = false;
}
}
// ページ全体のクリックイベントを追加
function addGlobalClickEvent() {
document.addEventListener("click", (event) => {
if (currentIframe && !currentIframe.contains(event.target)) {
removeCurrentIframe();
}
});
}
// 実行
addHoverEvents();
addGlobalClickEvent();
})();
#UserScript