Created
September 25, 2010 22:47
-
-
Save edvakf/597379 to your computer and use it in GitHub Desktop.
This file contains 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 pixivreader | |
// @author edvakf | |
// @namespace http://d.hatena.ne.jp/edvakf/ | |
// @include http://www.pixiv.net/new_illust.php* | |
// @include http://www.pixiv.net/search.php* | |
// @include http://www.pixiv.net/tags.php* | |
// @include http://www.pixiv.net/ranking.php* | |
// @include http://www.pixiv.net/ranking_log.php* | |
// @compatible Opera, Chrome (as UserJS and extension), Safari (as extension) | |
// @licence Public Domain | |
// ==/UserScript== | |
// Opera の場合は pixivreader.js という名前で保存。 | |
// 新着や検索結果やランキングページで左上に pixiv のアイコンが出るので、それをクリックすると pixivreader が開きます。 | |
// 下の方まで来ると自動的に次のページを読み込みます。また、新着一覧のページでは定期的に新しいイラストを読み込みます。 | |
// s キーでダラダラ下に下がっていき、ちょっとでも気に入ったやつを片っ端から i キーで右に表示していく使い方が便利です。 | |
// ショートカット: | |
// s : 左ペイン、一つ下へ | |
// a : 左ペイン、一つ上へ | |
// i : 大きな画像を右ペインに表示 | |
// j : 右ペイン、一つ下へ | |
// k : 右ペイン、一つ上へ | |
// n 又は space : 右ペイン、下へスクロール | |
// m 又は shift+space : 右ペイン、上へスクロール | |
// l : 右ペイン、さらに大きな画像を表示(縦長の漫画で使うといい) | |
// h : 右ペイン、漫画を表示 | |
// b : 右ペインの画像をブックマーク | |
// c 又は esc : ブックマーク編集終了 (Chrome と Safari では esc は使えません) | |
// u : 右ペイン、画像を消す | |
// o : 右ペイン、画像の元ページを開く | |
(function () { | |
var debug = false; | |
var mode = { | |
new_illust : (location.pathname.indexOf('/new_illust.php') === 0), | |
search : (location.pathname.indexOf('/search.php') === 0) || (location.pathname.indexOf('/tags.php') === 0), | |
ranking : (location.pathname.indexOf('/ranking.php') === 0) || (location.pathname.indexOf('/ranking_log.php') === 0), | |
}; | |
if (/http:\/\/www\.pixiv\.net\/(new_illust|search|tags|ranking(_log)?)\.php/.test(location.href)) { | |
if (location.href.indexOf('pixivreader') >= 0) { | |
document.documentElement.style.display = 'none'; | |
if (document.readyState === 'loading') { | |
document.addEventListener('DOMContentLoaded', init, false); | |
} else { | |
init(); | |
} | |
} else { | |
if (document.readyState === 'loading') { | |
document.addEventListener('DOMContentLoaded', init_readerToggle, false); | |
} else { | |
init_readerToggle(); | |
} | |
} | |
} | |
function init() { | |
init_view(); | |
init_Thumb(); | |
init_Showcase(); | |
init_events(); | |
init_externals(); | |
init_readerToggle(); | |
document.documentElement.style.display = 'block'; | |
} | |
// set up basic blocks and css | |
function init_view() { | |
addCSS([ | |
'html {overflow: hidden;}', | |
'.pixivreader {position:fixed; margin:0; padding:0; width: 100%; height: 100%; top: 0; left: 0;}', | |
'.pixivreader .focused {background-color:#FEF5CA !important; border: #8B7D6B solid 1px !important;}', | |
'.pixivreader .scrollbar {position:absolute; width: 8px; border-radius: 4px; background-color:black; opacity: 0.4}', | |
'.pixivreader .leftcol {position:relative; float: left; z-index: 100; width: 200px; height: 100%; overflow: hidden;}', | |
'.pixivreader .leftcol ul {margin:5px 10px; width: 180px}', | |
'.pixivreader .leftcol li {width:170px; margin:5px; background-color:white; text-align:center; border: #d0d0d0 solid 1px; padding-bottom: 3px;}', | |
'.pixivreader .leftcol li.hidden {display:none;}', | |
'.pixivreader .leftcol a {color:black;}', | |
'.pixivreader .leftcol a:hover {background-color:#FEF5CA}', | |
'.pixivreader .leftcol .bookmark_link {border: none;}', | |
'.pixivreader .leftcol img {display:block; margin:0 auto; background-color:white;}', | |
'.pixivreader .leftcol img.error {color: red; font-weight: bold;}', | |
'.pixivreader .rightcol {float: left; width: 100%; height: 100%; margin-left: -200px; overflow: hidden; z-index: 0;}', | |
'.pixivreader .rightcol > * {margin-left: 200px;}', | |
'.pixivreader .rightcol .showcase {padding-bottom: 700px; margin-right: 10px;}', | |
'.pixivreader .rightcol .showcase .item {background-color: white; position: relative; border: #d0d0d0 solid 1px; margin: 5px;}', | |
'.pixivreader .rightcol .showcase .item .itemheader {border-bottom: #8B7D68 dashed 1px;}', | |
'.pixivreader .rightcol .showcase .item .itemheader h2 a {font-weight: bold; font-size: 13pt;}', | |
'.pixivreader .rightcol .showcase .item .itembody {padding: 5px;}', | |
'.pixivreader .rightcol .showcase .item .itembody img {display:block; margin: 5px auto; max-width: 90%; max-height: 650px; background-size: 100%; border: solid #d0d0d0 1px; background-color:white;}', | |
'.pixivreader .rightcol .showcase .item.large .itembody img {max-height: none;}', | |
'.pixivreader .shade {position:absolute; left:0; top:0; width: 100%; height: 100%; background-color: black; opacity: 0.5; z-index: 1000;}', | |
'.pixivreader .bookmarker {position:absolute; z-index: 2000; background-color: white; width: 680px; height: 450px; margin-left: -340px; margin-top: -225px; left: 50%; top: 50%; }', | |
'.pixivreader .bookmarker form {padding: 10px;}', | |
// from pixiv.js (modified) | |
'.pixivreader .bookmarker .bookmain_title{padding:4px;}', | |
'.pixivreader .bookmarker .bookmain_title_img{text-align:left;}', | |
'.pixivreader .bookmarker .box_main_sender{padding-right:0px;padding-bottom:0px;}', | |
'.pixivreader .bookmarker .box_one_body{padding:0px; max-width: 100%}', | |
'.pixivreader .bookmarker .box_one_body > dl{padding:4px 4px 0px 4px;margin:0px;line-height:24px;}', | |
'.pixivreader .bookmarker .box_one_body > dl:last-child{padding:4px;}', | |
'.pixivreader .bookmarker .box_one_body > dl > dd{margin-top:-24px;}', | |
'.pixivreader .bookmarker .box_one_body + div{display:none;}', | |
'.pixivreader .bookmarker .bookmark_recommend_tag{margin:4px;}', | |
'.pixivreader .bookmarker .bookmark_recommend_tag + .bookmark_recommend_tag{margin-top:16px;}', | |
'.pixivreader .bookmarker .bookmark_recommend_tag > span:first-child{display:none;}', | |
'.pixivreader .bookmarker .bookmark_recommend_tag > br{display:none;}', | |
'.pixivreader .bookmarker .bookmark_recommend_tag > ul{padding:0px;margin:0px;}', | |
'.pixivreader .bookmarker .bookmark_recommend_tag > ul + ul{margin-top:4px;}', | |
'.pixivreader .bookmarker .bookmark_recommend_tag > ul > li{padding:2px;margin-right:4px;}', | |
'.pixivreader .bookmarker .bookmark_recommend_tag > ul > li[selected]{border:2px solid #56E655;padding:0px;}', | |
'.pixivreader .bookmarker .bookmark_bottom{padding-bottom:4px;}', | |
'.pixivreader .bookmarker .bookmark_bottom input{margin:0px;}', | |
].join('\n')); | |
// make viewer | |
var pr = document.createElement('div'); | |
pr.className = 'pixivreader'; | |
// leftcol | |
if (mode.new_illust || mode.search) { | |
var leftcol = document.querySelector('.search_a2_result').cloneNode(true); | |
} else if (mode.ranking) { | |
var leftcol = document.createElement('div'); | |
var ul = document.createElement('ul'); | |
leftcol.appendChild(ul); | |
forEach(document.querySelectorAll('.rankingZone'), function(r) { | |
var li = r.querySelector('.r_left_img').cloneNode(true); | |
li.className = ''; | |
var misc1 = document.createElement('div'); | |
misc1.innerHTML = r.querySelector('.r_left_text').textContent.replace(/^[\s\S]*?(\d+位)\s*?(前日\d位)?[\s\S]*$/, function($0, $1, $2) {return $1 + ($2 ? ' ('+$2+')' : '');}); | |
li.insertBefore(misc1, li.firstChild); | |
var misc2 = document.createElement('div'); | |
misc2.innerHTML = r.querySelector('.r_right').textContent.replace(/^[\s\S]*(評価回数:\d+) (スコア:\d+)[\s\S]*$/, '$1<br/>$2'); | |
li.appendChild(misc2); | |
li.querySelector('a').appendChild(document.createTextNode(r.querySelector('.f16b a').textContent)); | |
ul.appendChild(li); | |
}); | |
} | |
leftcol.className = 'leftcol'; | |
pr.appendChild(leftcol); | |
// rightcol | |
var rightcol = document.createElement('div'); | |
rightcol.className = 'rightcol'; | |
rightcol.innerHTML = '<div class="showcase"></div>'; | |
pr.appendChild(rightcol); | |
document.body.innerHTML = ''; | |
document.body.appendChild(pr); | |
} | |
// Thumbnail list for left col | |
var Thumb; | |
function init_Thumb() { | |
Thumb = { | |
images : [], | |
ids: {}, | |
pos : 0, | |
}; | |
var leftcol = document.querySelector('.pixivreader .leftcol'); | |
forEach(leftcol.querySelectorAll('li'), function(li) { | |
var img = li.querySelector('img'); | |
img.setAttribute('data-src', img.getAttribute('src')); | |
var id = img.src.match(/\/(\d+)_s\.\w+$/)[1]; | |
Thumb.ids[id] = li; | |
Thumb.images.push(li); | |
}); | |
Thumb.images[0].className += ' focused'; | |
setTimeout(function() {// because methods are defined below | |
Thumb.resetScrollbar(); | |
if (mode.new_illust) { | |
Thumb.autoRenew(2, true); | |
setInterval(Thumb.autoRenew, 60000); | |
} | |
}, 10); | |
// methods | |
Thumb.autoRenew = function Thumb_autoRenew(p, dontStop) { | |
if (!p) p = 1; | |
var maxpage = 4; | |
function recursive(page) { | |
setTimeout(function() { | |
Thumb.fetch(page, function(html) { | |
var status = Thumb.addIllusts(html); | |
if (status.success && status.isnew && (status.allnew || dontStop) && page < maxpage) { | |
recursive(page + 1); | |
} | |
}); | |
}, 1000); | |
} | |
recursive(p); | |
}; | |
Thumb.fetchNextPage = function Thumb_fetchNextPage() { | |
if (mode.new_illust) { | |
var page; | |
} else { | |
var m = location.href.match(/[?&]p=(\d+)/); | |
var page = m ? +m[1] : 1; | |
} | |
Thumb.fetchNextPage = function Thumb_fetchNextPage2() { | |
Thumb.fetchNextPage = function() {}; // no-op (avoid parallel request) | |
page = mode.new_illust ? Math.ceil(Thumb.images.length / 20) + 1 : page + 1; | |
Thumb.fetch(page, function(html) { | |
Thumb.fetchNextPage = Thumb_fetchNextPage2; // set back | |
var status = Thumb.addIllusts(html); | |
//log(JSON.stringify(status)); | |
if (!status.success || !status.isnew) { | |
Thumb.fetchNextPage = function() {}; // no-op | |
} | |
}); | |
}; | |
Thumb.fetchNextPage(); | |
}; | |
Thumb.fetch = function Thumb_fetch(page, callback) { | |
var url = location.href.replace(/([?&])p=\d+(&)?/, function($0, $1, $2) {return $1 === '?' ? '?' : $2 ? '&' : ''}); | |
url += url.indexOf('?') >= 0 ? '&' : '?'; | |
url += 'p=' + page; | |
log(url); | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', url, true); | |
xhr.onload = function() { | |
callback(xhr.responseText); | |
}; | |
xhr.send(); | |
}; | |
Thumb.addIllusts = function Thumb_addIllusts(html) { // returns the status of parsing | |
try { | |
if (mode.new_illust || mode.search) { | |
html = html.match(/<div class="search_a2_result[\s\S]*?<\/div>/).toString(); | |
} else if (mode.ranking) { | |
html = html.match(/<div class="rankingCenter">[\s\S]*?<div class="rankingRight">/).toString(); | |
} | |
} catch(e) { | |
log(e); | |
return {success: false}; | |
} | |
if (mode.new_illust || mode.search) { | |
var r = /<li[^>]*><a href=".*?"><img src="(.*?)" alt="(.*?)"[^>]*>(.*?)<\/a>(.*?)<\/li>/g; | |
var format = function format(m) { | |
return {url: m[1], title: m[3], titleAndAuthor: m[2], misc2: m[4]}; | |
}; | |
} else if (mode.ranking) { | |
var r = /<div class="rankingZone">[\s\S]*?<span class="f16b">(\d+位)<\/span>(?:<br \/>)?(前日\d+位)?[\s\S]*?<li class="r_left_img"><a href=".*?"><img src="(.*?)" alt="(.*?)" title=".*?" \/><\/a><\/li>[\s\S]*?<span class="f16b"><a href=".*?">(.*?)<\/a>[\s\S]*?(評価回数:\d+) (スコア:\d+)[\s\S]*?<div class="clear"><\/div>/g; | |
var format = function format(m) { | |
return {url: m[3], title: m[5], titleAndAuthor: m[4], misc1: '<div>' + m[1] + (m[2] ? '('+m[2]+')' : '') + '</div>', misc2: '<div>' + m[6] + '<br />' + m[7] + '</div>'}; | |
}; | |
} | |
var m, f, allnew = true, isnew = false; | |
while((m = r.exec(html)) && (f = format(m))) { | |
isnew = true; | |
if (!Thumb.add(f.url, f.title, f.titleAndAuthor, f.misc1, f.misc2)) allnew = false; | |
} | |
if (!isnew) allnew = false; | |
Thumb.resetScrollbar(); | |
Thumb.hideFarImg(); | |
return {success: true, isnew: isnew, allnew: allnew}; | |
}; | |
Thumb.add = function Thumb_add(url, title, titleAndAuthor, misc1, misc2) { // returns false if dup | |
if (!titleAndAuthor) titleAndAuthor = title; | |
var id = url.match(/\/(\d+)_s\.\w+$/)[1]; | |
if (Thumb.ids.hasOwnProperty(id)) return false; | |
var li = document.createElement('li'); | |
li.className += ' hidden'; | |
li.innerHTML = (misc1||'') + '<a href="member_illust.php?mode=medium&illust_id='+id+'">' + | |
'<img data-src="'+url+'" alt="'+titleAndAuthor+'" title="'+titleAndAuthor+'" border="0">'+title+'</a>' + (misc2||''); | |
leftcol.querySelector('ul').appendChild(li); | |
Thumb.images.push(li); | |
Thumb.ids[id] = li; | |
return true; | |
}; | |
Thumb.prev = function Thumb_prev() { | |
var pos = Thumb.pos - 1; | |
if (pos < 0) pos = 0; | |
Thumb.focus(pos, true); | |
}; | |
Thumb.next = function Thumb_next() { | |
var pos = Thumb.pos + 1; | |
if (pos >= Thumb.images.length) pos = Thumb.images.length - 1; | |
Thumb.focus(pos, true); | |
}; | |
Thumb.focus = function Thumb_focus(n, scroll) { // n is the position number or the DOM element, scroll is boolean | |
var f = document.querySelector('.leftcol .focused'); | |
if (f) f.className = f.className.replace(' focused', ''); | |
Thumb.images[n].className += ' focused'; | |
Thumb.pos = n; | |
Thumb.resetScrollbar(); | |
if (scroll) scroll_to(Thumb.images[n], leftcol, true); | |
if (Thumb.pos + 38 > Thumb.images.length) { | |
Thumb.fetchNextPage(); | |
} | |
}; | |
Thumb.resetScrollbar = function Thumb_resetScrollbar() { | |
Thumb.hideFarImg(); | |
var sc; | |
if (!(sc = document.querySelector('.pixivreader .scrollbar.left'))) { | |
sc = document.createElement('div'); | |
sc.style.left = '0'; | |
sc.className = 'scrollbar left'; | |
document.querySelector('.pixivreader').appendChild(sc); | |
} | |
var h = document.documentElement.clientHeight / Thumb.images.length; | |
var mod = 0; | |
if (h < 10) { | |
mod = 10 - h; | |
h = 10; | |
} | |
sc.style.height = h + 'px'; | |
sc.style.top = Thumb.pos / Thumb.images.length * (document.documentElement.clientHeight - mod) + 'px'; | |
}; | |
Thumb.hideFarImg = function Thumb_hideFarImg() { // release memory of images outside the viewport | |
var i = Thumb.pos - 50; | |
var l = Thumb.images.length; | |
if (i - 1 >= 0) { | |
var li = Thumb.images[i - 1]; | |
if (li.className.indexOf('hidden') < 0) { | |
li.className += ' hidden'; | |
li.querySelector('img').src = ''; | |
} | |
} | |
for (var j = 0, k; j < 100; k = i + j++) { | |
if (k >= 0 && k < l) { | |
var li = Thumb.images[k]; | |
if (li.className.indexOf('hidden') >= 0) { | |
li.className = li.className.replace(' hidden', ''); | |
var img = li.querySelector('img'); | |
img.src = img.getAttribute('data-src'); | |
} | |
} | |
} | |
if (k < l) { | |
var li = Thumb.images[k]; | |
if (li.className.indexOf('hidden') < 0) { | |
li.className += ' hidden'; | |
li.querySelector('img').src = ''; | |
} | |
} | |
}; | |
Thumb.sendToShowcase = function Thumb_sendToShowcase () { | |
var li; | |
if (li = Thumb.images[Thumb.pos]) { | |
var img = li.querySelector('img'); | |
Showcase.add(img.src, htmlEscape(img.alt), img.height, img.width); | |
} | |
}; | |
} | |
// Thumbnail list for right col | |
var Showcase; | |
function init_Showcase () { | |
Showcase = { | |
images : [], | |
pos : 0, | |
}; | |
var rightcol = document.querySelector('.pixivreader .rightcol'); | |
// methods | |
Showcase.add = function Showcase_add(url, title, height, width) { | |
var id = url.match(/\/(\d+)_s\.\w+$/)[1]; | |
var largeurl = url.replace(/_s(\.\w+)$/, '_m$1'); | |
var item = document.createElement('div'); | |
item.className = 'item'; | |
item.innerHTML = '<div class="itemheader"><h2><a href="member_illust.php?mode=medium&illust_id='+id+'">'+title+'</a></h2></div>' + | |
'<div class="itembody"><img src="'+url+'" alt="'+title+'" title="'+title+'" border="0"></div>'; | |
document.querySelector('.pixivreader .rightcol .showcase').appendChild(item); | |
var i = Showcase.images.push(item) - 1; | |
if (i === 0) Showcase.focus(item); | |
var img = item.querySelector('img'); | |
gradualLoadImg(img, url, largeurl, | |
function onload() { | |
Showcase.focus(item, true); | |
}, | |
function onerror(img) { | |
img.src = ''; | |
img.style.backgroundImage = 'url('+url+')'; | |
img.height = height || ''; | |
img.width = width || ''; | |
img.className += ' error'; | |
img.alt = 'Error!'; | |
Showcase.focus(item, true); | |
} | |
); | |
Showcase.resetScrollbar(); | |
}; | |
Showcase.prev = function Showcase_prev() { | |
if (Showcase.images.length === 0) return; | |
var rect = Showcase.images[Showcase.pos].getBoundingClientRect(); | |
if (rect.top < 0 && rect.bottom > 0) { | |
var pos = Showcase.pos; | |
} else { | |
var pos = Showcase.pos - 1; | |
if (pos < 0) pos = 0; | |
} | |
Showcase.focus(pos, true); | |
}; | |
Showcase.next = function Showcase_next() { | |
if (Showcase.images.length === 0) return; | |
var pos = Showcase.pos + 1; | |
if (pos >= Showcase.images.length) { | |
var rect = Showcase.images[Showcase.images.length - 1].getBoundingClientRect(); | |
if (rect.top < 0 && rect.bottom > 0) return; | |
// else | |
pos = Showcase.images.length - 1; | |
} | |
Showcase.focus(pos, true); | |
}; | |
Showcase.remove = function Showcase_remove() { | |
if (Showcase.images.length === 0) return; | |
if (Showcase.images.length === 1) { | |
var item = Showcase.images.pop(); | |
item.parentNode.removeChild(item); | |
} else { | |
var pos = Showcase.pos; | |
var item = Showcase.images[pos]; | |
item.parentNode.removeChild(item); | |
Showcase.images.splice(pos, 1); | |
if (pos >= Showcase.images.length) pos = Showcase.images.length - 1; | |
Showcase.focus(pos, true); | |
} | |
}; | |
Showcase.open = function Showcase_open() { | |
if (Showcase.images.length === 0) return; | |
window.open(Showcase.images[Showcase.pos].querySelector('h2 a').href); | |
}; | |
Showcase.scrollDown = function Showcase_scrollDown() { | |
rightcol.scrollTop += 150; | |
if (Showcase.images.length === 0) return; | |
var rect = Showcase.images[Showcase.images.length - 1].getBoundingClientRect(); | |
if (rect.bottom - rect.top > document.documentElement.clientHeight) { | |
if (rect.bottom < document.documentElement.clientHeight) rightcol.scrollTop -= (document.documentElement.clientHeight - rect.bottom) - 5; | |
} else { | |
if (rect.top < 0) rightcol.scrollTop += rect.top - 5; | |
} | |
Showcase.adjustFocus(); | |
}; | |
Showcase.scrollUp = function Showcase_scrollDown() { | |
rightcol.scrollTop -= 150; | |
Showcase.adjustFocus(); | |
}; | |
Showcase.adjustFocus = function Showcase_adjustFocus() { | |
if (Showcase.images.length <= 1) return; | |
var pos = Showcase.pos; | |
var item = Showcase.images[pos]; | |
var rect = item.getBoundingClientRect(); | |
if (rect.top - 5 <= 0 && rect.bottom > 0) return; | |
if (rect.bottom <= 0) { | |
while((item = Showcase.images[++pos]) && (rect = item.getBoundingClientRect())) { | |
if (rect.top - 5 <= 0 && rect.bottom > 0) { | |
return Showcase.focus(pos, false); | |
} | |
} | |
} else if (rect.top > 0) { | |
while((item = Showcase.images[--pos]) && (rect = item.getBoundingClientRect())) { | |
if (rect.top - 5 <= 0 && rect.bottom > 0) { | |
return Showcase.focus(pos, false); | |
} | |
} | |
} | |
}; | |
Showcase.focus = function Showcase_focus(n, scroll) { // n is the position number or the DOM element, scroll is boolean | |
if (Showcase.images.length === 0) return; | |
var f = document.querySelector('.rightcol .focused'); | |
if (f) f.className = f.className.replace(' focused', ''); | |
if (n instanceof HTMLElement) { | |
n.className += ' focused'; | |
Showcase.pos = indexOf(document.querySelectorAll('.rightcol .item'), n); | |
} else { | |
Showcase.images[n].className += ' focused'; | |
Showcase.pos = n; | |
} | |
if (scroll) scroll_to(Showcase.images[Showcase.pos], rightcol); | |
Showcase.resetScrollbar(); | |
}; | |
Showcase.resetScrollbar = function Showcase_resetScrollbar() { | |
var sc; | |
if (!(sc = document.querySelector('.pixivreader .scrollbar.right'))) { | |
sc = document.createElement('div'); | |
sc.className = 'scrollbar right'; | |
sc.style.right = '0'; | |
document.querySelector('.pixivreader').appendChild(sc); | |
} | |
var h = document.documentElement.clientHeight / Showcase.images.length; | |
var mod = 0; | |
if (h < 10) { | |
mod = 10 - h; | |
h = 10; | |
} | |
sc.style.height = h + 'px'; | |
sc.style.top = Showcase.pos / Showcase.images.length * (document.documentElement.clientHeight - mod) + 'px'; | |
}; | |
Showcase.toggleLarge = function Showcase_toggleLarge() { | |
if (Showcase.images.length === 0) return; | |
var item = Showcase.images[Showcase.pos]; | |
if (item.className.indexOf('manga') >= 0) { | |
if (item.className.indexOf('large') >= 0) { | |
item.className = item.className.replace(' large', ''); | |
} else { | |
item.className += ' large'; | |
} | |
return; | |
} | |
var img = item.querySelector('.itembody img'); | |
var src = img.src; | |
if (item.className.indexOf('large') >= 0) { | |
item.className = item.className.replace(' large', ''); | |
gradualLoadImg(img, src, src.replace(/(\.\w+)$/, '_m$1')); | |
} else { | |
item.className += ' large'; | |
gradualLoadImg(img, src, src.replace(/_m(\.\w+)$/, '$1'), | |
function onload() { | |
Showcase.focus(item); | |
}, | |
function onerror() { | |
item.className = item.className.replace(' large', ''); | |
} | |
); | |
} | |
}; | |
Showcase.toggleManga = function Showcase_toggleManga() { | |
if (Showcase.images.length === 0) return; | |
var item = Showcase.images[Showcase.pos]; | |
if (item.className.indexOf('large') >= 0 && item.className.indexOf('manga') < 0) return; | |
function quitManga() { | |
item.className = item.className.replace(' manga', ''); | |
item.className = item.className.replace(' large', ''); | |
var img = item.querySelector('.itembody img'); | |
img.src = img.src.replace(/(?:_m|_p0)(\.\w+)$/, '_m$1'); | |
var s; | |
while(s = img.nextSibling) { | |
s.parentNode.removeChild(s); | |
} | |
} | |
if (item.className.indexOf('manga') >= 0) { | |
quitManga(); | |
} else { | |
item.className += ' manga'; | |
var img = item.querySelector('.itembody img'); | |
var itembody = img.parentNode; | |
var firstpage = img.src.replace(/_m(\.\w+)$/, '_p0$1'); | |
var id = img.src.match(/(\d+)_m\.\w+$/)[1]; | |
function addPage(src) { | |
var page = document.createElement('img'); | |
page.src = src; | |
itembody.appendChild(page); | |
} | |
gradualLoadImg(img, img.src, firstpage, | |
function onload() { | |
addPage(firstpage.replace(/_p0(\.\w+)$/, '_p1$1')); // load second page anyway | |
var xhr = new XMLHttpRequest; | |
xhr.open('GET', 'http://www.pixiv.net/member_illust.php?mode=manga&illust_id='+id+'&type=scroll', true); | |
xhr.onreadystatechange = function() { | |
if (xhr.readyState === 4) { | |
if (xhr.status === 200) { | |
var m, i = 0, r = /<a href="#(?:page\d+|manga_footer)"><img src="(.*?)"><\/a>/g; | |
while(m = r.exec(xhr.responseText)) { | |
if (++i > 2) addPage(m[1]); | |
} | |
} | |
} | |
} | |
xhr.send(null); | |
}, | |
function onerror() { | |
quitManga(); | |
} | |
); | |
} | |
}; | |
Showcase.finishBookmark = function Showcase_finishBookmark() { | |
var bm = document.querySelector('.pixivreader .bookmarker'); | |
var shade = document.querySelector('.pixivreader .shade'); | |
if (bm) bm.parentNode.removeChild(bm); | |
if (shade) shade.parentNode.removeChild(shade); | |
}; | |
Showcase.bookmarkCurrent = function Showcase_bookmarkCurrent() { | |
if (Showcase.images.length === 0) return; | |
Showcase.finishBookmark(); | |
var shade = document.createElement('div'); | |
shade.className = 'shade'; | |
shade.onclick = Showcase.finishBookmark; | |
document.querySelector('.pixivreader').appendChild(shade); | |
var bm = document.createElement('div'); | |
bm.className = 'bookmarker'; | |
document.querySelector('.pixivreader').appendChild(bm); | |
var current = Showcase.images[Showcase.pos]; | |
var id = current.querySelector('h2 a').href.match(/illust_id=(\d+)$/)[1]; | |
var xhr = new XMLHttpRequest; | |
xhr.open('GET', 'http://www.pixiv.net/bookmark_add.php?type=illust&illust_id=' + id, true); | |
xhr.onreadystatechange = function() { | |
if (xhr.readyState === 4) { | |
if (xhr.status === 200) { | |
bm.innerHTML = xhr.responseText.match(/<form action="bookmark_add.php"[\S\s]*?<\/form>/); | |
// focus on comment field | |
setTimeout(function() { | |
var comment = document.getElementById('comment'); | |
comment.focus(); | |
}, 10); | |
// for bookmarks (see bookmark_add_v4.js?20100727) | |
location.href = "javascript:" + | |
"alltags = getAllTags();" + | |
"var input_tag = $('input_tag');" + | |
"var value = input_tag.value;" + | |
"var arr = value.split(/\s+| +/);" + | |
"tag_chk(arr);"; | |
} else { // error | |
Showcase.finishBookmark(); | |
} | |
} | |
}; | |
xhr.send(null); | |
}; | |
} | |
function init_events() { // shortcut and mouse | |
// keyboard handling | |
var keys = { | |
115 : Thumb.next, // s | |
97 : Thumb.prev, // a | |
105 : Thumb.sendToShowcase, // i | |
106 : Showcase.next, // j | |
107 : Showcase.prev, // k | |
110 : Showcase.scrollDown, // n | |
109 : Showcase.scrollUp, // m | |
32 : Showcase.scrollDown, // space | |
1032 : Showcase.scrollUp, // shift+space | |
108 : Showcase.toggleLarge, // l | |
104 : Showcase.toggleManga, // h | |
98 : Showcase.bookmarkCurrent, // b | |
99 : Showcase.finishBookmark, // c | |
27 : Showcase.finishBookmark, // esc | |
117 : Showcase.remove, // u | |
111 : Showcase.open, // o | |
}; | |
window.addEventListener('keypress', function(e) { | |
var a = document.activeElement; | |
var keyCode = (e.keyCode || e.charCode || e.which) + 1000 * e.shiftKey + 10000 * e.ctrlKey + 100000 * e.altKey + 1000000 * e.metaKey; | |
if (keyCode < 10000 && (a instanceof HTMLTextAreaElement || (a instanceof HTMLInputElement && (!a.type || a.type === 'text')))) return; | |
if (keys.hasOwnProperty(keyCode)) { | |
e.preventDefault(); | |
keys[keyCode](); | |
} | |
}, false); | |
window.addEventListener('resize', function(e) { | |
Showcase.focus(Showcase.pos, true); | |
}, false); | |
window.addEventListener('mousewheel', function(e) { | |
// http://phpspot.org/blog/archives/2006/08/javascript_23.html | |
if (e.detail) { | |
var delta = -e.detail; | |
} else if (e.wheelDelta) { // IE | |
var delta = e.wheelDelta/40; | |
} | |
if (delta > 0) Showcase.scrollUp(); | |
if (delta < 0) Showcase.scrollDown(); | |
}, false); | |
} | |
function init_externals() { // load scripts and stylesheet from pixiv | |
// for bookmark | |
var s1 = document.createElement('script'); | |
var s2 = document.createElement('script'); | |
var st = document.createElement('link'); | |
s1.src = 'http://source.pixiv.net/source/js/countStrlen.js?20100720'; | |
s2.src = 'http://source.pixiv.net/source/js/bookmark_add_v4.js?20100727'; | |
st.rel = 'stylesheet'; | |
st.href = 'http://source.pixiv.net/source/css/bookmark_add.css?20100720'; | |
var h = document.getElementsByTagName('head')[0]; | |
h.appendChild(s1); | |
h.appendChild(s2); | |
h.appendChild(st); | |
} | |
function init_readerToggle() { // create a button to toggle pixivreader | |
var box = document.createElement('div'); | |
box.style.width = '12px'; | |
box.style.height = '12px'; | |
box.style.position = 'fixed'; | |
box.style.top = 0; | |
box.style.left = 0; | |
box.style.zIndex = 10000; | |
var href = location.href; | |
href = href.indexOf('pixivreader') >= 0 ? | |
href.replace(/([?&])pixivreader(&)?/, function($0, $1, $2) {return $1 === '?' ? '?' : $2 ? '&' : ''}) : | |
href.indexOf('?') >= 0 ? | |
href.replace('?', '?pixivreader&') : | |
href + '?pixivreader'; | |
box.innerHTML = '<a href="' + href + '" style="display:block;position:absolute;top:0;left:0;height:12px;width:12px;opacity:0.5;" title="Toggle pixivreader">'+ | |
'<img src="/favicon.ico" border="0" width="12" height="12" alt="Toggle pixivreader"></a>'; | |
document.body.appendChild(box); | |
} | |
// utils | |
var entities = {'<' : '<', '>' : '>', '"' : '"', '\'' : ''', '&' : '&'}; | |
function htmlEscape(text) { | |
return (text+'').replace(/<>'"&/, function(m){return entities[m]}); | |
} | |
function addCSS(css) { | |
var style = document.createElement('style'); | |
style.textContent = css; | |
document.getElementsByTagName('head')[0].appendChild(style); | |
} | |
function forEach(list, fn) { | |
Array.prototype.forEach.call(list, fn); | |
} | |
function indexOf(list, searchElement, fromIndex) { | |
return Array.prototype.indexOf.call(list, searchElement, fromIndex); | |
} | |
function gradualLoadImg(img, small, large, onload, onerror) { | |
var img2 = document.createElement('img'); | |
img2.style.visibility = 'hidden'; | |
img2.style.backgroundImage = 'url('+small+')'; | |
function callback() { | |
img2.style.visibility = 'visible'; | |
clearInterval(timer); | |
img2.parentNode.removeChild(img2); | |
img.parentNode.replaceChild(img2, img); | |
if (onload) onload(img); | |
img2.onload = img2.onerror = null; | |
} | |
var useNatural = ('naturalHeight' in img); // true for safari, chrome, firefox | |
var w = img2.width; | |
var n = 0; | |
var timer = setInterval(function() { | |
if ((useNatural && img2.naturalHeight > 0 && img2.naturalWidth > 0) || (w !== 0 && img2.width !== w)) { | |
callback(); | |
img2.onload = function() {img.style.backgroundImage = 'none';}; | |
} | |
if (w === 0) w = img2.width; | |
if (++n > 30) clearInterval(timer); | |
}, 100); | |
img2.onload = function() { | |
callback(); | |
img2.style.backgroundImage = 'none'; | |
}; | |
img2.onerror = function() { | |
clearInterval(timer); | |
img.src = small; | |
img2.parentNode.removeChild(img2); | |
img2.onload = img2.onerror = null; | |
if (onerror) onerror(img); | |
}; | |
img2.src = large; | |
document.body.appendChild(img2); | |
} | |
function scroll_to(elem, origin, middle) { | |
if (!middle) { | |
origin.scrollTop = elem.offsetTop - 5; | |
} else { | |
// bring an element into viewport (simplified version of http://d.hatena.ne.jp/edvakf/20100202/1265094445) | |
//if (!origin) origin = document.documentElement; | |
var outer = {left: 0, right: window.innerWidth, top: 0, bottom: window.innerHeight}; | |
var inner = elem.getBoundingClientRect(); | |
//var x = origin.scrollLeft; | |
var y = origin.scrollTop; | |
//x += (inner.left + inner.right) / 2 - (outer.left + outer.right) / 2; | |
y += (inner.top + inner.bottom) / 2 - (outer.top + outer.bottom) / 2; | |
//origin.scrollLeft = x; | |
origin.scrollTop = y - 5; | |
} | |
} | |
function log(msg) { | |
if (!debug) return; | |
if (window.opera) opera.postError.call(opera, Array.prototype.slice.call(arguments)); | |
else console.log.apply(console, Array.prototype.slice.call(arguments)); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment