NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name xsnvshen // @namespace http://tampermonkey.net/ // @version 0.3 // @description Extract the original full size images from xsnvshen.com. Press space to start/stop slideshow, drag any extracted image to hide it and double click to reload it. // @author dc // @match https://www.xsnvshen.com/album/* // @grant none // @license MIT // @updateURL https://openuserjs.org/meta/dc165015/xsnvshen.meta.js // @downloadURL https://openuserjs.org/install/dc165015/xsnvshen.user.js // @copyright 2019, dc165015 (https://openuserjs.org/users/dc165015) // ==/UserScript== (function () { 'use strict'; let bigImgsCount = 0; let isBoardShowed = false; let slidesHandler, slidesInerval = 1000; let title = document.title; let $ = window.jQuery; let $thumbsList = $("div.showlists"); let $thumbs = $thumbsList.find("img"); let $slidesPanel = $("div.workContentWrapper"); let $board = $('<div class="top-board"></div>'); // show lists mode $('a#showlists').click(); setTriggerLink(); setStyle(); setOpDivs(); setHotkey(); function setTriggerLink() { let $button = $("div.show-topmbx > a").last(); $button.addClass('trigger-link'); $button.attr('href', '#'); $button.text('[展示全部原图]'); $button.click(() => extractAllBigImgs(isBoardShowed = true)); } function setStyle() { let style = document.createElement('STYLE'); style.type = 'text/css'; style.innerHTML = ` .op { background-color: white; width: 100%; height: 80px; display: flex; position: absolute; } .op-hide { opacity: 0; } .op-show { opacity: 0.5; } .op:hover { opacity: 0.5; } .op-select { bottom: 0; } .op-remove { top: 0; } .op .op-button { display: block; color: rgba(255,0,0,0.5); font-size: 30px; font-weight: bolder; margin: auto auto; } .top-board { background-color: black; position: absolute; min-height: 100%; width: 100%; z-index: 10000; overflow: auto; flex-direction: row; flex-wrap: nowrap; } .full-img-box { display: block; position: relative; width: 100%; height: 100vh; margin-bottom: 1px; } .full-img { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; max-width: 100%; max-height: 100%; } .trigger-link { float: right; color: blue !important; } `; document.head.append(style); } function setOpDivs() { let OP_REMOVE = 'remove', OP_REMOVED = 'removed', OP_SELECT = 'select', OP_SELECTED = 'selected'; $thumbs.each((n, img) => { setOpSelect(img); setOpRemove(img); }); function setOpSelect(img) { let $img = $(img); let $div = $createOpDiv(); $div.addClass('op-select'); $img.after($div); img.opSelect = (is) => { if (is == void 0) is = !img.isSelected; if (is) { $div.show(); $div.label(OP_SELECTED); img.isSelected = true; img.opRemove(false); } else { $div.hide(); $div.label(OP_SELECT); img.isSelected = false; } }; img.opSelect(false); $div.click(() => img.opSelect()); } function setOpRemove(img) { let $img = $(img); let $div = $createOpDiv(); $div.addClass('op-remove'); $img.before($div); img.opRemove = (is) => { if (is == void 0) is = !img.isRemoved; if (is) { $div.show(); $div.label(OP_REMOVED); img.isRemoved = true; img.opSelect(false); } else { $div.hide(); $div.label(OP_REMOVE); img.isRemoved = false; } }; img.opRemove(false); $div.click(() => img.opRemove()); } function $createOpDiv() { let $div = $('<div class="op"></div>'); $div.hide = () => { $div.removeClass('op-show'); $div.addClass('op-hide'); }; $div.show = () => { $div.removeClass('op-hide'); $div.addClass('op-show'); }; $div.label = (text = '') => { $div.html(`<span class="op-button">${text.toUpperCase()}</span>`); } return $div; } } function setHotkey() { document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.key == '`') { window.scrollTo(0, 0); extractAllBigImgs(isBoardShowed = !isBoardShowed); } else if (isBoardShowed) { doKeyActions(e); } function doKeyActions(e) { e.stopPropagation(); e.preventDefault(); if (e.key == 'ArrowDown') { scrollToImgBox('down'); } else if (e.key == 'ArrowUp') { scrollToImgBox('up'); } else if (e.key == ' ') { doSlides(); } else if (e.key == 'Escape') { reset(); } } function reset() { extractAllBigImgs(isBoardShowed = false); stopSlides(); $thumbs.each((i, img) => { img.opSelect(false); img.opRemove(false); }); } }); function scrollToImgBox() { let boxes = getBoxes(), current = getCurrentImgBoxInView(boxes); if (current) { current = getNextReadyImgBox(current); //$(current).fadeOut(0).fadeIn(400); current && current.scrollIntoView(true); } function getNextReadyImgBox(current){ let next = current, img, didGoThrough = false; do { next = next.nextElementSibling; if (!next) { if (didGoThrough) break; next = boxes[0]; didGoThrough = true; } img = next.children[0]; } while(!(img.complete || img.readyState)); return next || boxes[0]; } function getBoxes() { return $board.find('.full-img-box') || []; } function getCurrentImgBoxInView(boxes = []) { let current; for (let i = 0; i < boxes.length; i++) { current = boxes[i]; if (isInView(current)) break; }; return current; function isInView(el) { return el.style.display != 'none' && window.scrollY >= el.offsetTop && window.scrollY <= el.offsetTop + el.scrollHeight; } } } function doSlides() { if (slidesHandler) { stopSlides(); } else { startSlides(); } } function stopSlides() { clearInterval(slidesHandler); slidesHandler = void 0; } function startSlides() { if (isBoardShowed) { scrollToImgBox(); slidesHandler = setTimeout(startSlides, slidesInerval); } } } function extractAllBigImgs(doExtract = true) { if (doExtract) { $(document.body).prepend($board); startExtract(); } else { $board.detach(); $board.children().detach(); } removeThumbsListAndSlidesPanel(doExtract); function startExtract() { let $chosenThumbs = getChosen$Thumbs(); let i = bigImgsCount = $chosenThumbs.length; while (i-- > 0) { try { showBigImgBy($chosenThumbs[i]); } catch (e) {} } function getChosen$Thumbs() { let selected = []; let unremoved = []; $thumbs.each((i, img) => { let $thumb = $(img); if (img.isSelected) selected.push($thumb); if (!img.isRemoved) unremoved.push($thumb); }); return selected.length ? selected : unremoved; } function showBigImgBy($thumb, $box, retryNo = 0) { let $loadedImgBox, $img, $loadedBigImgBoxes = new Map(); if (!$box && ($loadedImgBox = $loadedBigImgBoxes.get($thumb))) { $board.prepend($loadedImgBox); } else { $box = $box || createBigImgWithBox($thumb); $img = $box.find('img'); $img.length && initImg(); } function createBigImgWithBox($thumb) { let $img = $('<img/>').addClass("full-img"); let $box = $('<div></div>').addClass("full-img-box"); $box.append($img); $loadedBigImgBoxes.set($thumb, $box); listenDblClick(); listenDrag(); return $box; function listenDblClick() { $box.dblclick((e) => { reload$img($img); }); function reload$img($img) { let src = $img.attr('src'); let index = src.indexOf('?'); src = index == -1 ? src : src.substring(0, src.indexOf('?')); setImgSrc($img, src); } } function listenDrag() { $box[0].ondrag = (e) => { $thumb[0].opRemove(); $box.detach(); bigImgsCount--; }; } } function initImg() { let src = getBigImgSrcFrom($thumb); setImgSrc($img, src); setImgId(); return new Promise((resolve, reject) => { var img = $img[0]; $board.prepend($box); $img.load(() => { $img.css('display', 'block'); updateTitle(); resolve(); }); img.onerror = img.onsuspend = img.onstalled = img.onemptied = () => { retryImg($thumb, src, $img, ++retryNo); reject(retryNo); }; }); function getBigImgSrcFrom($thumb) { return $thumb.data('original').replace(/thumb_600x900\//, ''); } function setImgId() { $img.attr('id', 'big' + $thumb.attr('id').match(/\d+/)); } function updateTitle() { let loadedCount = $board.find('img[style*="display: block;"]').length; document.title = loadedCount != bigImgsCount ? `${loadedCount}/${bigImgsCount}|${title}` : title; } function retryImg($thumb, src, $img, retryNo) { if (retryNo < 10) { setTimeout(() => { console.warn(`retry to load img(${src}) the ${retryNo} time.`); showBigImgBy($thumb, $img, retryNo); }, 10000 * retryNo * retryNo); } } } } } function removeThumbsListAndSlidesPanel(doRemove = true) { if (doRemove) { $slidesPanel.detach(); $thumbsList.detach(); } else { $('.swp-tit').after($slidesPanel, $thumbsList); } } } function setImgSrc($img, src) { // src = src + '?' + Date.now(); $img.attr('src', src); } })();