Skip to content

Instantly share code, notes, and snippets.

@RustingSword
Last active June 15, 2019 02:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RustingSword/18e977483acba97eb3062c871e7e465c to your computer and use it in GitHub Desktop.
Save RustingSword/18e977483acba97eb3062c871e7e465c to your computer and use it in GitHub Desktop.
从豆藤移植相册影院模式到饭否
// ==UserScript==
// @name fanfou相册增强
// @namespace https://fanfou.com
// @version 0.1
// @description album enhanced
// @author RustingSword
// @match https://*.fanfou.com/*
// @match http://*.fanfou.com/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @connect toonaive.me
// @connect api.fanfou.com
// @require https://code.jquery.com/jquery-1.12.4.min.js
// ==/UserScript==
var msg_ids = new Set();
function $$(w, dom){
return (dom || document).querySelectorAll(w);
};
function $(select){
var name = select.substring(1);
switch(select.charAt(0)){
case '#':
return document.getElementById(name);
case '.':
return document.getElementsByClassName(name);
case '/':
return document.getElementsByTagName(name);
default:
return document.getElementsByName(select);
};
};
function getTimestamp (detailUrl, img) {
var stamp = null, method = null;
GM_xmlhttpRequest({
method: 'GET',
url: detailUrl,
headers: {
'Cookie': document.cookie
},
onload: function(xhr){
if(xhr.status == 200){
var parser = new DOMParser();
var detail = parser.parseFromString(xhr.responseText, "text/html");
var spans = $$('.stamp>span', detail);
stamp = spans[0].title;
method = spans[1].textContent;
img.alt = img.title + '<br>' + stamp + ' ' + method;
}
}
});
}
function enableAlbum () {
if (location.href.indexOf('fanfou.com/album') != -1) {
var pics = $$('td>a');
for (var i=0, j=pics.length; i < j; i++){
var img = pics[i].getElementsByTagName('img')[0];
if(img){
getTimestamp(pics[i].href, img);
pics[i].className += ' highslide';
var large_img_end = img.src.indexOf('@');
var largeImg = img.src;
if (large_img_end != -1) {
largeImg = img.src.substring(0, large_img_end);
}
pics[i].setAttribute('onclick', 'return hs.expand(this, {src:\"' + largeImg + '\"});');
};
};
setUpAlbum();
}
}
function setUpAlbum(){
if(!$('#switchHighslide')){//避免加载下一页后重复操作
var photitle = $$('#crumb>h3')[0];
// 添加相册工具条
photitle.innerHTML += ' ' + (GM_getValue('highslide', true)
? '<a href=\"javascript:\" id=\"switchHighslide\" class=\"lnk-sharing fleft\" style=\"border-color:#e3f1ed;background-color:#f2f8f2;color:#4f946e;\" title=\"点击关闭相册影院模式\">关闭影院模式</a>'
: '<a href=\"javascript:\" id=\"switchHighslide\" class=\"btn-donate fleft\" style=\"border-color:#edceba;background-color:#fff0e2;color:#99776b;\" title=\"点击开启相册影院模式,享受浏览图片的乐趣 by豆藤\">开启影院模式</a>'
);
$('#switchHighslide').addEventListener('click', function(){// 切换相册影院模式
GM_setValue('highslide', !GM_getValue('highslide', true));
location.reload();
}, false);
};
// 相册影院模式
/**
\t\t\t * Name: Highslide JS
\t\t\t * Version: 4.1.9 (2010-07-05)
\t\t\t * Author: Torstein Hønsi
\t\t\t * Support: www.highslide.com/support
\t\t\t * License: www.highslide.com/#license
\t\t\t */
if(GM_getValue('highslide', true)){
// add JS
!GM_getValue('highslide_js', false) && GM_xmlhttpRequest({
method: 'GET',
url: 'https://toonaive.me/highslide.js',
onload: function(xhr){
if(xhr.status == 200){
GM_setValue('highslide_js', xhr.responseText);
var a = document.createElement('script');
a.innerHTML = xhr.responseText;
$$('head')[0].appendChild(a);//xhr为异步操作,所以第一次加载时,需要先执行
}
}
});
var a = document.createElement('script');
a.id = 'highslide_js';
a.innerHTML = GM_getValue('highslide_js', '');
$('#highslide_js') || $$('head')[0].appendChild(a);
// add css
!GM_getValue('highslide_css', false) && GM_xmlhttpRequest({
method: 'GET',
url: 'https://toonaive.me/highslide.css',
onload: function(xhr){
if(xhr.status == 200){
GM_setValue('highslide_css', xhr.responseText);
GM_addStyle(xhr.responseText);
}
}
});
GM_addStyle(GM_getValue('highslide_css', ''));
// add config
a = document.createElement('script');
a.id = 'highslide_config'
a.innerHTML = "\
hs.align = 'center';\
hs.transitions = ['expand', 'crossfade'];\
hs.fadeInOut = true;\
hs.dimmingOpacity = 0.8;\
hs.wrapperClassName = 'dark borderless floating-caption';\
hs.captionEval = 'this.thumb.alt';\
hs.marginBottom = 200;\
hs.numberPosition = 'caption';\
\
hs.addSlideshow({\
interval : 2000,\
repeat : false,\
useControls : true,\
overlayOptions : {\
className : 'text-controls',\
position : 'bottom center',\
relativeTo : 'viewport',\
offsetY : -60\
},\
thumbstrip : {\
position : 'bottom center',\
mode : 'horizontal',\
relativeTo : 'viewport'\
}\
});\
";
$('#highslide_config') || $$('head')[0].appendChild(a);
};
};
function isFanfouThumbnail(url) {
return url.indexOf('@120w_120h') != -1 ||
url.indexOf('@100w_100h') != -1 ||
url.indexOf('@596w') != -1;
}
function checkAndRemove(msgid, node) {
var server = 'https://api.fanfou.com/statuses/show.json?id=';
GM_xmlhttpRequest({
method: 'GET',
url: server + msgid,
headers: {
'Cookie': document.cookie
},
onload: function(xhr) {
if (xhr.status == 403) {
console.log('remove locked message: https://fanfou.com/statuses/' + msgid);
var parent = node.parentNode;
if (parent == null) {
console.log('parent of ' + msgid + ' is null');
} else {
console.log('really removed ' + msgid);
parent.removeChild(node);
}
} else {
console.log('https://fanfou.com/statuses/' + msgid + ' is not locked');
}
}
});
}
function removeLockedMessage() {
var msgs = $$('.solo>li');
for (var i = 0; i < msgs.length; i++) {
var reply = $$('.stamp>.reply', msgs[i])[0];
if (reply) {
var url = $$('a', reply)[0];
var id = url.href.split('/').pop();
if (msg_ids.has(id)) {
continue;
}
msg_ids.add(id);
checkAndRemove(id, msgs[i]);
}
}
}
function expandImage () {
var i, large_img;
var urls = $$('a');
for (i = 0; i < urls.length; i++) {
if (isFanfouThumbnail(urls[i].href)) {
large_img = urls[i].href.substring(0, urls[i].href.indexOf('@'));
urls[i].href = large_img;
urls[i].title = large_img;
}
}
}
// https://hijiangtao.github.io/2017/08/03/How-to-Manipulate-DOM-Effectively/
(function() {
// 'use strict';
enableAlbum();
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var observer = new MutationObserver(function(mutations, observer) {
expandImage();
removeLockedMessage();
});
// define what element should be observed by the observer
// and what types of mutations trigger the callback
observer.observe(document.documentElement, {
subtree: true,
childList: true,
attributeFilter: ['li']
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment