// ==UserScript==
// @name DMZJ漫画转为手机版链接
// @author Crab
// @namespace DMZJManga@dmzj.com
// @description DMZJ漫画转为手机版链接,并尝试恢复屏蔽的漫画。
// @include *://*.dmzj.com/*
// @compatible firefox 34+
// @compatible Chrome 45+
// @version 1.5.5
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function(){
var gUrl = (function(){
var rules = {
update: /^https?:\/\/manhua\.dmzj\.com\/update\_\d+\.shtml$/,
mobile: /^https?:\/\/m\.dmzj\.com\/view\/.+\.html([@?#&].+)?$/,
mobileInfo: /^https?:\/\/m\.dmzj\.com\/info\/\d+\.html([@?#&].+)?$/,
mobileHome: /^https?:\/\/m\.dmzj\.com\/([^\/\.]+\.html)?(\?t=\d+#\d+)?$/,
desktop: /^https?:\/\/manhua\.dmzj\.com\/.*$/,
subscribe: /^https?:\/\/i\.dmzj\.com\/\/?subscribe.*$/
};
var url = location.href;
for(var i in rules){
if(rules[i].test(url)){
rules = null;
if(i === 'desktop' && location.pathname === '/')
return 'deskHome';
return i;
}
}
})();
var $$ = function(e){
return Array.from(document.querySelectorAll(e));
};
//console.log(gUrl);
var _preventParentScrolling = function(target){
target.addEventListener('wheel', e => {
if(e.deltaY < 0 ?
target.scrollTop === 0 :
target.scrollTop === target.scrollHeight - target.clientHeight
) e.preventDefault();
});
};
var _cE = function (name, attr, parent){
var e = document.createElement(name);
attr = attr || {};
for (let i in attr){
if(i === 'text')
e.textContent = attr[i];
else if(i === 'html')
e.innerHTML = attr[i];
else
e.setAttribute(i, attr[i]);
}
parent && (Array.isArray(parent) ?
parent[0].insertBefore(e, parent.length == 2 ? parent[1] : parent[0].firstChild) :
parent.appendChild(e));
return e;
};
//动态转换链接
_cE('style', {text: `
@keyframes toMobileLink {from{opacity:.9}to{opacity:1}}
.acg-content-text a[href$=shtml]:not([mbl])/*cartoonList*/
,.pictext a[href$=shtml]:not([mbl])/*update*/
,${'.cartoon_online_border,.cartoon_online_border_other, .adiv2hidden:last-child'
.replace(/(?=,)|$/g, ' a[title][href$=shtml]:not([mbl])')}/*desktop*/
,.c_space> a:not([mbl]) /*subscribe*/
,#type_comics .adivhidden:last-child a[href$="shtml"]:not([mbl])/*subscribe 边栏*/
,.autoHeight p:nth-child(2)> a[href$="shtml"]:not([mbl]) /*oldSubscribe*/
,.tcaricature_block .adiv2hidden:last-child a[href$="shtml"]:not([mbl]),
.read_mend_mr a[href$="shtml"]:not([mbl]),
.icn-02_indexa[href$="shtml"]:not([mbl])/*deskHome*/
,.history_des a[href*="shtml"]:not([mbl])/*record*/
,.zxgxbox a[href$="shtml"]:not([mbl])/*tags 边栏*/
,#bookOpen .book_num:not([mbl])/*顶部弹出面板*/
,.middleright-right a[href$="shtml"]:not([mbl])/*排行榜页面*/
{animation:toMobileLink 1ms}
a[mbl][style]{width:20px!important}
/*首页*/
.icn-02_index a{padding-left:0!important}
.top_list span{width:15px}
.top_list a {width:140px}
.top_list .num{margin-right:-5px!important}
/*tags 边栏*/
.zxgxbox .tt_chapter{margin-left: 0px}
.zxgxbox .numbig{padding:0}
.zxgxbox .tt_comic {width: 74px}
.book_l{margin-left:-20px!important}
/*排行榜页面*/
.middleright-right .bikini li>a{padding:0!important}
.middleright-right .bikini li>a+a{width:110px!important}
`}, document.head);
addEventListener('animationstart', e => {
if(e.animationName !== 'toMobileLink')
return;
var a = e.target;
if(!a.href.includes('//manhua.')) return;
a.setAttribute('mbl', 1);
var a1 = a.cloneNode(true);
a1.textContent = '(#)';
a1.style.color = 'orange';
a.parentNode.insertBefore(a1, a);
a.href = a.href
.replace(/\/\/manhua([^\/]+)/,'//m$1/view')
.replace('.shtml', '.html')
.replace(/^http:/, 'https:'); // 替换为 https 减少ISP劫持。
});
if(gUrl == 'update'){
//漫画更新页面国漫灰色显示
var gm = [];
$$('a.pictextst[href*="\:\/\/www\.dmzj\.com\/"]').forEach(a => {
var boxdiv = a.closest('.boxdiv1');
if(boxdiv){
gm.push(boxdiv);
boxdiv.classList.add('filter');
}
});
//将国漫排在最后
var boxs = $$('.newpic_bg, .newpic_bgno');
gm.length && $$('.boxdiv1').filter(m => {
return gm.indexOf(m) == -1;
}).concat(gm).forEach((m, i) => {
boxs[Math.floor(i / 4)].appendChild(m);
});
gm = boxs = null;
_cE('style', {text: `
.newpic_bg::after, .newpic_bgno::after{
content: '';
display: block;
clear: both;
}
.boxdiv1 .picborder {
height:auto;
}
.boxdiv1.filter:not(:hover) .pictext,
.boxdiv1.filter:not(:hover) .picborder {
filter: grayscale(100%);
}
.boxdiv1.filter{
position: relative;
overflow: hidden;
}
.boxdiv1.filter::after{
content:'国漫';
display: block;
position: absolute;
z-index: 1;
color: white;
font-size:16px;
transform: rotate(-45deg);
transform-origin:10px 65px;
pointer-events: none;
width: 100px;
height: 50px;
text-align: center;
line-height: calc(100px - 1.5em);
background: rgba(255, 165, 0, 0.7);
}
`}, document.head);
}else if(gUrl == 'desktop'){
const {g_comic_url, g_last_chapter_id, g_last_update, g_comic_id} = unsafeWindow;
//被隐藏的漫画至少显示最新话
let mhContainer = $$('div.cartoon_online_border')[0];
if(mhContainer && mhContainer.firstElementChild.localName === 'img'){
mhContainer.innerHTML = `
<a href="${g_comic_url}${g_last_chapter_id}.shtml"
title="${g_last_update}"
target="_blank">${g_last_update}</a>
<h2>正在加载被屏蔽的地址...</h2>
`;
GM_xmlhttpRequest({
method:'GET',
timeout: 25000,
//url: `${location.protocol}//v2.api.dmzj.com/comic/${g_comic_id}.json`,
//url: `https://v2api.dmzj.com/comic/${g_comic_id}.json`,
url: `https://v3api.dmzj.com/comic/comic_${g_comic_id}.json`,
onload: e => {
let json = JSON.parse(e.responseText);
if(!json || !json.chapters || json.chapters.length === 0)
return mhContainer.lastElementChild.remove();
mhContainer.innerHTML = '';
let isFolderURL = location.pathname.endsWith('/');
JSON.parse(e.responseText).chapters.forEach(chapters => {
_cE('h3', {text: chapters.title}, mhContainer);
let ul = _cE('ul', null, mhContainer);
chapters.data.forEach(c => {
_cE('li', null, ul).innerHTML = `
<a href="${isFolderURL ? '' : g_comic_url}${c.chapter_id}.shtml"
title="${c.chapter_title}" target="_blank">${c.chapter_title}
</a>`;
});
_cE('div', {class: 'clearfix'}, mhContainer);
});
}
});
}
}else if(gUrl == 'subscribe'){
_cE('style', {text: `
.dy_r p em.c_space{
overflow:auto!important;
width:auto!important;
display: inline;
white-space: normal;
}
.dy_r p{height:auto!important;}
`}, document.head);
var my_subscribe_id = $$('#my_subscribe_id')[0];
var pageLoaded = false;
var addObserver = function(){
my_subscribe_id && (new MutationObserver(function(){
//默认显示未读订阅
if(!pageLoaded){
pageLoaded = true;
_cE('script', {text: `$(".read_id[value=2]").click()`}, document.body).remove();
return;
}
//未看新漫画总排前
this.disconnect();
$$('.c_space + .new').reverse().forEach(function(icon){
var li = icon.parentNode.parentNode.parentNode;
li.parentNode.insertBefore(li, li.parentNode.firstElementChild);
});
addObserver();
})).observe(my_subscribe_id, {childList: true});
};
addObserver();
}
if(gUrl == 'mobile' || 'mobileInfo'== gUrl){
_cE('style', {text: `
#chapters {
padding: 10px;
}
#chapters ul:after{
display: list-item;
clear: both;
content: '';
list-style:none;
}
#chapters dt{
border-bottom: 2px solid #ccc;
font-size: 150%;
text-indent: .5em;
padding: 5px 0;
}
#chapters dl+dl{
border-top: 2px solid #ccc;
}
#chapters li{
float: left;
width: 33%;
padding: 2px 8px;
box-sizing: border-box;
list-style:none;
}
#chapters a{
display: inline-block;
border: 2px solid transparent;
padding:0 5px;
color: #000;
max-width: 100%;
white-space: pre;
overflow: hidden;
text-overflow: ellipsis;
text-decoration: none;
}
#chapters a:hover{
color:blue;
border-color:blue;
}
#chapters a.cur{
border-color:orange;
}
`}, document.head);
}
if(gUrl == 'mobile'){
_cE('style', {text: `
html, body{min-height:100vh!important; background:#222!important}
body .UnderPage .subHeader {background-color: rgba(255, 255, 255, 0.68);}
.UnderPage{background:#222!important}
#commicBox{overflow:hidden; width: 80%; margin: 0 auto; }
#commicBox>div{text-align:center; padding-left: 10vw;}
#pageNum {
position: fixed;
top: 50px;
background: rgba(238, 170, 0, 0.5);
color: blanchedalmond;
height: 1.6em;
text-align:center;
line-height: 1.6em;
font-size: 2.3em;
right: 0px;
}
#np_chap{
position: fixed;
bottom:30%;
right: 20px;
z-index: 11111;
}
#np_chap>div>a, #np_chap>a{
cursor: pointer;
display: block;
background: transparent url("/images/page_bg.png") no-repeat scroll center bottom / 100% auto;
width: 40px;
height:40px;
transform: rotate(90deg);
margin-top: 5px;
box-shadow: 0 0 6px -2px rgba(255, 255, 255, 0.65);
border-radius: 8px;
}
#np_chap>div>a:not(:hover), #np_chap>a:not(:hover){
opacity: .5;
}
#np_chap>div>a:last-child{
transform: rotate(-90deg);
}
#np_chap>a{
background: rgba(0, 0, 0, 0.7);
transform:none;
position:relative;
}
/*首页小房子*/
#np_chap>a>span{
position:absolute;
width: 16px;
height:8px;
border: 1.5px solid #fff;
border-top-width: 0;
border-radius: 0 0 2.5px 2.5px;
top:50%;
left:calc(50% - 8px);
pointer-events:none;
}
#np_chap>a>span::before,
#np_chap>a>span::after{
position:absolute;
content: "";
width: 15px;
border-top: 1.5px solid #fff;
transform: rotate(-40deg);
top:-7px;
left:-5px;
}
#np_chap>a>span::before{
transform: rotate(40deg);
left:auto;
right:-5px;
}
#chapters{
display:none;
position: fixed;
z-index: 100000000000;
width: 60%;
max-width: 400px;
max-height: calc(100% - 150px);
height: auto;
overflow-y: scroll;
top:50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(255,255,255,.9);
border: 5px solid rgba(0,0,0,.5);
border-radius: 5px;
}
#chapters.show{
display:block;
}
#tucao{
position: fixed;
top: 30px;
left: 0;
color: #fff;
z-index: 1111111;
height: calc(100% - 115px);
}
#tucao:not(:hover){
opacity: 0.5
}
#tucao ul{
overflow-y:hidden;
height: calc(100% - 40px);
}
#tucao:hover ul{
overflow-y: scroll;
}
#tucao pre{
font-weight: bold;
margin-bottom: 5px;
}
#tucao li{
margin-bottom: 5px;
margin-left: 3px;
}
#tucao span{
padding: 0px 3px;
border-radius: 2px;
cursor: pointer;
border:transparent 1px solid;
}
#tucao span:hover{
background-color:#FFF!important;
color:#000;
border-color:red;
}
.control_scroll{
margin-top: 0!important;
padding-top:0!important;
opacity:.5;
transition: opacity 0.3s cubic-bezier(.55,.09,.68,.53) 0s;
}
.control_scroll:hover{
opacity:1;
}
#m_r_bottom{
display:block!important;
height:38px!important
}
#m_r_bottom>.BtnBox{
display:none;
}
#m_r_slider{
background-clip: content-box;
padding: 14px 0px;
top: 3px;
}
#m_r_slider_ball{
top: 3px;
}
.control_commentIcon{
margin-top: 9px;
}
/*#m_r_panelbox{display:none!important}
#commicBox>div>img{border-top:2px solid red;margin-top:-2px;}*/
/*底栏*/
.botNav{
background-color: #222;
}
.letchepter{
padding-bottom: 40px;
background-color: #222;
border-top-color:#000;
}
.letchepter .disable{
color:#4d4d4d !important;
}
.letchepter .disable:hover{
cursor:not-allowed;
}
@keyframes blink {
0% {opacity: .1;}
100% {opacity: .5;}
}
#resizer{
position: fixed;
top:0;
z-index: 9999999999;
display: block;
height: 100vh;
width: 20px;
background: orange;
cursor: col-resize;
opacity: 0;
right: calc((100% - 80%) / 2 - 20px / 2);
}
#resizer::before{
content: attr(title);
width: 100%;
height: 100%;
text-align: center;
writing-mode: tb;
writing-mode: sideways-rl;
line-height: 20px;
letter-spacing: .3em;
color: #fff;
display: block;
}
#resizer.undraggable{
background: #f88066;
}
#resizer:not(.dragging):hover{
animation: blink .5s infinite;
}
#resizer.dragging{
opacity: .8;
}
`}, document.head);
var updateMobilePage = () => {
var data = $$('body script:not([src])').map(s => s.textContent.match(/mReader\.initData\((.+\})(?=,\s*(?:"|'))/)).find(s=>s)[1];
_cE('script', {text: `(function(data){
//去倒计时guanggao
window['times'] = 0;
typeof window['llt'] === 'function' && window['llt']();
var _cE = ${_cE.toString()};
var _preventParentScrolling = ${_preventParentScrolling.toString()};
` + (function(){
var tucao = _cE('div', {id:'tucao'}, document.body);
_cE('small', {text: ' 更新日期:'}, _cE('h3', {text: '<' + data.chapter_name+'>'}, tucao));
if(data.updatetime){
let d = new Date(data.updatetime * 1000 + (new Date().getTimezoneOffset() + 8 * 60) * 60 * 1000);
_cE('pre', {text:
`${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()} ${d.getHours()}:${d.getMinutes()}`
.replace(/\d+/g, n => n.length === 1 ? `0${n}` : n)
}, tucao);
}
var ldp = _cE('p', {text: '评论加载中..'}, tucao);
window.success_jsonpCallback = function(json){
var length = json.data && json.data.list && json.data.list.length || 0;
ldp.textContent = (json.msg=='提交成功'? '' : ' '+json.msg) + (length ? ' 现有 '+ length+'/'+(json.data && json.data.total || 0)+' 吐槽:' : '');
if(!length) return;
var ul = _cE('ul', null, tucao),
opacity = 1,
tc = null;
for(var i=0; i<length; i++){
tc = json.data.list[i];
_cE('span', {text: tc.title, title: tc.nickname+' (uid: '+tc.uid+')\nIP:'+tc.ip}, _cE('li', null, ul)).style.backgroundColor = 'rgba(39, 117, 247, '+ opacity +')';
opacity -= 1 / (length + 1);
}
window.jQuery('#comment_count').show();
_preventParentScrolling(ul);
};
_cE('script', {
src: '//interface.dmzj.com/api/viewpoint/'
+ 'getViewpoint?callback=success_jsonpCallback&more=1&type='
+ data.chapter_type+ '&type_id='+data.comic_id+'&chapter_id='
+ data.id+'&_='+ new Date().getTime()
}, document.body).onload = function(){
this.remove();
window.success_jsonpCallback = null;
};
}).toString().replace(/^[^{]+{/, '') + `)(${data})`}, document.head).remove();
try{
data = JSON.parse(data);
console.info(data.page_url.join('\n'));
}catch(ex){
return console.error(ex);
}
var np_chap = _cE('span', {id:'np_chap'}, document.body),
np = _cE('div', null, np_chap);
_cE('span', null, _cE('a', {title: '章节目录', href: '../../info/'+data.comic_id+'.html'}, [np_chap]));
_cE('a', {title: '上一话', href: `/view/${data.comic_id}/${data.prev_chap_id}.html`}, np)
.style.display = data.prev_chap_id ? '' : 'none';
_cE('a', {title: '下一话', href: `/view/${data.comic_id}/${data.next_chap_id}.html`}, np)
.style.display = data.next_chap_id ? '' : 'none';
$$('.beforeChapter')[0].classList.toggle('disable', !data.prev_chap_id);
$$('.afterChapter')[0].classList.toggle('disable', !data.next_chap_id);
//将eval脚本运行在页面环境,减少沙箱环境影响
_cE('script', { text: `(function(sum_pages, localStorageKey){
var _cE = ${_cE.toString()};
` + (function(){
var _pageNum = _cE('div', {id:'pageNum', text: '1/' + sum_pages}, document.body),
imgs = null,
mReader = window.mReader;
//改良原来的获取当前页码方法
mReader.getCurrPage = function(){
imgs = imgs || document.querySelector('#commicBox>div[id]').children;
var ch = document.documentElement.clientHeight;
for(var i=0;i<imgs.length;i++){
var r = imgs[i].getBoundingClientRect();
if(r.top <= 95 && r.bottom > 95)
return i + 1;
}
};
var isScrolling = false;
var _updatePager = function(){
isScrolling = false;
// 页码
!_isSlider && mReader.updatePageDisplay();
var i = mReader.getCurrPage();
if(i) return (_pageNum._page != i) && (_pageNum.textContent = (_pageNum._page = i) + '/' + sum_pages);
}
var updatePager = function(){
if(isScrolling) return;
isScrolling = true;
requestAnimationFrame(_updatePager);
};
addEventListener('scroll', updatePager);
addEventListener('resize', updatePager);
//修复拖拽进度条
var slider = document.getElementById('m_r_slider_ball'),
sliderBar = document.getElementById('m_r_slider'),
_isSlider = false,
_sliderOffset = 0;
if(slider && sliderBar){
mReader.clickAction = eval('('+ mReader.clickAction.toString()
.replace(/#m_r_bottom/g, '#mark')
+').bind(mReader)');
//拖拽滑块跳转
addEventListener('mousemove', eval('('+ mReader.touchMoveAction.toString()
.replace(/^.*\{/, '$&\nif(!_isSlider) return;\n')
.replace('touches[0]', 'event')
.replace('32 -', '_sliderOffset - ')
.replace(/.*\}$/,'_pageNum.textContent = this.curr_page + "/"+ this.page_num;$&')
+').bind(mReader)'));
slider.onmousedown = event => {
if(event.button !== 0 || event.target !== slider) return;
_isSlider = true;
_sliderOffset = event.clientX - slider.offsetLeft - slider.parentNode.offsetLeft;
};
addEventListener('mouseup', () => {
if(!_isSlider) return;
_isSlider = false;
mReader.touchEndAction();
});
//点击进度条位置跳转
sliderBar.addEventListener('mousedown', eval('('+ mReader.touchMoveAction.toString()
.replace(/^.*\{/, '$&\nif(event.button !== 0)return;\nevent.preventDefault();'
+'\n_isSlider = true;\n')
.replace('touches[0]', 'event')
.replace('32 -', '2*')
.replace('currX < max', 'currX <= max')
.replace(/.*\}$/,'_pageNum.textContent = this.curr_page + "/"+ this.page_num;$&')
+').bind(mReader)'));
}
//弹出确定取消订阅窗口询问,以免误点击取消订阅。
if(typeof window.canDY === 'function'){
var _canDY = window.canDY;
window.canDY = obj => {
if(obj.classList.contains('dy_h') && !window.confirm('是否确定取消订阅?'))
return;
_canDY(obj);
};
}
//订阅相关 js 链接继承协议
if(typeof window.comicUrl === 'string')
window.comicUrl = window.comicUrl.replace(/^https?:/, location.protocol);
document.getElementById('m_r_panelbox').removeAttribute('onclick');
//拖拽滚动页面
function Drag({id, cursor, onMousedown, onMousemove, onMouseup}){
this.cursor = cursor;
this.dragAreaId = id;
this.onMousedown = onMousedown;
this.onMousemove = onMousemove;
this.onMouseup = onMouseup;
this.init();
}
Drag.prototype = {
_isMousedown: false,
_x:0, _y:0, _lx: 0, _ly: 0,
_wh: 0, _ww: 0,
init:function(){
['mousedown', 'mouseup', 'mousemove'].forEach(e => addEventListener(e, this));
},
_setCursorTimeout: null,
setCursor: function(isMove){
document.body.style.cursor = isMove ? this.cursor : '';
},
handleEvent: function(event){
switch(event.type){
case 'mousedown' :
if(!(event.buttons & 1) || event.target.id !== this.dragAreaId)
return;
this._isMousedown = true;
event.preventDefault();
this._x = this._lx = event.clientX;
this._y = this._ly = event.clientY;
this._wh = window.innerHeight;
this._ww = window.innerWidth;
clearTimeout(this._setCursorTimeout);
this._setCursorTimeout = setTimeout(this.setCursor.bind(this), 150, true);
if(typeof this.onMousedown === 'function')
this.onMousedown.call(this);
break;
case 'mouseup' :
if(!this._isMousedown) return;
this._isMousedown = false;
clearTimeout(this._setCursorTimeout);
this.setCursor();
if(typeof this.onMouseup === 'function')
this.onMouseup.call(this);
break;
case 'mousemove' :
if(!(event.buttons & 1) || !this._isMousedown) return;
var x = event.clientX - this._x,
y = event.clientY - this._y;
if(typeof this.onMousemove === 'function')
this.onMousemove.call(this, event, x, y);
this._lx = event.clientX;
this._ly = event.clientY;
break;
}
}
};
new Drag({
id: 'm_r_panelbox',
cursor: 'move',
onMousemove: function(event, x, y) {
if(Math.sqrt(x * x + y * y) < 10)
return;
//屏蔽漫画页怪异模式下无法获取根节点scrollTop
var st = document.documentElement.scrollTop || document.body.scrollTop,
dis = event.clientY - this._ly;
scrollTo(0, st - dis * Math.min(1.8, 1 + Math.abs(dis) * 100 / this._wh));
}
});
var resizer = _cE('div', {id: 'resizer', title: '拖拽改变图片最小宽度'}, document.body);
var commicBox = document.getElementById('commicBox');
var resziePic = function (width) {
if(width > 0 && width <= 100){
commicBox.style.width = `${width}%`;
resizer.style.right = `calc(${(100 - width) / 2}% - 20px / 2)`;
}
}
addEventListener('storage', function(event){
if(event.key !== localStorageKey) return;
resziePic(parseFloat(event.newValue, 10));
});
var resizerWidth = parseFloat((localStorage.getItem(localStorageKey) || 0), 10);
if(resizerWidth > 0){
resziePic(resizerWidth);
}else{
//初次使用时强制显示
resizer.classList.add('dragging');
localStorage.setItem(localStorageKey, 80);
}
new Drag({
id: 'resizer',
cursor: 'col-resize',
onMousedown: function(){
clearTimeout(this._setDragingTimeout);
this._setDragingTimeout = setTimeout(() => {
resizer.classList.add('dragging');
}, 150);
},
onMouseup: function(){
clearTimeout(this._setDragingTimeout);
resizer.classList.remove('dragging');
resizer.classList.remove('undraggable');
this._resizerUndraggable = false;
if(typeof this._resizerWidth === 'number' && this._resizerWidth > 0 && this._resizerWidth < 100){
localStorage.setItem(localStorageKey, this._resizerWidth);
window.jQuery(window).trigger('scroll');
}
},
onMousemove: function(event, x, y) {
if(Math.abs(x) < 5) return;
var right = (this._ww - event.clientX) / this._ww * 100;
var width = 100 - right * 2;
if((width - 10) / 100 * this._ww < 300 || width > 100){
if(!this._resizerUndraggable){
this._resizerUndraggable = true;
resizer.classList.add('undraggable');
}
if(width > 100) {
if(x > 0) return;
}else{
if(x < 0) return;
}
}else{
if(this._resizerUndraggable){
resizer.classList.remove('undraggable');
this._resizerUndraggable = false;
}
}
this._resizerWidth = width;
commicBox.style.width = `${width}%`;
resizer.style.right = `calc(${right}% - 20px / 2)`;
updatePager();
},
});
}).toString().replace(/^[^{]+{/, '') + `)(
${data.sum_pages},
'${(GM_info && GM_info.script && GM_info.script.name || 'DMZJ_GM') + '_resizerWidth'}'
)`}, document.head).remove();
};//updateMobilePage end
//通过屏蔽漫画页面为怪异模式判定
if(document.compatMode === 'BackCompat' && (/漫画(内容)?不存在/.test(document.body.textContent) || document.body.textContent.trim() === 'File not found.')){
document.body.innerHTML = `
<div id="msgContainer">
<p>该漫画浏览器端被屏蔽,正在尝试恢复。。</p>
<style>
#msgContainer{
position:absolute; top:0; left:0;
display: flex; flex-direction: column;
width:100%; min-height: 100vh;
align-items: center; justify-content: center;
background-color:#222;
z-index:99999999999999; opacity:1;
transition: opacity 1s ease-in-out 1s;
}
#msgContainer p{
color:#fff; font-size:30px; text-align:center;
transition: font-size .5s linear 0s, color .2s linear 0s;
}
</style>
</div>
`;
_cE('link', {href:'/css/style.css?2015102217', type: 'text/css', rel: 'stylesheet'}, [document.head]);
_cE('link', {href:'/css/global.css?2015111317', type: 'text/css', rel: 'stylesheet'}, [document.head]);//权重降低
var scriptLoader = urls => Promise.all(urls.map(url => new Promise((resolve, reject) => {
var script = _cE('script', {src: url}, document.body);
script.onload = resolve;
script.onerror = reject;
})));
var queues = arr => Promise.all(arr.map(a => typeof a === 'function' ? new Promise(a) : a));
//shijizhiling 8785
var pathname = location.pathname.split('/');
var chapterId = pathname.pop().split('.').shift();
var comicName = pathname.pop();
var getChapter = queues([
callback => {
//地址栏漫画id是数字
if(/^\d+$/.test(comicName)){
return callback(comicName);
}
//抓取pc端页面数据获取数字id
let onErr = text => callback(Promise.reject(new Error(text)));
GM_xmlhttpRequest({
method:'GET',
timeout: 25000,
url: `${location.protocol}//manhua.dmzj.com/${comicName}/`,
onerror: () => onErr('获取漫画 ID 请求失败!'),
ontimeout: () => onErr('获取漫画 ID 请求超时!'),
onload: e => {
let match = e.responseText &&
e.responseText.match(/var g_comic_id = "(\d+)";/);
match ? callback(match[1]) : onErr('该漫画真的不存在或可能已被删除!');
}
});
}]).then(e => {
const subId = e[0];
if(!subId) throw new Error(e);
//屏蔽漫画章节id全局变量依赖
_cE('script', { text: `(function(){
window.subId = ${subId};
window.chapterId = ${chapterId};
})()`}, document.head).remove();
return queues([
//`//v3api.dmzj.com/comic/${subId}.json`,
`//v3api.dmzj.com/comic/comic_${subId}.json`,
`//v3api.dmzj.com/chapter/${subId}/${chapterId}.json`
].map(url => callback => {
let onErr = text => callback(Promise.reject(new Error(`获取漫画章节目录请求${text}!`)));
GM_xmlhttpRequest({
method:'GET',
timeout: 25000,
url: 'https:' + url,
onerror: () => onErr('发生错误'),
ontimeout: () => onErr('超时'),
onload: callback
});
}));
});
scriptLoader(['/js/jquery-1.9.1.min.js']).then(() => queues([
getChapter,//获取章节
scriptLoader([
'/js/jquery.cookie.js',
'/js/common.js',
'/js/domain.js',
'/js/m_reader.js?2015102416',
'/js/TSB.js',
'/js/main.js',
'/js/jquery.lazyload.min.js',
]),
])).then(e => {
_cE('script', {text: `
(() => {
var $window = $(window);
eval('$.fn.lazyload =' + $.fn.lazyload.toString()
.replace('$("<img />")', 'let _time = new Date().getTime(); $&')
.replace(/(?=\\.bind\\("load")/, \`.bind("error", event => {
//保守小于 800 毫秒认为是浏览器 ssl 响应错误,实际远小于 800。
if(new Date().getTime() - _time < 800 && event.target.src.startsWith('https://imgsmall.')){
self.loaded = true;
self.dispatchEvent(new Event('ssl_error'));
}
})\`));
})();
`}, document.body);
let json;
try{
json = [JSON.parse(e[0][0].responseText),
JSON.parse(e[0][1].responseText)];
}catch(ex){
if(e[0][1].responseText.trim() === '章节不存在')
throw new Error('章节不存在,真的删除了。。');
throw new Error(ex);
}
//必须等待获取章节id全局变量依赖
return scriptLoader(['/js/m_readerBg.js?20160720']).then(() => {
return json;
});
}).then(([json1, json2]) => {
document.body.insertAdjacentHTML('afterBegin', '<div class="UnderPage"><div class="sharWin"id="read_Shar"><div class="sharClose"></div><p class="sharBar">分享到:</p><div class="sharBox"><div id="bdshare"class="bdshare_t bds_tools"><a class="bds_tsina sina"style=""></a><a class="bds_tqq tqq"></a><a class="bds_qzone zone"></a></div></div></div><section id="currentCache"><div class="view-imgBox"id="m_r_imgbox_0"><div class="mh_box"><div id="commicBox"></div><div class="botNav"><div class="botNav_box"><a class="tc"href=""><span>吐槽<em>0</em></span></a><a class="dy"onclick="canDY(this)"id="dys"href="javascript:void(0);"><span>订阅</span></a><a class="fx"onclick="sharwindow()"><span>分享</span></a></div></div><div class="letchepter"><a href="javascript:void(0);"onclick="$(\'#loadPrevChapter\').click()"class="beforeChapter"><上一章</a><em>/</em><a href="" class="ChapterLestMune">返回目录</a><em>/</em><a href="javascript:void(0);"onclick="$(\'#loadNextChapter\').click()"class="afterChapter">下一章></a></div></div></div></section><div class="subHeader"style="display: none; z-index: 999999999999999999;"id="m_r_title"><a href="javascript:"class="iconRet"onclick="mReader.returnBtn()"></a><a href="javascript:;"class="BarTit"></a><a href="javascript:"class="iconShar"onClick="sharwindow()"></a></div><div class="control_bottom"style="display: none; z-index: 999999999999999999;"id="m_r_bottom"><div class="BtnBox"><div class="load_box next"id="loadNextChapter"onclick="mReader.nextBtnAction()"></div><div class="load_box prev"id="loadPrevChapter"onclick="mReader.prevBtnAction()"></div><div class="page_left"id="m_r_nums"><span>1</span>/1</div></div><div class="control_scroll"><a href=""class="control_commentIcon"><em id="comment_count"></em></a><div class="scroll_left_Box"><div class="scroll_box"id="m_r_slider"><div class="scroll_barX"></div><div class="scroll_bar"id="m_r_slider_ball"ontouchmove="mReader.touchMoveAction(event)"ontouchend="mReader.touchEndAction(event)"></div></div></div></div></div><div class="control_panel alpha"style=" display:block"id="m_r_panelbox"prompt="true"onclick="mReader.clickAction(event)"><div class="mark"style="display: none;"id="mark"></div></div></div>');
var chapters = json1.chapters ? json1.chapters.map(d => d.data.find(cid => cid.chapter_id == chapterId)) : null;
var cindex, chapter, index;
if(!chapters || chapters.every(c => !c)){
//数据库最新章节列表缓存未更新
chapter = json2;
cindex = index = 0;
}else{
cindex = chapters.findIndex(c => c);
chapter = chapters[cindex];
index = json1.chapters ? json1.chapters[cindex].data.indexOf(chapter) : 0;
}
var data = {
id: chapterId,
comic_id: json1.id || chapter.comic_id,
chapter_name: chapter.chapter_title || chapter.title,
chapter_order: chapter.chapter_order,
createtime: chapter.updatetime,
updatetime: chapter.updatetime,
//防止混合内容屏蔽,替换为相同协议的图片链接
page_url: (json2.page_url || []).map(url => url.replace(/^https?:/, location.protocol)),
chapter_type:0,
chapter_num:chapter.chapter_order,
sum_pages:json2.picnum,
direction:json2.direction,
filesize:chapter.filesize,
picnum:json2.picnum,
hit:json1.hit_num,
comment_count:json2.comment_count
};
if(json1.chapters && json1.chapters[cindex].data.length > index + 1)
data.prev_chap_id = json1.chapters[cindex].data[index + 1].chapter_id;
if(index > 0)
data.next_chap_id = json1.chapters[cindex].data[index - 1].chapter_id;
document.title = json1.title ? json1.title + ' - ' + data.chapter_name : data.chapter_name;
_cE('script', {text:`mReader.initData(${JSON.stringify(data)}, "${json1.title}", "${json1.cover}");`}, [document.body]);
updateMobilePage();
var div = _cE('div', {id: 'chapters'});
if(json1.chapters){
div.innerHTML = '<dl>' + json1.chapters.map((d, i) => {
return d.data.map((c, j) => {
return `<li><a ${i == cindex && j == index ? 'class="cur" ' : ''}href="/view/${json1.id}/${c.chapter_id}.html" title="${c.chapter_title}">${c.chapter_title}</a></li>`;
}).join('');
}).map((c, i) => {
return `<dt>${json1.chapters[i].title}</dt>
<dd><ul>${c}</ul></dd>`;
}).join('') + '</dl>';
}else{
div.innerHTML = `<h2 style="color:red">暂时无章节,或者被屏蔽删除!</h2>`;
}
_preventParentScrolling(div);
//修复分享按钮
_cE('script', {id: 'bdshare_js', data: 'type=tools&mini=1'}, document.body);
_cE('script', {id: 'bdshell_js', src: '//static.dmzj.com/baidushare/static/js/shell_v2.js?cdnversion=' + Math.ceil(new Date()/3600000)}, document.body);
//修复吐槽链接
$$('.tc, .control_commentIcon').forEach(tc => tc.href = `/viewpoint/${data.comic_id}/${data.id}.html`);
$$('.BarTit')[0].textContent = chapter.chapter_title;
//没有触发resize、scroll事件无法显示第一张图片。
//异步延时触发,避免同步渲染计算图片元素无高度值,会将图片全部加载。
_cE('script', {text:`setTimeout(() => window.jQuery(window).trigger('scroll'), 100);`}, document.body).remove();
$$('#commicBox img').forEach(img => img.addEventListener('ssl_error', event => {
let url = event.target.dataset.original;
console.info(`图片:${url} \n可能服务证书错误导致浏览器无法加载,尝试使用 http 方式加载。`);
if(!url) return;
url = url.replace('https:', 'http:');
new Promise((resolve, reject) => GM_xmlhttpRequest({
method:'GET', timeout: 25000, url, responseType: 'blob',
onerror: reject, ontimeout: reject, onload: resolve,
headers: {'Referer': 'http://images.dmzj.com/'}
})).then(res => {
event.target.src = URL.createObjectURL(res.response);
//还原 fadeIn 动画
let opacity = 0, step = 1 - opacity, start = null, animate = (ts) => {
if(!start) start = ts;
opacity += step * ((ts - start) / 2000);
if(opacity >= 1) opacity = '';
event.target.style.opacity = opacity;
if(opacity !== '') requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
}, () => {});
}, {once: true}));
var msg = $$('#msgContainer>p')[0];
if(msg){
_cE('p', {text: '恢复成功!!', style: 'color: green;'}, msg);
msg.style.cssText = 'font-size:12px; color:#888;';
var msgContainer = msg.parentNode;
msgContainer.addEventListener('transitionend', event => {
if(event.propertyName === 'color' && event.target === msg){
msgContainer.style.opacity = 0;
}else if(event.propertyName === 'opacity' && event.target === msgContainer){
msgContainer.remove();
}
});
}
var btn = $$('#np_chap>a')[0];
var backLink = $$('.ChapterLestMune')[0];
backLink.href = btn.href;
document.body.appendChild(div);
document.addEventListener('click', event=>{
if(event.button === 0 && (event.target === btn || event.target === backLink)){
div.classList.toggle('show');
return event.preventDefault();
}
if(div.contains(event.target))
return;
div.classList.remove('show');
});
}).catch(e => {
console.error(e);
$$('#msgContainer>p')[0].appendChild(
_cE('p', {html: `恢复失败。。<br/><small>${e.message}</small>`, style: 'color: red;'})
).parentNode.style.cssText = 'font-size:12px; color:#888;';
});
}else{
updateMobilePage();
}
}else if('mobileInfo'== gUrl){
if(document.compatMode === 'BackCompat' && document.body.textContent.includes('此漫画暂不提供观看')){
new Promise((resolve, reject) => {
let onErr = text => reject(new Error(`获取漫画章节目录请求${text}!`));
GM_xmlhttpRequest({
method:'GET',
timeout: 25000,
//url: `https://v2api.dmzj.com/comic/${location.pathname.match(/\/(\d+)\.html/)[1]}.json`,
url: `https://v3api.dmzj.com/comic/comic_${location.pathname.match(/\/(\d+)\.html/)[1]}.json`,
onerror: () => onErr('发生错误'),
ontimeout: () => onErr('超时'),
onload: (e) => resolve(JSON.parse(e.responseText))
});
}).then(json => {
document.title = json.title;
document.body.innerHTML = `
<div><img src="${json.cover}" align="left" width="102" height="137">
<h2>${json.title}</h2>
<p>${json.description}</p>
</div>
`;
var div = _cE('div', {id: 'chapters'}, document.body);
console.log(json);
div.innerHTML = '<dl>' + json.chapters.map((d, i) => {
return d.data.map(c => {
return `<li><a href="/view/${json.id}/${c.chapter_id}.html" title="${c.chapter_title}">${c.chapter_title}</a></li>`;
}).join('');
}).map((c, i) => {
return `<dt>${json.chapters[i].title}</dt>
<dd><ul>${c}</ul></dd>`;
}).join('') + '</dl>';
});
}
}else if('mobileHome'== gUrl){
_cE('style', {text: `
.imgBox [class^='col_3_'] li{
width: 10%!important;
min-width: 120px;
margin: 0px 0% 0% 3%!important;
}
.imgBox [class^='col_2'] li{
width: 18%!important;
min-width: 200px;
}
.imgBox [class^='col_3_'] li img{
height: auto!important;
}
.imgBox [class^='col_3_'] li:nth-child(7n+1){
clear:left;
}
`}, document.head);
}
})();