- // ==UserScript==
- // @name Manga Loader
- // @namespace http://www.fuzetsu.com/MangaLoader
- // @version 1.4.13
- // @description Loads manga chapter into one page in a long strip format, supports switching chapters and works for a variety of sites, minimal script with no dependencies, easy to implement new sites
- // @copyright 2014+, fuzetsu
- // @noframes
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_deleteValue
- // @grant GM_registerMenuCommand
- // @match http://bato.to/read/*
- // @match http://mangafox.me/manga/*/*/*
- // @match http://readms.com/r/*/*/*/*
- // @match http://mangastream.com/read/*/*/*/*
- // @match http://g.e-hentai.org/s/*/*
- // @match http://exhentai.org/s/*/*
- // @match *://www.fakku.net/*/*/read*
- // @match http://www.mangareader.net/*/*
- // @match http://www.mangahere.co/manga/*/*
- // @match http://www.mangapanda.com/*/*
- // @match http://mangadeer.com/manga/*/*/*/*
- // @match http://mangacow.co/*/*
- // @match http://nowshelf.com/watch/*
- // @match http://nhentai.net/g/*/*
- // @match http://centraldemangas.net/online/*/*
- // @match http://narutomanga.com.br/leitura/online/capitulo/*
- // @match http://bleachmanga.com.br/leitura/online/capitulo/*
- // @match http://www.mangatown.com/manga/*/*/*
- // @match http://mangajoy.com/*/*
- // @match http://*.dm5.com/m*
- // @match http://raw.senmanga.com/*/*/*
- // @match http://www.japscan.com/lecture-en-ligne/*
- // @match http://www.pecintakomik.com/manga/*/*
- // @match http://dynasty-scans.com/chapters/*
- // @match http://www.onemanga.me/*/*
- // ==/UserScript==
- // don't bother running if in a frame
- if (window.top !== window.self) return;
-
- // set to true for manga load without prompt
- var BM_MODE = false;
-
- var scriptName = 'Manga Loader';
- var pageTitle = document.title;
-
- /**
- Sample Implementation:
- {
- match: "http://domain.com/.*" // the url to react to for manga loading
- , img: '#image' // css selector to get the page's manga image
- , next: '#next_page' // css selector to get the link to the next page
- , numpages: '#page_select' // css selector to get the number of pages. elements like (select, span, etc)
- , curpage: '#page_select' // css selector to get the current page. usually the same as numPages if it's a select element
- , nextchap: '#next_chap' // css selector to get the link to the next chapter
- , prevchap: '#prev_chap' // same as above except for previous
- , wait: 3000 // how many ms to wait before auto loading (to wait for elements to load)
- , pages: function(next_url, current_page_number, callback, extract_function) {
- // gets called requesting a certain page number (current_page_number)
- // to continue loading execute callback with img to append as first parameter and next url as second parameter
- // only really needs to be used on sites that have really unusual ways of loading images or depend on javascript
- }
-
- Any of the CSS selectors can be functions instead that return the desired value.
- }
- */
-
- var implementations = [{ // Batoto
- match: "^http://bato.to/read/.*",
- img: '#comic_page',
- next: '#full_image + div > a',
- numpages: '#page_select',
- curpage: '#page_select',
- nextchap: 'select[name=chapter_select]',
- prevchap: 'select[name=chapter_select]',
- invchap: true
- }, { // MangaPanda
- match: "^http://www.mangapanda.com/.*/[0-9]*",
- img: '#img',
- next: '.next a',
- numpages: '#pageMenu',
- curpage: '#pageMenu',
- nextchap: 'td.c5 + td a',
- prevchap: 'table.c6 tr:last-child td:last-child a'
- }, { // MangaFox
- match: "^http://mangafox.me/manga/[^/]*/[^/]*/[^/]*",
- img: '#image',
- next: 'a.next_page',
- numpages: function() {
- return extractInfo('select.m') - 1;
- },
- curpage: 'select.m',
- nextchap: '#chnav p + p a',
- prevchap: '#chnav a'
- }, { // MangaStream
- match: "^http://(readms|mangastream).com/(r|read)/[^/]*/[^/]*/[^/]*",
- img: '#manga-page',
- next: '.next a',
- numpages: function() {
- var lastPage = getEl('.subnav-wrapper .controls .btn-group:last-child ul li:last-child');
- return parseInt(lastPage.textContent.match(/[0-9]/g).join(''), 10);
- },
- nextchap: function(prev) {
- var found;
- var chapters = [].slice.call(document.querySelectorAll('.controls > div:first-child > .dropdown-menu > li a'));
- chapters.pop();
- for (var i = 0; i < chapters.length; i++) {
- if (window.location.href.indexOf(chapters[i].href) !== -1) {
- found = chapters[i + (prev ? 1 : -1)];
- if (found) return found.href;
- }
- }
- },
- prevchap: function() {
- return this.nextchap(true);
- }
- }, { // MangaReader
- match: "^http://www.mangareader.net/.*/.*",
- img: '#img',
- next: '.next a',
- numpages: '#pageMenu',
- curpage: '#pageMenu',
- nextchap: 'td.c5 + td a',
- prevchap: 'table.c6 tr:last-child td:last-child a'
- }, { // MangaTown
- match: "^http://www.mangatown.com/manga/[^/]*/v[0-9]*/c[0-9]*",
- img: '#image',
- next: '#viewer a',
- numpages: '.page_select select',
- curpage: '.page_select select',
- nextchap: '#top_chapter_list',
- prevchap: '#top_chapter_list',
- wait: 1000
- }, { // MangaCow
- match: "^http://mangacow\\.co/.*/[0-9]*",
- img: '.prw > a > img',
- next: '.prw > a:last-child',
- numpages: 'select.cbo_wpm_pag',
- curpage: 'select.cbo_wpm_pag',
- nextchap: function(prev) {
- var chapSel = getEl('select.cbo_wpm_chp');
- var nextChap = chapSel.options[chapSel.selectedIndex + (prev ? 1 : -1)];
- if (nextChap) {
- return 'http://mangacow.co/' + window.location.pathname.slice(1, window.location.pathname.slice(1).indexOf('/') + 2) + nextChap.value;
- }
- },
- prevchap: function() {
- return this.nextchap(true);
- }
- }, { // MangaHere
- match: "^http://www.mangahere.co/manga/.*/.*",
- img: '#viewer img',
- next: '#viewer a',
- numpages: 'select.wid60',
- curpage: 'select.wid60',
- nextchap: function(prev) {
- var chapters = getEls('.reader_tip > p:nth-last-child(2) > a, .reader_tip > p:nth-last-child(1) > a'),
- tag = chapters[0] && chapters[0].previousElementSibling && chapters[0].previousElementSibling.textContent.trim();
- if (tag === 'Next Chapter:') {
- if (prev) {
- return chapters[1];
- } else {
- return chapters[0];
- }
- } else {
- if (prev) {
- return chapters[1];
- }
- }
- },
- prevchap: function() {
- return this.nextchap(true);
- }
- }, { // MangaDeer
- match: "^http://mangadeer\\.com/manga/.*",
- img: '.img-link > img',
- next: '.page > span:last-child > a',
- numpages: '#sel_page_1',
- curpage: '#sel_page_1',
- nextchap: function(prev) {
- var ddl = getEl('#sel_book_1');
- var index = ddl.selectedIndex + (prev ? -1 : 1);
- if (index >= ddl.options.length) return;
- var mangaName = window.location.href.slice(window.location.href.indexOf('manga/') + 6);
- mangaName = mangaName.slice(0, mangaName.indexOf('/'));
- return 'http://mangadeer.com/manga/' + mangaName + ddl.options[index].value + '/1';
- },
- prevchap: function() {
- return this.nextchap(true);
- }
- }, { // Central de Mangas
- match: "^http://(centraldemangas\\.net|(bleachmanga|narutomanga)\\.com\\.br/leitura)/online/[^/]*/[0-9]*",
- img: '#manga-page',
- next: '#manga-page',
- numpages: '#manga_pages',
- curpage: '#manga_pages',
- nextchap: function(prev) {
- var url = window.location.href,
- chapters = getEl('#manga_caps'),
- urlPre = url.slice(0, url.lastIndexOf('/') + 1),
- newChap = chapters.options[chapters.selectedIndex + (prev ? -1 : 1)];
- return newChap ? urlPre + newChap.textContent : null;
- },
- prevchap: function() {
- return this.nextchap(true);
- },
- pages: function(url, num, cb, ex) {
- var url = url.slice(0, url.lastIndexOf('-') + 1) + ("0" + num).slice(-2) + url.slice(url.lastIndexOf('.'));
- cb(url, url);
- }
- }, { // Manga Joy
- match: "^http://mangajoy.com/[^/]*/[0-9]*",
- img: '.prw img',
- next: '.nxt',
- numpages: '.wpm_pag.mng_rdr > div:nth-child(3) > ul > li:nth-child(3) > select',
- curpage: '.wpm_pag.mng_rdr > div:nth-child(3) > ul > li:nth-child(3) > select',
- nextchap: function(prev) {
- var chapter = extractInfo('.wpm_pag.mng_rdr > div:nth-child(3) > ul > li:nth-child(2) > select', {
- type: 'value',
- val: prev ? 1 : -1
- });
- if (chapter) {
- var urlParts = window.location.href.slice(7).split('/');
- while (urlParts.length > 2) urlParts.pop();
- return 'http://' + urlParts.join('/') + '/' + chapter;
- }
- },
- prevchap: function() {
- return this.nextchap(true);
- }
- }, { // GEH/EXH
- match: "^http://(g.e-hentai|exhentai).org/s/.*/.*",
- img: '.sni > a > img, #img',
- next: '.sni > a, #i3 a'
- }, { // Fakku
- match: "^http(s)?://www.fakku.net/.*/.*/read",
- img: '.current-page',
- next: '.current-page',
- numpages: '.drop',
- curpage: '.drop',
- pages: function(url, num, cb, ex) {
- var firstNum = url.lastIndexOf('/'),
- lastDot = url.lastIndexOf('.');
- var c = url.charAt(firstNum);
- while (c && !/[0-9]/.test(c)) {
- c = url.charAt(++firstNum);
- }
- var curPage = parseInt(url.slice(firstNum, lastDot), 10);
- var url = url.slice(0, firstNum) + ('00' + (curPage + 1)).slice(-3) + url.slice(lastDot);
- cb(url, url);
- }
- }, { // Nowshelf
- match: "^http://nowshelf.com/watch/[0-9]*",
- img: '#image',
- next: '#image',
- numpages: function() {
- return parseInt(getEl('#page').textContent.slice(3), 10);
- },
- curpage: function() {
- return parseInt(getEl('#page > input').value, 10);
- },
- pages: function(url, num, cb, ex) {
- var url = url.slice(0, -7) + ('00' + num).slice(-3) + url.slice(-4);
- cb(url, url);
- }
- }, { // nhentai
- match: "^http://nhentai\\.net\\/g\\/[0-9]*/[0-9]*",
- img: '#image-container > a > img',
- next: '#image-container > a > img',
- numpages: '.num-pages',
- curpage: '.current',
- pages: function(url, num, cb, ex) {
- url = url.replace(/\/[^\/]*$/, '/') + num;
- cb(url, url);
- }
- }, { // dm5
- match: "^http://[^\\.]*\\.dm5\\.com/m[0-9]*",
- img: '#cp_image',
- next: '#cp_image',
- numpages: '#pagelist',
- curpage: '#pagelist',
- pages: function(url, num, cb, ex) {
- var cid = window.location.href.match(/m[0-9]*/g)[2].slice(1),
- xhr = new XMLHttpRequest();
- xhr.open('get', 'imagefun.ashx?cid=' + cid + '&page=' + num);
- xhr.onload = function() {
- var images = eval(xhr.responseText);
- console.log(self.images);
- cb(images[0], images[0]);
- };
- xhr.send();
- }
- }, { // Senmanga
- match: "^http://raw\\.senmanga\\.com/[^/]*/[0-9]*/[0-9]*",
- img: '#picture',
- next: '#omv > table > tbody > tr:nth-child(2) > td > a',
- numpages: 'select[name=page]',
- curpage: 'select[name=page]',
- nextchap: function(prev) {
- var url = window.location.href,
- current = url.match(/\/([0-9]+)\//)[1];
- return window.location.href.replace(/[0-9]+\/[0-9]+\/?$/, '') + (parseInt(current) + (prev ? -1 : 1)) + '/1';
- },
- prevchap: function() {
- return this.nextchap(true);
- }
- }, { // japscan
- match: "^http://www\\.japscan\\.com/lecture-en-ligne/[^/]*/[0-9]*",
- img: '#imgscan',
- next: '#next_link',
- numpages: '#pages',
- curpage: '#pages',
- nextchap: '#next_chapter',
- prevchap: '#back_chapter'
- }, { // pecintakomik
- match: "^http://www\\.pecintakomik\\.com/manga/[^/]*/[^/]*",
- img: '.picture',
- next: '.pager a:nth-child(3)',
- numpages: 'select[name=page]',
- curpage: 'select[name=page]',
- nextchap: function(prev) {
- var chapters = getEl('select[name=chapter]'),
- chapter = chapters.options[chapters.selectedIndex + (prev ? 1 : -1)];
- if (chapter) {
- return window.location.href.replace(/\/[^\/]*\/[0-9]*\/?$/, '/' + chapter.value);
- }
- },
- prevchap: function() {
- return this.nextchap(true);
- }
- }, { // dynasty-scans
- match: "^http://dynasty-scans.com/chapters/.*",
- img: '#image > img',
- next: '#image > img',
- numpages: function() {
- return unsafeWindow.pages.length;
- },
- curpage: function() {
- return parseInt(getEl('#image > div.pages-list > a.page.active').textContent);
- },
- nextchap: '#next_link',
- prevchap: '#prev_link',
- pages: function(url, num, cb, ex) {
- url = unsafeWindow.pages[num - 1].image;
- cb(url, url);
- }
- }, { // OneManga
- match: "^http://www\\.onemanga\\.me/[^/]*/[0-9]*",
- img: 'img.manga-page',
- next: '.nav_pag > li:nth-child(1) > a',
- numpages: 'select.cbo_wpm_pag',
- curpage: 'select.cbo_wpm_pag',
- nextchap: function(prev) {
- var curChap = parseInt(extractInfo('select.cbo_wpm_chp', {type: 'value'})),
- targetChap = curChap + (prev ? -1 : 1);
- return window.location.href.replace(/\/[0-9]*(\/[0-9]*\/?)?$/, '/' + targetChap);
- },
- prevchap: function() {
- return this.nextchap(true);
- }
- }];
-
- var log = function(msg, type) {
- type = type || 'log';
- if (type === 'exit') {
- throw scriptName + ' exit: ' + msg;
- } else {
- console[type](scriptName + ' ' + type + ': ', msg);
- }
- };
-
- var getEl = function(q, c) {
- if (!q) return;
- return (c || document).querySelector(q);
- };
-
- var getEls = function(q, c) {
- return [].slice.call((c || document).querySelectorAll(q));
- };
-
- var storeGet = function(key) {
- if (typeof GM_getValue === "undefined") {
- var value = localStorage.getItem(key);
- if (value === "true" || value === "false") {
- return (value === "true") ? true : false;
- }
- return value;
- }
- return GM_getValue(key);
- };
-
- var storeSet = function(key, value) {
- if (typeof GM_setValue === "undefined") {
- return localStorage.setItem(key, value);
- }
- return GM_setValue(key, value);
- };
-
- var storeDel = function(key) {
- if (typeof GM_deleteValue === "undefined") {
- return localStorage.removeItem(key);
- }
- return GM_deleteValue(key);
- };
-
- var extractInfo = function(selector, mod, context) {
- selector = this[selector] || selector;
- if (typeof selector === 'function') {
- return selector.call(this);
- }
- var elem = getEl(selector, context),
- option;
- mod = mod || {};
- if (elem) {
- switch (elem.nodeName.toLowerCase()) {
- case 'img':
- return (mod.altProp && elem.getAttribute(mod.altProp)) || elem.src || elem.getAttribute('src');
- case 'a':
- return elem.href || elem.getAttribute('href');
- case 'ul':
- return elem.children.length;
- case 'select':
- switch (mod.type) {
- case 'index':
- return elem.options.selectedIndex + 1;
- case 'value':
- option = elem.options[elem.options.selectedIndex + (mod.val || 0)] || {};
- return option.value;
- default:
- return elem.options.length;
- }
- break;
- default:
- switch (mod.type) {
- case 'index':
- return parseInt(elem.textContent);
- default:
- return elem.textContent;
- }
- }
- }
- };
-
- var addStyle = function() {
- if (!this.MLStyle) {
- this.MLStyle = document.createElement('style');
- this.MLStyle.dataset.name = 'ml-style';
- document.head.appendChild(this.MLStyle);
- }
- this.MLStyle.textContent += [].join.call(arguments, '\n');
- };
-
- var toStyleStr = function(obj, selector) {
- var stack = [],
- key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- stack.push(key + ':' + obj[key]);
- }
- }
- if (selector) {
- return selector + '{' + stack.join(';') + '}';
- } else {
- return stack.join(';');
- }
- };
-
- var throttle = function(callback, limit) {
- var wait = false;
- return function() {
- if (!wait) {
- callback();
- wait = true;
- setTimeout(function() {
- wait = false;
- }, limit);
- }
- };
- };
-
- var createButton = function(text, action, styleStr) {
- var button = document.createElement('button');
- button.textContent = text;
- button.onclick = action;
- button.setAttribute('style', styleStr || '');
- return button;
- };
-
- var getViewer = function(prevChapter, nextChapter) {
- var viewerCss = toStyleStr({
- 'background-color': 'black',
- 'font': '0.813em courier',
- 'text-align': 'center',
- }, 'body'),
- imagesCss = toStyleStr({
- 'margin-top': '10px',
- 'margin-bottom': '10px'
- }, '.ml-images'),
- imageCss = toStyleStr({
- 'max-width': '100%',
- 'display': 'block',
- 'margin': '3px auto'
- }, '.ml-images img'),
- counterCss = toStyleStr({
- 'background-color': '#222',
- 'color': 'white',
- 'border-radius': '10px',
- 'width': '30px',
- 'margin-left': 'auto',
- 'margin-right': 'auto',
- 'margin-top': '-12px',
- 'padding-left': '5px',
- 'padding-right': '5px',
- 'border': '1px solid white',
- 'z-index': '100',
- 'position': 'relative'
- }, '.ml-counter'),
- navCss = toStyleStr({
- 'text-decoration': 'none',
- 'color': 'white',
- 'background-color': '#444',
- 'padding': '3px 10px',
- 'border-radius': '5px',
- 'transition': '250ms'
- }, '.ml-chap-nav a'),
- navHoverCss = toStyleStr({
- 'background-color': '#555'
- }, '.ml-chap-nav a:hover'),
- statsCss = toStyleStr({
- 'position': 'fixed',
- 'bottom': '0',
- 'right': '0',
- 'background-color': '#222',
- 'color': 'white',
- 'padding': '7px',
- 'border-top-left-radius': '5px',
- 'opacity': '0.4',
- 'transition': '250ms',
- 'cursor': 'default'
- }, '.ml-stats'),
- statsCollapseCss = toStyleStr({
- 'color': 'orange',
- 'cursor': 'pointer'
- }, '.ml-stats-collapse'),
- statsHoverCss = toStyleStr({
- 'opacity': '1'
- }, '.ml-stats:hover');
- // clear all styles and scripts
- var title = document.title;
- document.head.innerHTML = '<meta name="viewport" content="width=device-width, initial-scale=1">';
- document.title = title;
- // navigation
- var nav = '<div class="ml-chap-nav">' + (prevChapter ? '<a href="' + prevChapter + '">Prev Chapter</a> ' : '') +
- (storeGet('mAutoload') ? '' : '<a href="" data-ignore="true">Exit</a> ') +
- (nextChapter ? '<a href="' + nextChapter + '">Next Chapter</a>' : '') + '</div>';
- // stats
- var stats = '<div class="ml-stats"><span title="hide stats" class="ml-stats-collapse">>></span><span class="ml-stats-content"></span></div>';
- // combine ui elements
- document.body.innerHTML = nav + '<div class="ml-images"></div>' + nav + stats;
- // add all styles to the page
- addStyle(viewerCss, imagesCss, imageCss, counterCss, navCss, navHoverCss, statsCss, statsCollapseCss, statsHoverCss);
- // set up return UI object
- var UI = {
- images: getEl('.ml-images'),
- statsContent: getEl('.ml-stats-content'),
- statsCollapse: getEl('.ml-stats-collapse')
- };
- // set up listeners
- document.addEventListener('click', function(evt) {
- if (evt.target.nodeName === 'A' && !evt.target.dataset.ignore && evt.target.parentNode.className.indexOf('ml-chap-nav') !== -1) {
- log('next chapter will autoload');
- storeSet('autoload', 'yes');
- }
- }, false);
- UI.statsCollapse.addEventListener('click', function(evt) {
- var test = UI.statsCollapse.textContent === '>>';
- UI.statsContent.style.display = test ? 'none' : '';
- UI.statsCollapse.textContent = test ? '<<' : '>>';
- }, false);
- return UI;
- };
-
- var getCounter = function(imgNum) {
- var counter = document.createElement('div');
- counter.classList.add('ml-counter');
- counter.textContent = imgNum;
- return counter;
- };
-
- var addImage = function(src, loc, imgNum, callback) {
- var image = new Image(),
- counter = getCounter(imgNum);
- image.onerror = function() {
- log('failed to load ' + src);
- image.onload = null;
- image.style.backgroundColor = 'white';
- image.title = 'Reload?';
- image.src = '//rgeorgeeb-tilebuttongenerator.googlecode.com/hg-history/c35993682c2d50149976fd7a1f302f8c01a88716/asset-studio/src/res/clipart/icons/refresh.svg';
- image.onclick = function() {
- image.remove();
- counter.remove();
- addImage(src, loc, imgNum, callback);
- };
- };
- image.onload = callback;
- image.src = src;
- loc.appendChild(image);
- loc.appendChild(counter);
- };
-
- var loadManga = function(imp) {
- var ex = extractInfo.bind(imp),
- imgUrl = ex('img'),
- nextUrl = ex('next'),
- numPages = ex('numpages'),
- curPage = ex('curpage', {
- type: 'index'
- }) || 1,
- nextChapter = ex('nextchap', {
- type: 'value',
- val: (imp.invchap && -1) || 1
- }),
- prevChapter = ex('prevchap', {
- type: 'value',
- val: (imp.invchap && 1) || -1
- }),
- xhr = new XMLHttpRequest(),
- d = document.implementation.createHTMLDocument(),
- addAndLoad = function(img, next) {
- updateStats();
- addImage(img, UI.images, curPage, function() {
- pagesLoaded += 1;
- updateStats();
- });
- loadNextPage(next);
- },
- updateStats = function() {
- UI.statsContent.textContent = ' ' + pagesLoaded + '/' + curPage + ' loaded' + (numPages ? ', ' + numPages + ' total' : '');
- },
- getPageInfo = function() {
- var page = d.body;
- d.body.innerHTML = xhr.response;
- try {
- // find image and link to next page
- addAndLoad(ex('img', imp.imgmod, page), ex('next', null, page));
- } catch (e) {
- log('error getting details from next page, assuming end of chapter.');
- }
- },
- loadNextPage = function(url) {
- if (mLoadLess && count % loadInterval === 0) {
- if (resumeUrl) {
- resumeUrl = null;
- } else {
- resumeUrl = url;
- log('waiting for user to scroll further before loading more images, loaded ' + count + ' pages so far, next url is ' + resumeUrl);
- return;
- }
- }
- if (curPage + 1 > numPages) {
- log('reached "numPages" ' + numPages + ', assuming end of chapter');
- return;
- }
- if (lastUrl === url) {
- log('last url (' + lastUrl + ') is the same as current (' + url + '), assuming end of chapter');
- return;
- }
- curPage += 1;
- count += 1;
- lastUrl = url;
- if (imp.pages) {
- imp.pages(url, curPage, addAndLoad, ex);
- } else {
- xhr.open('get', url);
- xhr.onload = getPageInfo;
- xhr.onerror = function() {
- log('failed to load page, aborting', 'error');
- };
- xhr.send();
- }
- },
- count = 1,
- pagesLoaded = curPage - 1,
- loadInterval = 10,
- lastUrl, UI, resumeUrl;
-
- if (!imgUrl || !nextUrl) {
- log('failed to retrieve ' + (!imgUrl ? 'image url' : 'next page url'), 'exit');
- }
-
- UI = getViewer(prevChapter, nextChapter);
-
- UI.statsContent.textContent = ' 0/1 loaded, ' + numPages + ' total';
-
- if (mLoadLess) {
- window.onscroll = throttle(function(e) {
- if (!resumeUrl) return; // exit early if we don't have a position to resume at
- var scrollBottom = document.body.scrollHeight - ((document.body.scrollTop || document.documentElement.scrollTop) + window.innerHeight);
- if (scrollBottom < 4500) {
- log('user scroll nearing end, loading more images starting from ' + resumeUrl);
- loadNextPage(resumeUrl);
- }
- }, 100);
- }
-
- addAndLoad(imgUrl, nextUrl);
-
- };
-
- var pageUrl = window.location.href,
- btnLoadCss = toStyleStr({
- 'position': 'fixed',
- 'bottom': 0,
- 'right': 0,
- 'padding': '5px',
- 'margin': '0 10px 10px 0',
- 'z-index': '99999'
- }),
- btnLoad;
-
- // used when switching chapters
- var autoload = storeGet('autoload');
- // manually set by user in menu
- var mAutoload = storeGet('mAutoload') || false;
- // should we load less pages at a time?
- var mLoadLess = storeGet('mLoadLess') === false ? false : true;
-
- // clear autoload
- storeDel('autoload');
-
- // register menu commands
- if (typeof GM_registerMenuCommand === 'function') {
- GM_registerMenuCommand('ML: ' + (mAutoload ? 'Disable' : 'Enable') + ' manga autoload', function() {
- storeSet('mAutoload', !mAutoload);
- window.location.reload();
- });
- GM_registerMenuCommand('ML: Load ' + (mLoadLess ? 'full chapter in one go' : '10 pages at a time'), function() {
- storeSet('mLoadLess', !mLoadLess);
- window.location.reload();
- });
- }
-
- log('starting...');
-
- var success = implementations.some(function(imp) {
- if (imp.match && (new RegExp(imp.match, 'i')).test(pageUrl)) {
- if (BM_MODE || mAutoload || autoload) {
- log('autoloading...');
- setTimeout(loadManga.bind(null, imp), imp.wait || 0);
- return true;
- }
- // append button to dom that will trigger the page load
- btnLoad = createButton('Load Manga', function(evt) {
- loadManga(imp);
- this.remove();
- }, btnLoadCss);
- document.body.appendChild(btnLoad);
- return true;
- }
- });
-
- if (!success) {
- log('no implementation for ' + pageUrl, 'error');
- }