Last active
December 23, 2023 02:25
-
-
Save marktaiwan/474262db6cdac8b4e7411cd5471654a5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Desuarchive Image Expansion | |
// @description Inline image expansion | |
// @version 1.0.0 | |
// @author Marker | |
// @license MIT | |
// @namespace https://github.com/marktaiwan/ | |
// @homepageURL https://github.com/marktaiwan/ | |
// @match https://desuarchive.org/* | |
// @inject-into content | |
// @noframes | |
// @require https://raw.githubusercontent.com/soufianesakhi/node-creation-observer-js/master/release/node-creation-observer-latest.js | |
// @grant GM_addStyle | |
// ==/UserScript== | |
(function () { | |
'use strict'; | |
/* Shorthands */ | |
function $(selector, root = document) { | |
return root.querySelector(selector); | |
} | |
function $$(selector, root = document) { | |
return root.querySelectorAll(selector); | |
} | |
function onLeftClick(callback, root = document) { | |
root.addEventListener('click', e => { | |
if (e instanceof MouseEvent && e.button === 0) callback(e); | |
}); | |
} | |
const SCRIPT_ID = 'desu-image-expansion'; | |
const EXPANDED_ATTR = `${SCRIPT_ID}-expanded`; | |
const PENDING_ATTR = `${SCRIPT_ID}-pending`; | |
const LOADED_ATTR = `${SCRIPT_ID}-loaded`; | |
const fileExtensionRegExp = new RegExp('\\.(?:jpg|png|gif)$'); | |
const CSS = ` | |
.thread_image_link[${PENDING_ATTR}] .post_image { | |
opacity: 0.75; | |
} | |
article.thread > .thread_image_box[${EXPANDED_ATTR}], | |
aside.posts .post_wrapper > .thread_image_box[${EXPANDED_ATTR}] { | |
float: none; | |
text-align: unset; | |
} | |
#backlink .thread_image_link .expanded_image, | |
.thread_image_link .expanded_image, | |
.thread_image_link[${EXPANDED_ATTR}] .post_image { | |
display: none; | |
} | |
#backlink .thread_image_link .post_image, | |
.thread_image_link .post_image, | |
.thread_image_link[${EXPANDED_ATTR}] .expanded_image { | |
display: block; | |
} | |
#backlink .post_image { | |
opacity: 1; | |
} | |
#backlink .text .spoiler { | |
color: unset; | |
background: #ccc; | |
} | |
`; | |
function toggle(anchor) { | |
const expanded = anchor.hasAttribute(EXPANDED_ATTR); | |
const pending = anchor.hasAttribute(PENDING_ATTR); | |
const loaded = anchor.hasAttribute(LOADED_ATTR); | |
if (loaded) { | |
const article = anchor.closest('article'); | |
const container = anchor.closest('.thread_image_box'); | |
const padding = 5; | |
const scrollTop = article.getBoundingClientRect().top; | |
if (scrollTop < 0) window.scrollBy({top: scrollTop - padding, left: 0}); | |
container.toggleAttribute(EXPANDED_ATTR, !expanded); | |
anchor.toggleAttribute(EXPANDED_ATTR, !expanded); | |
} else if (pending) { | |
anchor.removeAttribute(PENDING_ATTR); | |
} else { | |
anchor.setAttribute(PENDING_ATTR, ''); | |
if (!$('.expanded_image', anchor)) { | |
const img = document.createElement('img'); | |
img.src = anchor.href; | |
img.style.maxWidth = '100%'; | |
img.classList.add('expanded_image'); | |
anchor.append(img); | |
checkLoadStart(anchor, img); | |
} | |
} | |
} | |
function checkLoadStart(root, expandedImage) { | |
if (expandedImage.naturalWidth) { | |
root.setAttribute(LOADED_ATTR, ''); | |
if (root.hasAttribute(PENDING_ATTR)) { | |
root.removeAttribute(PENDING_ATTR); | |
toggle(root); | |
} | |
} else { | |
window.setTimeout(checkLoadStart, 100, root, expandedImage); | |
} | |
} | |
GM_addStyle(CSS); | |
onLeftClick(e => { | |
const target = e.target; | |
const anchor = target.closest('a.thread_image_link'); | |
if (!anchor || !fileExtensionRegExp.test(anchor.href)) return; | |
e.preventDefault(); | |
toggle(anchor); | |
}); | |
NodeCreationObserver.init(SCRIPT_ID); | |
NodeCreationObserver.onCreation('.post_backlink > .backlink', backlink => { | |
const postId = Number.parseInt(backlink.parentElement.dataset.post); | |
const previewId = Number.parseInt(backlink.dataset.post); | |
const selector = `#backlink [id="${previewId}"]`; | |
backlink.addEventListener('mouseenter', () => { | |
$$(`${selector} a.backlink[data-post="${postId}"]`).forEach(ele => { | |
ele.classList.add('post_level', 'post_level_administrator'); | |
}); | |
}); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment