NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
(function(){ var defaultSettings = { prefetchNext: 5, //number of prefetched pages ahead prefetchBack: 5, //number of prefetched pages behind prefetchNextStart: 2, //number of prefetched pages ahead when the script starts prefetchBackStart: 1, //number of prefetched pages behind when the script starts prefetchNoNext: true, //specifies if previous page should be prefetched when theres no next page fullLayout: true, //true for full layout mode, false for minimalistic mode clickImgNavigates: true, //specifies if clicking the image will change pages clikLeftHalfGoesBack: true, //specifies if clicking the left half of the image will take you to the previous page flipControlsManga: false, //flip the controls (L/R arrows, L/R image click, back/next buttons) for mangas or other right-to-left content autozoom: false, //enable fit-to-screen shrinkWidth: false, //when fit-to-screen enabled and image too wide, shrink it shrinkHeight: false, //when fit-to-screen enabled and image too long, shrink it expandWidth: false, //when fit-to-screen enabled and image too narrow, expand it expandHeight: false, //when fit-to-screen enabled and image too short, expand it showButtons: true, //show or hide the buttons (back/next, bookmarks, settings, etc...) borderLR: 0, //pixels to leave as border to the sides of the image when zooming and scrolling borderUD: 0, //pixels to leave as border above and below the image when zooming and scrolling goToBookmark: true, //if you have 1 bookmark saved for a site, asks you if you want to go there when you visit the site moveWhileLoading: false, //lets you change pages even if the image for the next page is still loading debugMode: false, //alerts on errors, and shows some of the currently cache'd pages/images with the "," key showSettingsOnFail: false, //if no settings are found for this site and default ones didn't work, show settings screen keyboardShortcuts: { //keyboard shortcuts... back: {name: 'LEFT', keyCode: 37, ctrlKey: false, shiftKey: false, altKey: false}, next: {name: 'RIGHT', keyCode: 39, ctrlKey: false, shiftKey: false, altKey: false}, scroll_left: {name: 'CTRL + LEFT', keyCode: 37, ctrlKey: true, shiftKey: false, altKey: false}, scroll_right: {name: 'CTRL + RIGHT', keyCode: 39, ctrlKey: true, shiftKey: false, altKey: false}, scroll_up: {name: 'CTRL + UP', keyCode: 38, ctrlKey: true, shiftKey: false, altKey: false}, scroll_down: {name: 'CTRL + DOWN', keyCode: 40, ctrlKey: true, shiftKey: false, altKey: false}, reload: {name: '.', keyCode: 190, ctrlKey: false, shiftKey: false, altKey: false}, set_bm: {name: 'CTRL + ALT + B', keyCode: 66, ctrlKey: true, shiftKey: false, altKey: true}, add_bm: {name: 'CTRL + ALT + A', keyCode: 65, ctrlKey: true, shiftKey: false, altKey: true}, layout: {name: '-', keyCode: isWebKit() ? 189 : 173, ctrlKey: false, shiftKey: false, altKey: false}, botones: {name: 'SHIFT + -', keyCode: isWebKit() ? 189 : 173, ctrlKey: false, shiftKey: true, altKey: false}, fit: {name: '+', keyCode: isWebKit() ? 187 : 171, ctrlKey: false, shiftKey: false, altKey: false}, slide: {name: 'CTRL + ALT + S', keyCode: 83, ctrlKey: true, shiftKey: false, altKey: true}, debug_mode: {name: 'CTRL + ALT + X', keyCode: 88, ctrlKey: true, shiftKey: false, altKey: true}, debug_info: {name: ',', keyCode: 188, ctrlKey: false, shiftKey: false, altKey: false} } }; // ==UserScript== // @name Webcomic Reader // @author ameboide // @version 2015.03.27 // @namespace http://userscripts.org/scripts/show/59842 // @description Can work on almost any webcomic/manga page, preloads 5 or more pages ahead (or behind), navigates via ajax for instant-page-change, lets you use the keyboard, remembers your progress, and it's relatively easy to add new sites // @lastchanges added 2 sites, fixed 6 more // @updatetype 24 // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_openInTab // @include http://www.sluggy.com/* // @include http://sluggy.com/* // @include http://www.penny-arcade.com/comic* // @include http://penny-arcade.com/comic* // @include http://www.xkcd.com/* // @include http://xkcd.com/* // @include http://www.xkcd.org/* // @include http://xkcd.org/* // @include http://www.xkcd.net/* // @include http://xkcd.net/* // @include https://www.xkcd.com/* // @include https://xkcd.com/* // @include http://www.giantitp.com/* // @include http://www.dilbert.com/strip/* // @include http://dilbert.com/strip/* // @include http://hf.dilbert.com/strip/* // @include http://www.explosm.net/* // @include http://explosm.net/* // @include http://www.nuklearpower.com/* // @include http://www.reallifecomics.com/* // @include http://reallifecomics.com/* // @include http://www.pvponline.com/* // @include http://pvponline.com/* // @include http://www.brawlinthefamily.com/* // @include http://drmcninja.com/* // @include http://www.vgcats.com/*/* // @include http://www.phdcomics.com/* // @include http://www.cad-comic.com/* // @include http://www.smbc-comics.com/* // @include http://abstrusegoose.com/* // @include http://thedoghousediaries.com/* // @include http://www.erfworld.com/* // @include http://es.juanelo.net/*/* // @include http://www.mangastream.com/* // @include http://mangastream.com/* // @include http://readms.com/* // @include http://www.qwantz.com/* // @include http://qwantz.com/* // @include http://www.2pstart.com/*/* // @include http://www.spaceavalanche.com/* // @include http://www.gunshowcomic.com/* // @include http://gunshowcomic.com/* // @include http://www.terrorisland.net/* // @include http://nedroid.com/* // @include http://manga.animea.net/* // @include http://www.bobandgeorge.com/* // @include http://bobandgeorge.com/* // @include http://www.shamusyoung.com/* // @include http://www.stationv3.com/* // @include http://www.lfgcomic.com/page/* // @include http://lfgcomic.com/page/* // @include http://www.gpf-comics.com/* // @include http://www.questionablecontent.net/* // @include http://questionablecontent.net/* // @include http://miscellanea.wellingtongrey.net/* // @include http://www.daisyowl.com/* // @include http://daisyowl.com/* // @include http://www.hyperdeathbabies.com/* // @include http://www.kyo.cn/Viewcartoon/* // @include http://www.mangatoshokan.com/* // @include http://amultiverse.com/* // @include http://wondermark.com/* // @include http://www.amazingsuperpowers.com/* // @include http://www.anymanga.com/* // @include http://anymanga.com/* // @include http://mangafox.me/* // @include http://www.leasticoulddo.com/* // @include http://leasticoulddo.com/* // @include http://www.sinfest.net/* // @include http://www.crfh.net/* // @include http://crfh.net/* // @include http://www.pennyandaggie.com/* // @include http://pennyandaggie.com/* // @include http://www.darkbolt.com/* // @include http://darkbolt.com/* // @include http://www.egscomics.com/* // @include http://egscomics.com/* // @include http://www.the-gutters.com/* // @include http://www.punchanpie.net/* // @include http://punchanpie.net/* // @include http://noneedforbushido.com/* // @include http://www.teahousecomic.com/* // @include http://www.applegeeks.com/* // @include http://applegeeks.com/* // @include http://www.mangareader.net/* // @include http://stoptazmo.com/* // @include http://www.arcamax.com/* // @include http://www.nettserier.no/* // @include http://nettserier.no/* // @include http://disneycomics.free.fr/*/show.php?* // @include http://www.nerfnow.com/* // @include http://nerfnow.com/* // @exclude http://www.nerfnow.com/*/comments* // @exclude http://nerfnow.com/*/comments* // @include http://www.virtualshackles.com/* // @include http://www.little-gamers.com/* // @include http://www.digitalunrestcomic.com/* // @include http://digitalunrestcomic.com/* // @include http://www.duelinganalogs.com/* // @include http://www.actiontrip.com/* // @include http://actiontrip.com/* // @include http://www.myextralife.com/* // @include http://www.mondaynightcrew.com/* // @include http://mondaynightcrew.com/* // @include http://notinventedhe.re/* // @include http://www.unshelved.com/* // @include https://www.eviscerati.org/comics* // @include http://read.mangashare.com/* // @include http://haven-reader.net/* // @include http://www.manga2u.me/* // @include http://manga2u.me/* // @include http://buttersafe.com/* // @include http://www.romanticallyapocalyptic.com/* // @include http://romanticallyapocalyptic.com/* // @include http://www.somethingpositive.net/* // @include http://somethingpositive.net/* // @include http://www.rhymes-with-witch.com/* // @include http://rhymes-with-witch.com/* // @include http://www.superstupor.com/* // @include http://superstupor.com/* // @include http://www.misfile.com/* // @include http://www.asofterworld.com/* // @include http://asofterworld.com/* // @include http://www.achewood.com/* // @include http://achewood.com/* // @include http://www.act-i-vate.com/* // @include http://act-i-vate.com/* // @include http://www.biggercheese.com/* // @include http://biggercheese.com/* // @include http://www.gwscomic.com/* // @include http://gwscomic.com/* // @include http://www.fonflatter.de/* // @include http://www.ruthe.de/* // @include http://ruthe.de/* // @include http://www.daybydaycartoon.com/* // @include http://daybydaycartoon.com/* // @include http://www.dieselsweeties.com/* // @include http://dieselsweeties.com/* // @include http://www.foxtrot.com/* // @include http://www.csectioncomics.com/* // @include http://garfieldminusgarfield.net/* // @include http://www.girlgeniusonline.com/* // @include http://www.gocomics.com/* // @exclude http://www.gocomics.com/ // @exclude http://www.gocomics.com/?* // @include http://www.gunnerkrigg.com/* // @include http://gunnerkrigg.com/* // @include http://www.ho-lo.co.il/* // @include http://www.jeffzugale.com/* // @include http://www.threepanelsoul.com/* // @include http://threepanelsoul.com/* // @include http://www.oglaf.com/* // @include http://oglaf.com/* // @include http://www.kevinandkell.com/* // @include http://kevinandkell.com/* // @include http://kittyhawkcomic.com/* // @include http://www.lackadaisycats.com/comic.php* // @include http://lackadaisycats.com/comic.php* // @include http://www.lukesurl.com/* // @include http://mycardboardlife.com/* // @include http://megatokyo.com/* // @include http://www.megatokyo.it/* // @include http://www.megatokyo.de/* // @include http://ex2.unixmanga.net/* // @include http://allmymanga.com/* // @include http://noreasoncomics.com/* // @include http://www.pixelcomic.net/* // @include http://pixelcomic.net/* // @include http://www.redmeat.com/* // @include http://redmeat.com/* // @include http://sexylosers.com/* // @include http://www.doonesbury.com/* // @include http://stalebacon.com/* // @include http://www.mangaeden.com/* // @include http://www.pbfcomics.com/* // @include http://tjandamal.com/* // @include http://sfeertheory.littlefoolery.com/* // @include http://wanderingones.com/* // @include http://www.big-big-truck.com/ayiw/* // @include http://big-big-truck.com/ayiw/* // @include http://wapsisquare.com/* // @include http://www.wastedtalent.ca/* // @include http://www.wulffmorgenthaler.com/* // @include http://wulffmorgenthaler.com/* // @include http://www.weregeek.com/* // @include http://*.katbox.net/* // @include http://*.keenspace.com/* // @include http://*.comicgenesis.com/* // @include http://www.beanleafpress.com/* // @include http://gipcomic.com/* // @include http://www.theoswaldchronicles.com/* // @include http://www.awkwardzombie.com/* // @include http://awkwardzombie.com/* // @include http://www.stainedglasssamurai.com/* // @include http://stainedglasssamurai.com/* // @include http://*.seraph-inn.com/* // @include https://www.fakku.net/manga/* // @include https://www.fakku.net/doujinshi/* // @include http://www.deadwinter.cc/* // @include http://deadwinter.cc/* // @include http://www.loveisintheblood.com/* // @include http://rhapsodies.wpmorse.com/* // @include http://www.piratesofmars.com/* // @include http://www.soulless-comic.com/* // @include http://www.earthsongsaga.com/vol* // @include http://rainchildstudios.com/strawberry/* // @include http://www.goblinscomic.org/* // @include http://www.venusenvycomic.com/* // @include http://venusenvycomic.com/* // @include http://www.meekcomic.com/* // @include http://www.dominic-deegan.com/* // @include http://dominic-deegan.com/* // @include http://yafgc.net/* // @include http://www.sdamned.com/* // @include http://www.twolumps.net/* // @include http://twolumps.net/* // @include http://www.precociouscomic.com/* // @include http://precociouscomic.com/* // @include http://betweenplaces.spiderforest.com/* // @include http://specialschool.spiderforest.com/* // @include http://requiem.spiderforest.com/* // @include http://sevensmith.net/chirault/* // @include http://www.junglestudio.com/roza/* // @include http://www.dream-scar.net/* // @include http://dream-scar.net/* // @include http://www.tryinghuman.com/* // @include http://tryinghuman.com/* // @include http://www.thedreamercomic.com/* // @include http://thedreamercomic.com/ // @include http://www.shazzbaa.com/* // @include http://shazzbaa.com/* // @include http://www.sandraandwoo.com/* // @include http://www.freakangels.com/* // @include http://comics.com/* // @include http://www.sakanacomic.com/* // @include http://www.jaygeefisher.com/* // @include http://jaygeefisher.com/* // @include http://www.doujin-moe.us/* // @include http://keychain.patternspider.net/* // @include http://www.collectedcurios.com/* // @include http://www.doomies.com/* // @include http://doomies.com/* // @include http://www.qgmindpolice.com/* // @include http://www.slowwave.com/* // @include http://slowwave.com/* // @include http://www.sylvanmigdal.com/* // @include http://sylvanmigdal.com/* // @include http://www.c.urvy.org/* // @include http://c.urvy.org/* // @include http://www.the-artiste.net/* // @include http://www.doublefine.com/* // @include http://wwww.survivingtheworld.net/* // @include http://survivingtheworld.net/* // @include http://view.thespectrum.net/* // @include http://www.mangavolume.com/* // @include http://nonadventures.com/* // @include http://www.robandelliot.cycomics.com/* // @include http://robandelliot.cycomics.com/* // @include http://soulsymphonycomic.com/* // @include http://www.blastwave-comic.com/* // @include http://www.channelate.com/* // @include http://www.picturesforsadchildren.com/* // @include http://picturesforsadchildren.com/* // @include http://www.optipess.com/* // @include http://www.drawuntilitsfunny.com/* // @include http://beardfluff.com/* // @include http://lawlscomic.com/* // @include http://www.maakies.com/* // @include http://www.lefthandedtoons.com/* // @include http://trollscience.com/* // @include http://www.diggercomic.com/* // @include http://luciphurrsimps.com/* // @include http://nikkisprite.com/* // @include http://planet-nowhere.com/* // @include http://www.mysisterthefreak.com/* // @include http://www.gronkcomic.com/* // @include http://www.redsplanet.com/* // @include http://www.cowshell.com/* // @include http://everblue-comic.com/* // @include http://tmkcomic.depleti.com/* // @include http://www.remindblog.com/* // @include http://inkdolls.com/* // @include http://www.terra-comic.com/* // @include http://lovecraftismissing.com/* // @include http://www.redmoonrising.org/* // @include http://www.khaoskomix.com/* // @include http://ipaintgirls.com/* // @include http://memoria.valice.net/* // @include http://www.twilightlady.com/* // @include http://submanga.com/* // @include http://g.e-hentai.org/* // @include http://animesquish.com/* // @include http://crazytje.be/* // @include http://www.tenmangas.com/* // @include http://tenmangas.com/* // @include http://www.tenmanga.com/* // @include http://tenmanga.com/* // @include http://www.perveden.com/* // @include http://reader.imangascans.org/* // @include http://www.ekkifu.com/* // @include http://www.bittersweetcandybowl.com/* // @include http://www.doujintoshokan.com/* // @include http://www.imagebam.com/* // @include http://www.exploitationnow.com/* // @include http://www.otakuworks.com/* // @include http://h-manga.info/* // @include http://basicinstructions.net/* // @include http://www.insaneyetisquirrel.com/* // @include http://*.kukudm.com/comiclist/*/*/* // @include http://*.kukudm.net/comiclist/*/*/* // @include http://mh.socomic.com/comiclist/*/*/* // @include http://www.socomic.net/comiclist/*/*/* // @include http://www.webcomicsnation.com/* // @include http://www.pawn.se/* // @include http://www.rpgworldcomic.com/* // @include http://rpgworldcomic.com/* // @include http://maskedretriever.com/* // @include http://www.missmab.com/* // @include http://www.lookwhatibroughthome.com/* // @include http://hijinksensue.com/* // @include http://www.darthsanddroids.net/* // @include http://darthsanddroids.net/* // @include http://www.harkavagrant.com/* // @include http://www.turbosloth.net/* // @include http://turbosloth.net/* // @include http://www.walkinginsquares.com/* // @include http://walkinginsquares.com/* // @include http://dresdencodak.com/* // @include http://www.straysonline.com/comic/* // @include http://straysonline.com/comic/* // @include http://www.emi-art.com/* // @include http://emi-art.com/* // @include http://www.dragonball-multiverse.com/* // @include http://insanesoft.org/fanfyria/* // @include http://*.snafu-comics.com/* // @include http://www.wayfarersmoon.com/* // @include http://wayfarersmoon.com/* // @include http://*.smackjeeves.com/* // @include http://www.10kcommotion.com/* // @include http://10kcommotion.com/* // @include http://somemangas.com/* // @include http://www.multiplexcomic.com/* // @include http://multiplexcomic.com/* // @include http://www.johnandjohn.nl/index.php?*wltypeid=1* // @include http://www.sorcery101.net/* // @include http://www.treadingground.com/* // @include http://www.jerkcity.com/* // @include http://jerkcity.com/* // @include http://www.kiwiblitz.com/* // @include http://thepunchlineismachismo.com/* // @include http://kafkaskoffee.com/* // @include http://www.out-at-home.com/* // @include http://occasionalcomics.com/* // @include http://www.zombieboycomics.com/* // @include http://www.babyblues.com/* // @include http://babyblues.com/* // @include http://www.bearandtiger.com/* // @include http://mangatopia.net/* // @include http://exhentai.org/* // @include http://www.wigucomics.com/* // @include http://www.mankin-trad.net/* // @include http://mankin-trad.net/* // @include http://www.mangahere.co/* // @include http://es.mangahere.co/* // @include http://www.scarygoround.com/* // @include http://scarygoround.com/* // @include http://www.schlockmercenary.com/* // @include http://www.warehousecomic.com/* // @include http://warehousecomic.com/* // @include http://www.tnemrot.com/* // @include http://www.holiday-wars.com/* // @include http://www.zapcomic.com/* // @include http://www.twokinds.net/* // @include http://twokinds.net/* // @include http://www.dumbingofage.com/* // @include http://www.shortpacked.com/* // @include http://www.itswalky.com/* // @include http://itswalky.com/* // @include http://www.evildivacomics.com/* // @include http://axecop.com/* // @include http://www.somethingofthatilk.com/* // @include http://somethingofthatilk.com/* // @include http://www.reddit.com/ // @include http://www.reddit.com/?* // @include http://www.reddit.com/r/* // @exclude http://www.reddit.com/*/comments/* // @include http://blankitcomics.com/* // @include http://www.anime-source.com/* // @include http://anime-source.com/* // @include http://www.mangarush.com/* // @include http://www.citymanga.com/*/*/* // @include http://citymanga.com/*/*/* // @include http://www.dctp.ws/*/V*.html // @include http://dctp.ws/*/V*.html // @include http://dctpws.thetrogdor.com/* // @include http://doctorcatmd.com/* // @include http://www.sheldoncomics.com/* // @include http://sheldoncomics.com/* // @include http://luscious.net/*/pictures/* // @include http://old.lu.scio.us/hentai/albums/* // @exclude http://old.lu.scio.us/hentai/albums/*/page/* // @include http://www.geekculture.com/joyoftech/* // @include http://www.basketcasecomix.com/* // @include http://www.geeklifecomic.com/* // @include http://www.realmofatland.com/* // @include http://realmofatland.com/* // @include http://thedoujin.com/index.php?page=post&s=view&id=* // @include http://eatmanga.com/* // @include http://www.oslevadosdabreca.com/* // @include http://www.thedevilbear.com/* // @include http://thedevilbear.com/* // @include http://www.bladebunny.com/* // @include http://www.exiern.com/* // @include http://nsfw-comix.com/* // @include http://jaynaylor.com/* // @include http://www.anelnoath.com/* // @include http://www.faans.com/* // @include http://www.truefork.org/* // @include http://truefork.org/* // @include http://www.aorange.com/* // @include http://www.strangecandy.net/* // @include http://www.thewotch.com/* // @include http://thewotch.com/* // @include http://www.cheercomic.com/* // @include http://cheercomic.com/* // @include http://www.sgvy.com/* // @include http://sgvy.com/* // @include http://www.drunkduck.com/* // @include http://drunkduck.com/* // @include http://www.ephralon.de/seekers_detailed.php* // @include http://ephralon.de/seekers_detailed.php* // @include http://www.terinu.com/* // @include http://terinu.com/* // @include http://dcisgoingtohell.com/* // @include http://las-historietas.blogspot.com/* // @include http://www.palcomix.com/* // @include http://palcomix.com/* // @include http://www.palcomix.org/* // @include http://palcomix.org/* // @include http://www.whiteninjacomics.com/* // @include http://whiteninjacomics.com/* // @include http://www.apenotmonkey.com/* // @include http://malandchad.com/* // @include http://www.goodmanga.net/* // @include http://www.digitalcomicmuseum.com/* // @include http://digitalcomicmuseum.com/* // @include http://goldenagecomics.co.uk/* // @include http://fourcolorshadows.blogspot.com/* // @include http://thehorrorsofitall.blogspot.com/* // @include http://bato.to/* // @include http://www.eegra.com/* // @include http://www.octopuspie.com/* // @include http://www.lovemenicecomic.com/* // @include http://www.manga-access.com/* // @include http://manga-access.com/* // @include http://www.ju-ni.net/* // @include http://ju-ni.net/* // @include http://blog.saveapathea.com/* // @include http://www.dead-philosophers.com/* // @include http://www.nerd-theater.com/* // @include http://nerd-theater.com/* // @include http://lackadaisy.foxprints.com/comic.php* // @include http://www.mangastream.to/* // @include http://www.kingfeatures.com/* // @include http://kingfeatures.com/* // @include http://www.thezombiehunters.com/* // @include http://thezombiehunters.com/* // @include http://www.bugcomic.com/* // @include http://www.interrobangstudios.com/* // @include http://interrobangstudios.com/* // @include http://www.hlcomic.com/* // @include http://hlcomic.com/* // @include http://syacartoonist.com/* // @include http://satwcomic.com/* // @include http://stupidfox.net/* // @include http://www.casualvillain.com/* // @include http://fanboys-online.com/* // @include http://www.girlswithslingshots.com/* // @include http://www.mntgaiden.com/* // @include http://truyen.vnsharing.net/* // @include http://lovehentaimanga.com/* // @include http://ravensdojo.com/* // @include http://freefall.purrsia.com/* // @include http://www.mangachapter.net/* // @include http://www.shd-wk.com/* // @include http://shd-wk.com/* // @include http://www.pepsaga.com/* // @include http://slimythief.com/* // @include http://www.pebbleversion.com/* // @include http://pebbleversion.com/* // @include http://mentalcatproductions.com/* // @include http://schoolbites.net/* // @include http://www.accurseddragon.com/* // @include http://www.krakowstudios.com/* // @include http://www.stringtheorycomic.com/* // @include http://www.supercrash.net/* // @include http://loveandcapes.com/* // @include http://victorycomic.comicgenesis.com/* // @include http://magellanverse.com/* // @include http://www.evil-comic.com/* // @include http://flakypastry.runningwithpencils.com/* // @include http://www.pointguardian.com/* // @include http://gogetaroomie.chloe-art.com/* // @include http://legendofbill.com/* // @include http://www.springiette.net/* // @include http://springiette.net/* // @include http://www.vampirecheerleaders.net/* // @include http://www.paranormalmysterysquad.com/* // @include http://www.draculaeverlasting.com/* // @include http://www.amazingagentjennifer.com/* // @include http://mindmistress.comicgenesis.com/* // @include http://www.evernightcomic.com/* // @include http://www.xindm.cn/* // @include http://mh2.xindm.cn/* // @include http://www.manga123.com/read/* // @include http://manga.redhawkscans.com/* // @include http://www.mudascantrad.com/* // @include http://slide.extrascans.net/* // @include http://*.thewebcomic.com/* // @include http://www.mangapark.com/* // @include http://mangapark.com/* // @include http://www.manga-go.com/* // @include http://www.comicstriplibrary.org/display/* // @include http://comicstriplibrary.org/display/* // @include http://www.wirepop.com/* // @include http://wirepop.com/* // @include http://www.fantasyrealmsonline.com/manga/* // @include http://foolrulez.org/* // @include http://reader.japanzai.com/* // @include http://www.psychopandas.com/reader/* // @include http://psychopandas.com/reader/* // @include http://www.ourmanga.com/* // @include http://readonline.egscans.org/* // @include http://read.egscans.org/* // @include http://reader.eternalmanga.net/* // @include http://gallery.ryuutama.com/* // @include http://*.tiraecol.net/* // @include http://tiraecol.net/* // @include http://www.conejofrustrado.com/* // @include http://www.e2w-illustration.com/* // @include http://2gamerz.com/* // @include http://reader.fth-scans.com/* // @include http://www.simple-scans.com/* // @include http://simple-scans.com/* // @include http://www.mymangaspot.com/* // @include http://comic.naver.com/* // @include http://www.peteristhewolf.com/* // @include http://peteristhewolf.com/* // @include http://www.wlpcomics.com/* // @include http://wlpcomics.com/* // @include http://www.mangatraders.com/* // @include http://hentaifromhell.net/* // @include http://trenchescomic.com/* // @include http://www.sakicow.com/reader/* // @include http://sakicow.com/reader/* // @include http://www.goominet.com/unspeakable-vault/* // @include http://www.doesnotplaywellwithothers.com/* // @include http://krakowstudios.com/* // @include http://www.aikoniacomic.com/* // @include http://aikoniacomic.com/* // @include http://www.grrlpowercomic.com/* // @include http://www.poisonedminds.com/* // @include http://poisonedminds.com/* // @include http://nodwick.humor.gamespy.com/* // @include http://www.the-whiteboard.com/* // @include http://the-whiteboard.com/* // @include http://www.mezzacotta.net/* // @include http://www.hbrowse.com/* // @include http://www.vexxarr.com/* // @include http://vexxarr.com/* // @include http://aptitude.surfacingpoint.com/* // @include http://www.bardsworth.com/* // @include http://fancyadventures.com/* // @include http://www.chron.com/entertainment/comics-games/comic/* // @include http://www.purplepussy.net/* // @include http://purplepussy.net/* // @include http://www.heroeslocales.com/bunsen/* // @include http://www.readhentaionline.com/* // @include http://readhentaionline.com/* // @include http://www.darklegacycomics.com/* // @include http://darklegacycomics.com/* // @include http://candicomics.com/* // @include http://www.buckocomic.com/* // @include http://bearmageddon.com/* // @include http://betweenfailures.net/* // @include http://www.sisterclaire.com/* // @include http://www.fayerwayer.com/* // @include http://www.niubie.com/* // @include http://www.awesomehospital.com/* // @include http://ars.userfriendly.org/cartoons/* // @include http://www.friendswithboys.com/* // @include http://www.mangago.com/* // @include http://www.jesusandmo.net/* // @include http://www.calamitiesofnature.com/* // @include http://www.rosalarian.com/* // @include http://rosalarian.com/* // @include http://dungeond.com/* // @include http://www.irregularwebcomic.net/* // @include http://adistantsoil.com/* // @include http://comic.nodwick.com/* // @include http://ffn.nodwick.com/* // @include http://ps238.nodwick.com/* // @include http://kronos.mcanime.net/* // @include http://www.ghastlycomic.com/* // @include http://thedevilspanties.com/* // @include http://walkingdeadbr.com/*displayimage.php* // @include http://www.mangapanda.com/* // @include http://mangable.com/* // @include http://dragonflyscans.org/* // @include http://readincesthentai.com/* // @include http://www.animephile.com/* // @include http://hentaistreamer.com/* // @include http://kissmanga.com/* // @include http://www.readmangahentai.com/* // @include http://readmangahentai.com/* // @include http://www.masterbloodfer.org/* // @include http://masterbloodfer.org/* // @include http://www.mangatank.com/* // @include http://www.snowflakescomic.com/* // @include http://mangafox.mobi/* // @include http://www.mangainn.me/* // @include http://invisiblebread.com/* // @include http://www.shiftylook.com/comics/* // @include http://onlinereader.mangapirate.net/* // @include http://www.8comic.com/love/* // @include http://8comic.com/love/* // @include http://www.mangahead.com/* // @include http://mangahead.com/* // @include http://www.vickifox.com/* // @include http://www.spinnyverse.com/* // @include http://zenpencils.com/* // @include http://wootmanga.com/* // @include http://hentai2read.com/* // @include http://m.hentai2read.com/* // @include http://komikmy.com/*/*/* // @include http://www.hentaifr.net/doujinshisheng.php* // @include http://www.sientoymiento.cl/* // @include http://www.commissionedcomic.com/* // @include http://www.mangasky.com/* // @include http://mangapirate.net/* // @include http://nomanga.com/* // @include http://www.pipi.cl/* // @include http://hentaimangaonline.com/* // @include http://webcomics.yaoi911.com/* // @include http://www.whompcomic.com/* // @include http://actiontimebuddies.com/* // @include http://www.superbrophybrothers.com/* // @include http://www.surasplace.com/* // @include http://surasplace.com/* // @include http://mangacow.me/* // @include http://fallensyndicate.com/reader/* // @include http://www.nekothekitty.net/* // @include http://curtailedcomic.com/* // @include http://www.wiemanga.com/* // @include http://img.wiemanga.com/* // @include http://hentai4manga.com/* // @include http://bradcolbow.com/* // @include http://www.gaomanga.com/* // @include http://www.theherobiz.com/* // @include http://guildedage.net/comic/* // @include http://betweenfailures.com/* // @include http://www.claudeandmonet.com/* // @include http://phobia.subcultura.es/tira/* // @include http://www.manga-tu.be/* // @include http://de.ninemanga.com/* // @include http://proxer.me/* // @include http://www.demanga.com/* // @include http://www.meinmanga.com/* // @include http://www.senmanga.com/* // @include http://raw.senmanga.com/* // @include http://www.mangaesta.net/* // @include http://www.mabuns.web.id/* // @include http://www.manga4indo.com/* // @include http://www.bloomingfaeries.com/* // @include http://www.friendshipscans.com/* // @include http://neechan.net/* // @include http://www.komikid.com/* // @include http://komikid.com/* // @include http://blog.komikid.com/* // @include http://www.findchaos.com/* // @include http://chaoslife.findchaos.com/* // @include http://moonoverjune.com/* // @include http://www.shadbase.com/* // @include http://www.shagbase.com/* // @include http://www.mrlovenstein.com/* // @include http://www.anticscomic.com/* // @include http://octopuns.blogspot.com/* // @include http://www.onemanga.me/* // @include http://mangacow.co/* // @include http://www.mangabee.com/* // @include http://www.ver-manga.net/* // @include http://mangadoom.co/* // @include http://www.powernapcomic.com/* // @include http://www.ismanga.com/* // @include http://www.mangabird.com/* // @include http://mangachrome.com/* // @include http://www.7manga.com/* // @include http://7manga.com/* // @include http://www.mangadevil.com/* // @include http://mangadevil.com/* // @include http://www.mangamofo.com/* // @include http://*.hentai.ms/* // @include http://view.mangamonger.com/* // @include http://blackbird.ashen-ray.com/* // @include http://carciphona.com/* // @include http://ahs-comic.com/* // @include http://www.gogetaroomie.com/* // @include http://gogetaroomie.com/* // @include http://*.thecomicseries.com/* // @include http://www.sleepymaid.com/gallery/displayimage.php* // @include http://sleepymaid.com/gallery/displayimage.php* // @include http://www.squid-ops.com/* // @include http://squid-ops.com/* // @include http://www.endcomic.com/* // @include http://www.thenoobcomic.com/* // @include http://thenoobcomic.com/* // @include http://zizki.com/* // @include http://*.zizki.com/* // @include http://pururin.com/* // @include http://www.thedailyblink.com/* // @include http://mangabandits.net/* // @include http://www.neumanga.com/* // @include http://www.pecintakomik.com/* // @include http://www.schizmatic.com/* // @include http://schizmatic.com/* // @include http://www.yuri-ism.net/* // @include http://www.bringbackroomies.com/* // @include http://blindsprings.com/* // @include http://www.wtfcomics.com/*archive.html?* // @include http://wtfcomics.com/*archive.html?* // @include http://www.olympusoverdrive.com/index.php?* // @include http://olympusoverdrive.com/index.php?* // @include http://*gucomics.com/* // @include http://www.punksandnerds.com/* // @include http://*.troutcave.net/* // @include http://www.berserkersdaughter.com/* // @include http://gingerhaze.com/nimona/comic/* // @include http://aiacrowd.com/* // @include http://aspect.waywardstudios.net/* // @include http://chirault.sevensmith.net/* // @include http://cucumber.gigidigi.com/* // @include http://filteredfuzz.com/* // @include http://www.dorktower.com/* // @include http://mangajoy.com/* // @include http://nhentai.net/* // @include http://www.hejibits.com/* // @include http://mangaindo.co/* // @include http://5.79.87.81/* // @include http://www.dm72.com/* // @include http://dm72.com/* // @include http://www.gao-subs.com/* // @include http://www.mangawindow.com/* // @include http://mangawindow.com/* // @include http://omgmanga.com/* // @include http://paintraincomic.com/* // @include http://extrafabulouscomics.com/* // ==/UserScript== var dataCache = null; //cache para no leer del disco y parsear la configuracion en cada getData var firstRun = false; //por si funcionan las GM_* pero falla preguntar sin el "this.", o si tiran una excepcion al preguntar try{ GM_getValue = GM_getValue || this.GM_getValue; }catch(e){ GM_getValue = false; } try{ GM_setValue = GM_setValue || this.GM_setValue; }catch(e){ GM_setValue = false; } try{ GM_deleteValue = GM_deleteValue || this.GM_deleteValue; }catch(e){ GM_deleteValue = false; } try{ GM_xmlhttpRequest = GM_xmlhttpRequest || this.GM_xmlhttpRequest; }catch(e){ GM_xmlhttpRequest = false; } try{ GM_registerMenuCommand = GM_registerMenuCommand || this.GM_registerMenuCommand; }catch(e){ GM_registerMenuCommand = false; } try{ GM_openInTab = GM_openInTab || this.GM_openInTab; }catch(e){ GM_openInTab = false; } try{ //fix para usar data persistente sin pseudogreasemonkey if (!GM_getValue || GM_getValue.toString().indexOf("not supported")>-1) { GM_getValue=function (key,def) { if(!localStorage || !localStorage.hasOwnProperty(key)) return def; var val = localStorage[key]; return val !== undefined ? val : def; }; GM_setValue=function (key,value) { if(!localStorage) return null; return localStorage[key]=value; }; GM_deleteValue=function (key) { if(localStorage) localStorage.removeItem(key); }; } else{ var gmsets = GM_getValue('wcr.settings', null); if(gmsets) dataCache = JSON.parse(gmsets); else{ firstRun = true; GM_setValue('wcr.settings', '{}'); dataCache = {}; } } if(!GM_openInTab) GM_openInTab = window.open; if(!GM_registerMenuCommand || GM_registerMenuCommand.toString().indexOf("not supported")>-1){ GM_registerMenuCommand = function(txt, fun){ var boton = document.createElement('button'); boton.innerHTML = txt; setEvt(boton, 'click', fun); document.body.appendChild(boton); } } }catch(e){} var prefetchSize = confPrefetchSize([defaultSettings.prefetchBack, defaultSettings.prefetchNext]); //number of prefetched pages ahead in each direction var prefetchSizeStart = confPrefetchSizeStart([defaultSettings.prefetchBackStart, defaultSettings.prefetchNextStart]); //number of prefetched pages in each direction the first time var prefetchNoNext = confBool('prefetchNoNext', true); var keepLayout = confKeepLayout(defaultSettings.fullLayout); //decide to keep the original layout of the page (true) or use a clean minimalistic layout (false) var debug = confDebug(defaultSettings.debugMode); //alerts on errors, and shows some of the currently cache'd pages/images with the "," key var showButtons = confShowButtons(defaultSettings.showButtons); //show or hide the buttons (back/next, bookmarks, settings, etc...) var leftImageClick = confLeftImageClick(defaultSettings.clikLeftHalfGoesBack); //specifies if clicking the left half of the image will take you to the previous page var goToBookmark = confBool('goToBookmark', defaultSettings.goToBookmark); var useHistoryAPI = confBool('useHistoryAPI', true); var moveWhileLoading = confBool('moveWhileLoading', defaultSettings.moveWhileLoading); var maximgs = []; //mantener solo este num de imagenes cargadas atras y adelante de la actual para no comer memoria maximgs[1] = Math.max(23, prefetchSize[1]); maximgs[-1] = Math.max(23, prefetchSize[0]); var usarb64 = confBool('b64_images', false); /* paginas[i] = { url: //'substring' or /regexp/ that matches the url img: //gets the <img> element containing the desired image (not just the src, but the whole <img>) //if not present, searches an img with a src containing some common strings like "/comics/" or "/strips/" //'string' means "the <img> element whose src starts with 'string'" back: next: //get the href of the back and next links //if not present, defaults to links containing "back"|"prev" / "next" in the <a> element's innerHTML //'string' means "the href of the <a> element that satisfies 'string' (as an xpath expression) extra: //optional array of additional content, as a 'literal string' or taken from the html by either ['xpath'] or [/regexp/, group number] bgcol: txtcol: //override the default colors of the page for readability or aesthetics //'#RRGGBB', '#RGB', 'rgb(r, g, b)' js: //executes a custom function after a page change, receiving the direction (1=forward, -1=back, 0 the first time) as a parameter scrollx: scrolly: //tells the top-left coordinates for scrolling after changing page (default = U/L) //'U', 'D', 'L', 'R' and 'M' are to show the top, bottom, left, right and middle of the image //or it can be a number (in pixels) or a function that returns a number layout: //forces the default behaviour for the layout (true=keep the original, false=clean it) xelem: //string with an xpath expression to get the element to be used as placeholder for the extra content //used only when keeping the original layout } img/back/next/extra[i] can be either: 'string', ['xpath expression that returns the first element found'], ['xpath expression that returns an array of elements', 'string to put between each element', ?first_index, ?last_index], [/regular expression/, group number to get the desired content] function(html_of_requested_page, position_relative_to_the_starting_page){ return content; } a 'string' is interpreted as part of a default xpath expression for img/back/next, or a literal string for extra[i] */ var paginas = [ { url: 'penny-arcade.com', img: [['#comicFrame img']], extra: [[['.title h2']]], style: '#bb,#header{position:relative;}' }, { url: 'xkcd.', img: ['//div[@id="comic"]//img'], first: '.="|<"', last: '.=">|"', extra: ['<br/>', ['//div[@id="ctitle"]'], function(html, pos) { var href = xpath('//div[@id="comic"]//a/@href', html); return '<br/><a href=' + href + '>' + (href.indexOf('xkcd') >= 0 ? 'Large version' : 'Bonus Link!') + '</a>'; }, function(html, pos) { var comic = xpath('//div[@id="comic"]', html); var img = comic.getElementsByTagName('img')[0]; img.parentNode.removeChild(img); return comic; }], bgcol: '#fff' }, { url: '*.dilbert.com', img: [['.img-comic']], back: '@alt="Older Strip"', next: '@alt="Newer Strip"' }, { url: 'explosm.net/comics', img: [['#main-comic']], extra: [['//small[@class="author-credit-name"]/../../..'], [/<img id="main-comic" .+?\/([^"\/]+)\.\w+"/i, 1], function(html, pos){ var url = selCss('#main-comic', html).parentNode.getAttribute('href'); if(!url) return ''; var htmlVideo = syncRequest(url, pos); return selCss('.flex-video', htmlVideo); }], style: '#wcr_imagen{max-width:none;}' }, { url: 'pvponline.com', img: [['.comic-art img']], extra: [[['.comic header']]], style: '.nav-locked .main-nav{display: none;}' }, { url: 'brawlinthefamily.keenspot.com', extra: [['//div[@class="post-comic"]']], xelem: '//div[@class="post-comic"]' }, { url: 'vgcats.com', img: 'images/' }, { url: 'phdcomics.com/comics', img: 'http://www.phdcomics.com/comics/archive/', extra: [['//title/text()'], ' - ', ['//td/font/i/b/text()'], ['//img[contains(@src, "/comics/archive/")]/following-sibling::table']] }, { url: 'smbc-comics.com', img: [['#comic']], back: [['.prev']], next: [['.next']], extra: [['//div[@id="aftercomic"]/img[contains(@src,"/")]'], [['.cc-newscontent:first-of-type']]], style: '#wcr_extra .date, #wcr_extra .blogtext{text-align: center;}' }, { url: 'abstrusegoose.com', img: 'http://abstrusegoose.com/strips/', extra: ['<br/>[', ['//h3/*/text()'], ']<br/><br/>', [/"storycontent"[\s\S]+?<img [\s\S]+?>([\s\S]+?)<\/div>/i, 1]] }, { url: 'thedoghousediaries.com', img: [['#imgdiv img']], back: [['#previouslink']], next: [['#nextlink']], extra: [[['#title-signoff-share']]] }, { url: /erfworld\.com\/(page\/|$)/, img: ['//div[@class="entry"]//img'], back: 'contains(.,"Older")', next: 'contains(.,"Newer")', extra: [['//div[@class="post"]/*', '', 0, 2], ['//div[@class="post"][1]//div[@class="entry"]/p[not(.//img)]', ''], '</div>'] }, { url: 'erfworld.com', extra: [[['.post>h2']], ['//table[@class="PxgGalleryTable"]//p[not(img)]', '']] }, { url: 'es.juanelo.net/archivo', img: 'http://es.juanelo.net/tiras/', back: '.="« Anterior"', next: '.="Siguiente »"', style: '#page{width:1210px;} .narrowcolumn{width:810px;}' }, { url: 'es.juanelo.net/show', img: ['//div[@id="tirashow"]//img[starts-with(@src, "http://es.juanelo.net/tiras/")]'], back: ['//div[@id="tirashow"]//a[.="« Anterior"]/@href'], next: ['//div[@id="tirashow"]//a[.="Siguiente »"]/@href'], style: '#page{width:1210px;} .narrowcolumn{width:810px;}' }, { url: 'es.juanelo.net/20', img: 'http://es.juanelo.net/tiras/', back: 'contains(.,"«")', next: 'contains(.,"»")', extra: [[['img[src*="/tiras/"]', '<br/>', 1]], [['.post>h2']], [['.entry>p']]], style: '#page{width:1210px;} .narrowcolumn{width:810px;}', bgcol: '#334255' }, { url: 'mangastream.com|readms.com', img: [['#manga-page']], back: [['.previous a']], next: [['.next a']], style: '.subnav[style*="fixed"]{display: none;}#wcr_imagen{max-width:none;}#reader-sky{z-index:-1;}', scrollx:'R', layout: true }, { url: 'terrorisland.net', extra: [['//div[@class="commentary"]', '']] }, { url: 'drmcninja.com', img: 'http://drmcninja.com/comics/', extra: ['<br/>', ['//select[@id="series_select"]'], ['//select[@id="page_select"]'], [['.post-comic .entry']]], js: function(dir){ var selSer = xpath('//div[@id="wcr_div"]//*[@id="series_select"]'); setEvt(selSer, 'change', function(){ exec("document.location.href = '/archives/comic/'+series_arr["+selSer.selectedIndex+"].posts[0];"); }); selSer.style.visibility = 'visible'; selSer.disabled = false; var selPag = xpath('//div[@id="wcr_div"]//*[@id="page_select"]'); setEvt(selPag, 'change', function(){ document.location.href = '/archives/comic/'+selPag.value; }); } }, { url: 'manga.animea.net', img: ['//img[@class="mangaimg"]'], back: function(html, pos){ var page = parseInt(html.match(/var page = (\d+);/)[1]); var pages = parseInt(html.match(/var pages=(\d+);/)[1]); var chapter = html.match(/var chapter="(.+?)";/)[1]; var manga = decodeURI(link[pos]).match(new RegExp('/([^/]+)'+chapter.replace(/[-[\]{}()+?.,\\^$#\s]/g, "\\$&")))[1]; if(page > 1) return '/'+manga+chapter+'-page-'+(page-1)+'.html'; var chap = xpath('//select[@id="chapterlistheader"]/option[@value="'+chapter+'"]/preceding-sibling::option[1]/@value'); return '/'+manga+chap+'-page-end.html'; }, next: function(html, pos){ var page = parseInt(html.match(/var page = (\d+);/)[1]); var pages = parseInt(html.match(/var pages=(\d+);/)[1]); var chapter = html.match(/var chapter="(.+?)";/)[1]; var manga = decodeURI(link[pos]).match(new RegExp('/([^/]+)'+chapter.replace(/[-[\]{}()+?.,\\^$#\s]/g, "\\$&")))[1]; if(page < pages) return '/'+manga+chapter+'-page-'+(page+1)+'.html'; var chap = xpath('//select[@id="chapterlistheader"]/option[@value="'+chapter+'"]/following-sibling::option[1]/@value'); return '/'+manga+chap+'-page-1.html'; }, extra: [[['#chapterlistheader']], [['[name="page"]']]], scrollx:'R', js: function(dir){ var selchap = selCss('#wcr_extra #chapterlistheader'); if(dir){ selchap.innerHTML = selCss('#chapterlistheader', '<div>'+extra[0]+'</div>').innerHTML; } selchap.value = link[posActual].match(/(-chapter-.+?)-/)[1]; } }, { url: 'shamusyoung.com/twentysidedtale', img: 'http://shamusyoung.mu.nu/images/comic_', extra: [['//div[@class="entry-text"]/*', '', 5, -4], ['//h2[@class="entry-title"]']] }, { url: 'gpf-comics.com', img: '/comics/', back: './img[@alt="Previous Comic"]', next: './img[@alt="Next Comic"]' }, { url: 'daisyowl.com', img: ['//div[@align="center"]//img[starts-with(@src,"/comic_images/")]'] }, { url: 'hyperdeathbabies.com', img: 'anomaly/' }, { url: 'kyo.cn', img: function(html, pos){ var index = parseInt(get("index").value) + pos; var chnum = parseInt(get("num").value); if(index > chnum) throw 'fin'; var img_url = get("img_url").value; var pipeichar = parseInt(get("ppchar").value); var preurl = pos ? imagen[0] : get('mainpic').src; preurl = preurl.substr(0, preurl.indexOf('/', 8)+1); var ll = pipeichar - (index+'').length; var tmp = ""; for(var i=0; i<ll; i++) tmp += "0"; return preurl + img_url + tmp + index + ".jpg"; }, back: function(html, pos){ var index = parseInt(get("index").value) + pos - 1; var chnum = parseInt(get("num").value); if(index <= 0) throw '0'; return '##'+index; }, next: function(html, pos){ var index = parseInt(get("index").value) + pos + 1; var chnum = parseInt(get("num").value); if(index > chnum) throw 'fin'; return '##'+index; }, scrollx:'R' }, { url: 'mangatoshokan.com|doujintoshokan.com', img: ['//img[@id="readerPage"]'], back: '.="« Last"', next: '.="Next »"', extra: ['Chapter: ', ['//table[@class="reader"]//select', ' Page: ', 0, 2], '<br/><br/>', ['//form/select[@onchange]']], txtcol: '#fff', scrollx:'R' }, { url: 'amultiverse.com', img: [['#comic img']], extra: [['//div[@class="post-content"]']], js: function(){ if(keepLayout) get('comic').style.height = get('wcr_div').offsetHeight + 'px'; }, xelem: '//div[@id="content"]//div[@class="post-content"]', style: '#comic button{float:none;}' }, { url: 'wondermark.com', img: 'http://wondermark.com/c/', back: '@rel="prev"', next: '@rel="next"', txtcol: '#fff' }, { url: 'amazingsuperpowers.com', img: function(html, pos){ try{ return selCss('#comic-1 img', html); } catch(e){ if(selCss('#comic-1 #comic-short', html)) return selCss('img', html); } }, extra: [[['#comic-1 #comic-short']], function(html, pos){ var href = selCss('#question a', html).href; var htmlHidden = syncRequest(href, pos); return contenido(htmlHidden, [['#comic > *', '']]); }, [['.post']]], style: '#page,#header{width:auto;}', layelem:'//div[@id="comic-1"]' }, { url: 'anymanga.com', img: ['//img[starts-with(@src, "/manga") and not(contains(@src, "/covers/"))]'], back: [/var url_back = "([^\"]+)"/, 1], next: [/var url_next = "([^\"]+)"/, 1], scrollx:'R' }, { url: 'mangafox.me', img: ['//img[@id="image"]'], back: function(html, pos){ var href = contenido(html, ['//a[contains(@class, "prev_page")]/@href'], pos); if(href.indexOf('javascript')<0){ if(href.indexOf('/')<0) return link[pos].replace(/[^\/]*$/, href); return href; } return contenido(html, ['//span[contains(., "Previous Chapter")]/../a/@href'], pos).replace(/\d+\.html/, '999.html'); }, next: function(html, pos){ var current_page = parseInt(html.match(/var current_page=(\d+);/)[1]); var final_page_of_chapter = parseInt(html.match(/var total_pages=(\d+);/)[1]); if(current_page < final_page_of_chapter){ //just load next page var href = contenido(html, ['//a[contains(@class, "next_page")]/@href'], pos); if(href.indexOf('/')<0) return link[pos].replace(/[^\/]*$/, href); return href; } return contenido(html, ['//span[contains(., "Next Chapter")]/../a/@href'], pos); }, extra: [function(html, pos){ if(extra[0]) return extra[0].replace(/(<\/select>)[\s\S]*/i, '$1'); return contenido(html, ['//select[@id="bottom_chapter_list"]'], pos); }, ' ', [['select.m']], '<select id="top_chapter_list" style="display:none"></select>', function(html, pos){ var alt = xpath('//img[@id="image"]/@onerror', html).replace(/^.+?'|'$/g, ''); return '<a id="alt_img" style="display:none" href="'+alt+'"/>'; }], js: function(dir){ if(!dir){ exec('(function unbindear(){'+ 'try{ $(function(){$(document).unbind();}); }'+ 'catch(e){ setTimeout(unbindear, 200); }'+ '})();'); (function rellenar(){ if(get('bottom_chapter_list').innerHTML.trim()){ extra[0] = get('wcr_extra').innerHTML; var opts = selCss('#wcr_extra #bottom_chapter_list').options; var div = document.createElement('div'); for(var i=-1; extra[i]; i--); for(i++; extra[i]; i++){ if(!i) continue; div.innerHTML = extra[i]; var sel = selCss('#bottom_chapter_list', div); for(var j=0; j<opts.length; j++) sel.options[j] = opts[j].cloneNode(true); extra[i] = div.innerHTML; } try{ var sel = selCss('#bottom_bar #bottom_chapter_list'); for(var j=0; j<opts.length; j++) sel.options[j] = opts[j].cloneNode(true); }catch(e){} } else setTimeout(rellenar, 200); })(); } var selcaps = selCss('#wcr_extra #bottom_chapter_list'); var caps = selcaps.options; selcaps.style.cssFloat = ''; for(var i=0; i<caps.length; i++) if(link[posActual].indexOf(caps[i].value+'/') >= 0) return selcaps.selectedIndex = i; return 0; }, onerr: function(url, img, num, pos){ if(num) return null; return xpath('//a[@id="alt_img"]/@href', extra[pos]); }, scrollx:'R' }, { url: 'sinfest.net', back: 'img[@alt="Previous"]', next: 'img[@alt="Next"]', fixurl: function(url, img, link){ return url.replace('http://sinfest', 'http://www.sinfest'); } }, { url: 'crfh.net', img: ['//img[contains(@src, "/crfh")]'] }, { url: 'nuklearpower.com', img: ['//img[contains(@src, "/comics/")]'], back: '@rel="prev"', next: '@rel="next"' }, { url: 'mangareader.net', img: ['//div[@id="imgholder"]//img'], style: '#imgholder{width:auto !important;}', scrollx:'R' }, { url: 'stoptazmo.com', img: 'http://read.', back: function(html, pos){ var selmanga = contenido(html, ['//select[@name="series"]']); var selchap = contenido(html, ['//select[@name="chapter"]']); var selpage = contenido(html, ['//select[@name="pagesel1"]']); var manga = selmanga.value; var chap, page; if(selpage.selectedIndex > 0){ chap = selchap.value; page = selpage[selpage.selectedIndex-1].value; } else if(selchap.selectedIndex > 0){ chap = selchap[selchap.selectedIndex-1].value; page = 0; } else throw 'primera pag del primer cap'; return [link[0], 'chapter=' + chap + '&chapter_hid=' + chap + '&pagesel1=' + page + '&image_hid=' + page + '&manga_hid=' + manga + '&series=' + manga]; }, next: function(html, pos){ var selmanga = contenido(html, ['//select[@name="series"]']); var selchap = contenido(html, ['//select[@name="chapter"]']); var selpage = contenido(html, ['//select[@name="pagesel1"]']); var manga = selmanga.value; var chap, page; if(selpage.selectedIndex < selpage.length-1){ chap = selchap.value; page = selpage[selpage.selectedIndex+1].value; } else if(selchap.selectedIndex < selchap.length-1){ chap = selchap[selchap.selectedIndex+1].value; page = 0; } else throw 'ultima pag del ultimo cap'; return [link[0], 'chapter=' + chap + '&chapter_hid=' + chap + '&pagesel1=' + page + '&image_hid=' + page + '&manga_hid=' + manga + '&series=' + manga]; }, extra: [['//form[@name="pageSelector1"]']], scrollx:'R', style: 'form img{display:none;} #wcr_imagen{display:inline;}' }, { url: 'questionablecontent.net/', extra: [['//div[@id="news"]']], xelem: '//div[@id="news"]' }, { url: 'arcamax.com/thefunnies', img: '/newspics/' }, { url: /nettserier.no\/./, img: '/_striper/', back: 'starts-with(., "F") and contains(., "rre ")', next: 'starts-with(., "Neste ")' }, { url: 'disneycomics.free.fr', img: ['//div/img'] }, { url: 'virtualshackles.com', img: ['//div[@id="comicbox"]/img'] }, { url: 'qwantz.com', back: [['[rel="prev"]']], next: [['[rel="next"]']], extra: ['<br/>', [/<span class="rss-title">(.*?)<\/span>/, 1], '<br/><br/>', function(html, pos){ return unescape(contenido(html, [/mailto:.+?subject=(.*?)\""?/, 1])); }] //original: http://userscripts.org/scripts/show/51520 }, { url: 'notinventedhe.re', img: 'h', style: 'button{display:inline;color:#000;float:none;} #comic-nav{margin:0;}' }, { url: 'unshelved.com', style: 'button{display:inline;color:#000;float:none;}' }, { url: 'eviscerati.org', img: [['.field-name-field-comic-image img']], back: [['.previous a']], next: [['.next a']] }, { url: 'haven-reader.net', img: [['#mangaPage img']], back: function(html, pos){ var series = selCss('[name=series]', html).value; var chapter = selCss('[name=chapter]', html).value; var page = xpath('//select[@name="page"]/option[@selected]/preceding-sibling::option[1]/@value', html); return '?mode=view&series='+series+'&chapter='+chapter+'&page='+(page != '0' ? page : '1&prev'); }, next: function(html, pos){ var series = selCss('[name=series]', html).value; var chapter = selCss('[name=chapter]', html).value; try{ var page = xpath('//select[@name="page"]/option[@selected]/following-sibling::option[1]/@value', html); } catch(e){ var page = selCss('[name=page] [selected]', html).value + '&next'; } return '?mode=view&series='+series+'&chapter='+chapter+'&page='+page; }, extra: ['<form name="navigate">', [['.series_name']], [['.chapter_number']], [['.page']], '</form>'], js: function(dir){ if(!dir){ var form = selCss('form[name=navigate][method]'); form.parentNode.removeChild(form); } }, scrollx:'R' }, { url: 'read.mangashare.com', img: ['//div[@id="page"]//img'], back: [/value="prev" onclick="javascript:window.location='(.+?)';"/, 1], next: [/value="next" onclick="javascript:window.location='(.+?)';"/, 1], extra: [['//div[@class="controls"]//select', '']], xelem: '//div[@class="controls"]', scrollx:'R' }, { url: 'manga2u.me|demanga.com', img: ['//img[@class="manga-page"]'], back: [/wpm_nav_pvs\s*=\s*["'](.+?)['"];/, 1], next: [/wpm_nav_nxt\s*=\s*["'](.+?)['"];/, 1], scrollx:'R' }, { url: 'buttersafe.com', extra: [['//div[@class="post-comic"]']] }, { url: 'romanticallyapocalyptic.com', img: [['.comicmid img']], back: 'span[@class="spritePrevious"]', next: 'span[@class="spriteNext"]', first: 'span[@class="spriteStart"]' }, { url: 'somethingpositive.net', img: 'arch/|/arch/|sp', txtcol: '#888' }, { url: 'rhymes-with-witch.com', img: 'images/rww|images/lwr|images/rippy' }, { url: 'superstupor.com', img: 'sust|http://www.superstupor.com/sust', back: 'img[@src="last.gif"]', txtcol: '#888' }, { url: 'misfile.com', img: 'overlay.php?pageCalled' }, { url: 'digitalunrestcomic.com', img: 'strips/' }, { url: 'sluggy.com', img: '/images/comics/', back: '.="Prev."', next: '.="Next"', extra: [['//img[starts-with(@src, "/images/comics/")]', '', 1], ['//div[@class="comic_popup"]']] }, { url: 'asofterworld.com', img: 'clean/', bgcol: '#fff' }, { url: 'achewood.com', img: 'http://m.assetbar.com/achewood/' }, { url: 'act-i-vate.com', img: 'http://www.act-i-vate.com/uploads/005/' }, { url: 'biggercheese.com', img: 'comics/' }, { url: 'gwscomic.com', img: 'images/gws/', back: 'img[@src="images/gwsmenu/back_off.jpg"]' }, { url: 'fonflatter.de', img: ['//p/a/img[@title]'], next: '..[@id="next"]', back: '..[@id="prev"]' }, { url: 'ruthe.de', img: ['//div[@id="cartoon"]//img'], back: '@id="b_back"', next: '@id="b_next"' }, { url: 'daybydaycartoon.com', img: ['//div/p/img'] }, { url: 'dieselsweeties.com', img: '/hstrips/' }, { url: 'foxtrot.com', bgcol: '#fff' }, { url: 'csectioncomics.com', img: ['//div[@class="post-body entry-content"]/p//img'] }, { url: 'garfieldminusgarfield.net/post', img: ['//div[@class="photo"]//img'] }, { url: 'gocomics.com', img: function(html, pos){ try{ return selCss('div > .strip', html); } catch(e){ return selCss('.strip', html); } }, back: ['//ul[@class="feature-nav"]//a[@class="prev"]/@href'], next: ['//ul[@class="feature-nav"]//a[@class="next"]/@href'], last: [['.newest']], style: '.feature_item, .feature, #content {width: auto !important;} .zoom_link{display:none !important;}', layelem:'//p[@class="feature_item"]//img', fixurl: function(url, img, link){ if (img && url.indexOf('width=') > 0) { url = url.replace(/width=[^&]*/, ''); } return url; } }, { url: 'jeffzugale.com', extra: [['//div[@id="newsbox"]']], xelem: '//div[@id="newsbox"]' }, { url: 'threepanelsoul.com', extra: [['//nobr', '<br/>']], bgcol: '#fff' }, { url: 'oglaf.com', img: [['#strip']], back: 'div[@id="pv" or @id="pvs"]', next: 'div[@id="nx"]', extra: [['//div[@id="tt"]/img']], style: 'b>div{float:left;}', bgcol: '#ccc' }, { url: 'kevinandkell.com', back: '..[@id="prevstrip"]', next: '..[@id="nextstrip"]', extra: [['//div[@id="caption"]/span']] }, { url: 'kittyhawkcomic.com', img: ['//div[@id="comic"]/img'] }, { url: 'mycardboardlife.com', img: 'http://mycardboardlife.com/comics/', extra: [['//div[@class="entry"]']] }, { url: 'megatokyo.', back: [['.prev a']], next: [['.next a']], style: '#wcr_div{margin-bottom:50px;}#wcr_div *{float:none; text-align:center;}' }, { url: 'ex2.unixmanga.net', img: [/\'<IMG .*?SRC="(.+?)"/i, 1], back: function(html, pos){ if(html.indexOf('PREVIOUS PAGE') > 0) return match(html, /var prevlink = "(.+?)"/, 1); return match(html, /document\.write.+?href *= *"(.+?)".+PREVIOUS CHAPTER/, 1); }, next: [/var nextlink = "(.+?)"/, 1], scrollx:'R' }, { url: 'reader.imangascans.org', img: function(html, pos){ var page = parseInt(html.match(/else var page = parseInt\('(\d+)'\);/)[1]) - 1; var pages = JSON.parse(html.match(/var pages = (.+)(;|$)/m)[1]); return pages.pg_base + pages.pages[page]; }, back: function(html, pos){ var selpag = selCss('#page_select', html); var pars = selpag.getAttribute('onchange').match(/\('(.+)', '(.+)', .+\)/); if(selpag.selectedIndex){ return "http://reader.imangascans.org/" + pars[1] + "/" + pars[2] + "/" + selpag.options[selpag.selectedIndex - 1].value; } var selchap = selCss('[name="chapter"]', html); if(selchap.selectedIndex){ var chap = "http://reader.imangascans.org/" + pars[1] + "/" + selchap.options[selchap.selectedIndex - 1].value; var htmlPrev = syncRequest(chap, pos); return chap + "/" + xpath('//select[@id="page_select"]/option[last()]/@value', htmlPrev); } throw 'fail'; }, next: function(html, pos){ var selpag = selCss('#page_select', html); var pars = selpag.getAttribute('onchange').match(/\('(.+)', '(.+)', .+\)/); if(selpag.selectedIndex < selpag.options.length-1){ return "http://reader.imangascans.org/" + pars[1] + "/" + pars[2] + "/" + selpag.options[selpag.selectedIndex + 1].value; } var selchap = selCss('[name="chapter"]', html); if(selchap.selectedIndex < selchap.options.length-1){ return "http://reader.imangascans.org/" + pars[1] + "/" + selchap.options[selchap.selectedIndex + 1].value; } throw 'fail'; }, extra: [['//div[@class="pager"]']], xelem: '//div[@class="pager"]/..', layelem:'//div[@id="image_frame"]', scrollx:'R' }, { url: 'noreasoncomics.com', img: ['//div[@id="comic"]/img'], extra: [['//div[@id="column"]']], xelem: '//div[@id="column"]' }, { url: 'pixelcomic.net', img: ['//font/img'], extra: [['//font/font', '']] }, { url: 'redmeat.com', img: ['//div[@id="weeklyStrip"]/img'], extra: [['//div[@class="moreRedMeat"]', '', 1]] }, { url: 'sexylosers.com', back: '.="<<" and font[@color="#ffaaaa"]', next: '.=">>" and font[@color="#ffaaaa"]' }, { url: 'mangaeden.com|perveden.com', img: ['//img[@id="mainImg"]'], scrollx:'R' }, { url: 'pbfcomics.com', img: '/archive', back: 'img[contains(@src,"Older")]', next: 'img[contains(@src,"Newer")]', extra: [['//center/span/b[1]']] }, { url: 'tjandamal.com', img: 'http://tjandamal.com/comic/img/comic/', back: '.="<"', next: '.=">"' }, { url: 'sfeertheory.littlefoolery.com', img: 'art/' }, { url: 'wanderingones.com', img: ['//img[@alt="comic strip"]'], extra: [['//img[@alt="comic strip"]', '<br/>', 1]] }, { url: 'big-big-truck.com/ayiw/*.html', img: ['//img'], extra: [['//tr[2]//strong'], ['//td/p', '']] }, { url: 'wastedtalent.ca', img: 'http://www.wastedtalent.ca/sites/default/files/imagecache/comic_full/comics/' }, { url: 'wulffmorgenthaler.com', img: 'striphandler.ashx?stripid=' }, { url: 'weregeek.com', img: ['//div[@id="comic"]/img'] }, { url: '*.katbox.net', img: [['.webcomic-image img']] }, { url: 'gipcomic.com', img: '/pages/', back: 'img[@alt="prev"]', next: 'img[@alt="next"]', scrollx:'R' }, { url: 'theoswaldchronicles.com', img: 'http://www.theoswaldchronicles.com/wp-content/webcomic/', back: '@rel="previous"', next: '@rel="next"' }, { url: 'awkwardzombie.com', img: ['//div[@id="comic"]/img'], back: 'img[@alt="Previous Comic"]', next: 'img[@alt="Next Comic"]', extra: [['//div[@id="comic"]/img', '<br/>', 1], ['//div[@id="blarg"]']] }, { url: 'stainedglasssamurai.com', img: ['//div[@id="mainContent"]//img'] }, { url: '*.seraph-inn.com', img: 'pages/' }, { url: 'fakku.net', img: function(html, pos){ var thumbs = JSON.parse(match(html, /params\.thumbs\s*=\s*(.+);/, 1)); var x = link[0].match(/page=(\d+)/); x = Number(x ? x[1] : 0)+pos; if(!x) return '.'; if(x<0 || x>thumbs.length) throw 'fail'; x = x.toString(); while(x.length<3) x='0'+x; return html.match(/'([^']+\/images\/manga\/[^']+)'/)[1] + x + '.jpg'; }, back: function(html, pos){ var thumbs = JSON.parse(match(html, /params\.thumbs\s*=\s*(.+);/, 1)); var x = link[0].match(/page=(\d+)/); x = Number(x ? x[1] : 0)+pos-1; if(x<0 || x>thumbs.length) throw 'fail'; return link[0].replace(/#.+/, '')+'##page='+x; }, next: function(html, pos){ var thumbs = JSON.parse(match(html, /params\.thumbs\s*=\s*(.+);/, 1)); var x = link[0].match(/page=(\d+)/); x = Number(x ? x[1] : 0)+pos+1; if(x<0 || x>thumbs.length) throw 'fail'; return link[0].replace(/#.+/, '')+'##page='+x; }, js: function(dir){ if(!dir){ exec( "$(function(){"+ //cambio los links de los thumbs "$('[href^=\"#page\"]').each(function(){"+ "$(this).attr('href', document.location.href.replace(/#.+/, '')+'&'+$(this).attr('href'));"+ "});"+ //arreglo el select "$('.drop').change(function(){"+ "window.location.href = document.location.href.replace(/#.+/, '')+"+ "($(this).val() != '0' ? '&#page=' + $(this).val() : '');"+ "});"+ //saco el interval q molesta con el update_page "for(var i=setInterval(' ', 23232323); i; i--) clearInterval(i);"+ "});" ); } var x = link[0].match(/page=(\d+)/); x = Number(x ? x[1] : 0)+posActual; get('thumbs').style.display = x ? 'none' : ''; }, style: 'header{position:absolute;}', scrollx:'R', layelem:'//div[@id="image"]' }, { url: 'soulless-comic.com', img: 'http://www.soulless-comic.com?comic_object' }, { url: 'earthsongsaga.com', img: '../images/vol', back: function(html, pos){ try{ return selCss('#previous a', html); } catch(e){ return xpath('//table[2]//td[2]//a/@href', html); } }, next: function(html, pos){ try{ return selCss('#next a', html); } catch(e){ return xpath('//table[2]//td[3]//a/@href', html); } }, extra: [function(html, pos){ return '<img src="'+xpath('//a[starts-with(@href, "../images/vol")]/@href', html)+'"/>'; }], style: '#wcr_div{background:#d1be8b;}' }, { url: 'goblinscomic.com', style: '#comic{overflow:visible;}' //ugly but works... }, { url: 'precociouscomic.com', back: '.="Previous"', next: '.="Next"' }, { url: '*.spiderforest.com', img: ['//img[contains(@src, "comics/")]'] }, { url: 'sevensmith.net/chirault', img: 'images/' }, { url: 'junglestudio.com/roza', img: 'pages/', back: 'img[contains(@src, "navtable_09.gif")]', next: 'img[contains(@src, "navtable_11.gif")]' }, { url: 'dream-scar.net', img: 'files/' }, { url: 'tryinghuman.com', back: 'img[@alt="Previous comic"]', next: 'img[@alt="Next comic"]' }, { url: 'thedreamercomic.com', img: 'issues/' }, { url: 'sandraandwoo.com', img: ['//div[@id="comic"]/img'] }, { url: 'freakangels.com', img: 'http://www.freakangels.com/comics/', back: function(html, pos){ var page = link[pos].match(/page=(\d+)/); if(page) page = page[1]; if(!page || page==1) return xpath('//li[@class="left"]/a/@href', html); return link[pos].replace(/page=\d+/, 'page='+(page-1)); }, next: function(html, pos){ var page = link[pos].match(/page=(\d+)/); page = page ? Number(page[1]) : 1; try{ return xpath('//a[contains(@href, "page='+(page+1)+'")]/@href', html); } catch(e){ return xpath('//li[@class="right"]/a/@href', html); } } }, { url: 'comics.com', img: ['//a[@class="STR_StripImage"]/img'], back: [/Link_Previous: '(.+?)'/, 1], next: [/Link_Next: '(.+?)'/, 1] }, { url: 'sakanacomic.com', img: '/img/com/', style: '#comic-outer{height:auto;}' }, { url: 'jaygeefisher.com', img: 'Strips/', extra: [['//img[starts-with(@src, "Strips/")]', '<br/>', 1]], style: '#wcr_div div{position:relative;}' }, { url: 'doujin-moe.us', img: ['//img[@class="picture"]'], fixurl: function(url, img, link){ if(link && document.location.href.indexOf('&non_lr=1')>0) return url.replace('#top', '&non_lr=1'); return url; } }, { url: 'keychain.patternspider.net', next: 'img[@alt="forward"]', extra: [['//div[@class="style3"]']] }, { url: 'collectedcurios.com/sequentialart.php', img: ['//img[@id="strip"]'], back: 'img[@title="Back one"]', next: 'img[@title="Forward one"]' }, { url: 'doomies.com', img: ['//table[contains(@background, "/gotico.gif")]//img'] }, { url: 'waywardsons.keenspot.com', img: [['img[src*="/comics"]']], back: 'img[@id="p_bot_nav"]', next: 'img[@id="n_bot_nav"]' }, { url: 'marryme.keenspot.com|lastblood.keenspot.com', img: ['//div[@id="comic"]/img'], back: '(preceding-sibling::small | preceding-sibling::*/small)[.="Previous Comic:"]', next: '(preceding-sibling::small | preceding-sibling::*/small)[.="Next Comic:"]', fixurl: function(url, img, link){ if(img) return url.replace(/http:\/\/.+?\//, 'http://'+document.location.host+'/'); return url; } }, { url: 'exposure.keenspot.com', img: [['img[src*="/comics"]']], back: 'img[@id="exp46"]', next: 'img[@id="exp48"]' }, { url: 'yirmumah.keenspot.com', img: [['img[src*="/comics"]']], back: '.="Previous"', next: '.="Next"' }, { url: 'twokinds.keenspot.com', img: [['#cg_img img']], back: '@id="cg_back"', next: '@id="cg_next"' }, { url: 'roadwaffles.keenspot.com', img: 'comics/', back: '.="previous"', next: '.="next"' }, { url: 'plusev.keenspot.com', img: [['img[src*="/comics"]']], back: 'img[@id="Previous_Day"]', next: 'img[@id="Next"]' }, { url: '*.keenspot.com', img: [['img[src*="/comics"]']], back: '(img/@alt | .)="Previous comic"', next: '(img/@alt | .)="Next comic"' }, { url: 'qgmindpolice.com', extra: [['//div[@class="post"]']] }, { url: 'slowwave.com', img: ['//img[@alt="slow wave"]'] }, { url: 'sylvanmigdal.com', img: '/c/', back: 'img[starts-with(@alt,"Antecedent")]', next: 'img[starts-with(@alt,"Subsequent")]' }, { url: '*.c.urvy.org', img: '/c/', back: 'img[@alt="Previous page"]', next: 'img[@alt="Next page"]' }, { url: 'the-artiste.net', img: '/img/com/', extra: [['//div[@id="commentary"]']], js: function(dir){ get('commentary').style.display = ''; } }, { url: 'survivingtheworld.net', img: 'Lesson|Recitation|GuestLecture', back: [['.previous a']], next: [['.next a']], extra: [[['.comiccontainer > p[align="justify"]', '']]] }, { url: 'view.thespectrum.net|animephile.com', img: [['#mainimage']], back: function(html, pos){ var page, ch; try{ //pag ant, mismo cap page = xpath('//select[@name="page"]/option[@selected="selected"]/preceding-sibling::option[1]/@value', html); ch = xpath('//select[@name="ch"]/option[@selected="selected"]/@value', html); } catch(e){ //cap ant, ultima pag page = xpath('//input[@id="lastpage"]/@value', html); ch = xpath('//select[@name="ch"]/option[@selected="selected"]/preceding-sibling::option[1]/@value', html); } return '?ch='+ch+'&page='+page; }, next: function(html, pos){ var page, ch; try{ //pag sgte, mismo cap page = xpath('//select[@name="page"]/option[@selected="selected"]/following-sibling::option[1]/@value', html); ch = xpath('//select[@name="ch"]/option[@selected="selected"]/@value', html); } catch(e){ //cap sgte, primera pag page = 1; ch = xpath('//select[@name="ch"]/option[@selected="selected"]/following-sibling::option[1]/@value', html); } return '?ch='+ch+'&page='+page; }, extra: [['//form']], js: function(dir){ if(!dir) exec("right_one = left_one = function(){};"); var sels = xpath('//select', document, true); for(var i=0; i<sels.length; i++) setEvt(sels[i], 'change', function(evt){ var frm = evt.target.parentNode.parentNode; if(evt.target.name=='ch') frm.childNodes[11].childNodes[1].value = '1'; frm.submit(); }); }, scrollx:'R', style: '.imgContainer img {max-width:none;}' }, { url: 'mangavolume.com', extra: [[['#chapters']], [['#pages']]], js: function(dir){ if(!dir) exec("back = next = '';"); }, scrollx:'R' }, { url: 'nonadventures.com', extra: [['//div[@class="post"]']] }, { url: 'beardfluff.com', img: 'http://beardfluff.com/wp-content/webcomic/' }, { url: 'lawlscomic.com', img: 'http://lawlscomic.com/comics/', back: '@class="navi navi-prev"', next: '@class="navi navi-next"' }, { url: 'maakies.com', img: ['//a[@rel="attachment"]/img'], back: '..[@class="nav-previous"]', next: '..[@class="nav-next"]' }, { url: 'lefthandedtoons.com', img: 'http://www.lefthandedtoons.com/toons/' }, { url: 'trollscience.com', img: '/image/', extra: [['//h2'], ['//div[@id="troll-rate"]'], ['//div[@id="troll-comments"]']] }, { url: 'giantitp.com', back: 'img[@alt="Previous Comic"]', next: 'img[@alt="Next Comic"]' }, { url: 'submanga.com', img: [['div > a > img']], back: 'img[@src="./s/hdl.gif"]', next: 'img[@src="./s/hdr.gif"]', extra: [['//select']], style: '#t{position:relative !important;} #wcr_div div{margin:0;}', scrollx:'R', onerr: function(url, img, num){ if(num >= 2) return null; var n = parseInt(img.match(/\/\/img(\d)/)[1]); n = ((n - 1) % 3) + 2; //2>3>4>2 return {img: img.replace(/\/\/img\d/, '//img'+n) }; } }, { url: 'g.e-hentai.org|exhentai.org', img: [['#i3 a img, iframe + a img, .smi > a img']], back: function(html, pos){ var num = Number(link[pos].match(/-(\d+)(\?.+)?$/)[1]); var as = xpath('//a[img]', html, true); for(var i=0; i<as.length; i++) if(as[i].href.match(new RegExp('-'+(num-1)+'(\\?|$)'))) return as[i].href; throw 'fail'; }, next: function(html, pos){ var num = Number(link[pos].match(/-(\d+)(\?.+)?$/)[1]); var as = xpath('//a[img]', html, true); for(var i=0; i<as.length; i++) if(as[i].href.match(new RegExp('-'+(num+1)+'(\\?|$)'))) return as[i].href; throw 'fail'; }, extra: [['//div[span]'], '<span style="display:none">', ['//a[@onclick[contains(., "nl")]]'], '</span>'], scrollx:'R', onerr: function(url, img, num, pos){ if(num >= 4) return null; var nl = extra[pos].innerHTML.match(/nl\((\d+)\)/)[1]; var u = url.split('?nl='); if(u[1] == nl) return null; return {url: u[1] + '?nl=' + nl }; } }, { url: 'animesquish.com', back: function(html, pos){ try{ return xpath('//a[.="Previous"]/@href', html); } catch(e){ return xpath('//a[@rel="prev"]/@href', html); } }, next: function(html, pos){ try{ return xpath('//a[.="Next"]/@href', html); } catch(e){ return xpath('//a[@rel="next"]/@href', html); } }, extra: [['//a[@rel="bookmark"]/text()'], ['//select[@class="contentjumpddl"]']] }, { url: 'crazytje.be', img: 'http://img.crazytje.be/reader/', back: '.="<< Back"', next: '.="Next >>"', js: function(dir){ if(!dir) exec("goToPreviousPage = goToNextPage = '';"); }, extra: [[['#chapter']], [['#pages']]], scrollx:'R' }, { url: 'tenmangas.com|tenmanga.com|*.wiemanga.com', img: [['#comicpic']], back: [/pre_page = "(.+?)"/, 1], next: [/next_page = "(.+?)"/, 1], js: function(dir){ if(!dir) exec("document.onkeyup = '';"); }, extra: [[['#chapter']], [['#page']]], scrollx:'R' }, { url: 'ekkifu.com', img: 'http://img', back: [/value="previous page" onclick="javascript:window.location='(.+)';"/i, 1], next: [/value="next page" onclick="javascript:window.location='(.+)';"/i, 1], extra: [[['.chapter-navigation select', ' Page ']]], scrollx:'R' }, { url: 'bittersweetcandybowl.com', img: [['#page_img']], back: '@rel="prev"', next: '@rel="next"', extra: [[['#authorcommentary']], [['#comicselect']]], style: '.pagenavlink{display:none;} #content #wcr_div *{text-align:center;}' }, { url: 'imagebam.com', img: ['//img[@alt="loading"]'] }, { url: 'otakuworks.com', img: [['#filelist>a>img']], back: function(html, pos){ if(contenido(html, [/fmanga_hasprev = (\d+)/, 1]) == '1'){ var prev = contenido(html, [/fmanga_prev = (\d+)/, 1]); return contenido(html, [/fmanga_link = "(.+?)"/, 1]).replace('{1}', prev); } return contenido(html, [/if\(fmanga_hasprev\).+\n.+'(.+?)'/, 1]); }, next: function(html, pos){ if(contenido(html, [/fmanga_hasnext = (\d+)/, 1]) == '1'){ var next = contenido(html, [/fmanga_next = (\d+)/, 1]); return contenido(html, [/fmanga_link = "(.+?)"/, 1]).replace('{1}', next); } return contenido(html, [/if\(fmanga_hasnext\).+\n.+'(.+?)'/, 1]); }, scrollx:'R' }, { url: 'basicinstructions.net', img: [['.full-image-block img']], back: '@class="journal-entry-navigation-next"', next: '@class="journal-entry-navigation-prev"' }, { url: 'insaneyetisquirrel.com', img: [['.comic_content img']], extra: [[['.comictitle']], '<br/>'] }, { url: '*.kukudm.*|*.socomic.*', img: function(html, pos){ if(!pos) return selCss('td>img'); var src = match(imagen[0], /https?:\/\/[^\/]+\//, 0) + match(html, /write\(.+? src *= *'"\+[^+]+\+"(.+?)'/i, 1); return src; }, back: 'img[@src="/images/t.gif"]', next: 'img[@src="/images/d.gif"]', scrollx:'R' }, { url: 'webcomicsnation.com', img: ['//tr[2]/td/div[2]/a/img'], back: '.="Previous"', next: '.="Next"', extra: [['//tr[2]/td/div/a/img', '<br/>', 2]] }, { url: 'missmab.com', img: ['//center/img | //p/img'], extra: [['//i']] }, { url: 'darthsanddroids.net', extra: [[['.center b']], [['.text']]], style: '.text{text-align:left;}' }, { url: 'harkavagrant.com', img: [['.rss-content img']], extra: [[['.black11']]] }, { url: 'walkinginsquares.com', extra: [[['#enlight']]] }, { url: 'dresdencodak.com', img: 'http://dresdencodak.com/comics/', back: 'img[@src="http://dresdencodak.com/m_prev.png"]', next: 'img[@src="http://dresdencodak.com/m_next.png"]', extra: [[['.post>h2']], [['.post p', '', 0, -1]]] }, { url: 'straysonline.com', img: [['td[align="center"]>a>img']] }, { url: /emi-art\.com\/twtyh\/(index\.html)?$/, img: [['font[color="#000000"]>img']] }, { url: 'emi-art.com', img: [['center>img']] }, { url: 'dragonball-multiverse.com', img: [['#balloonsimg>img']], layout: false }, { url: 'wayfarersmoon.com', img: '/admin/uploads/wm', back: 'img[@alt="back button"]', next: 'img[@alt="forward button"]', first: 'img[@alt="begin button"]', last: 'img[@alt="end button"]' }, { url: '*.smackjeeves.com', img: [['#comic_image']] }, { url: '10kcommotion.com', img: function(html, pos){ var num = Number(link[0].match(/\?(\d+)$/)[1])+pos; return match(html, new RegExp('image\\['+num+'\\]="(.+?)"'), 1); }, back: function(html, pos){ var url = link[0].match(/^(.+\?)(\d+)$/); var num = Number(url[2])+pos-1; return num ? url[1]+num : null; }, next: function(html, pos){ var url = link[0].match(/^(.+\?)(\d+)$/); var num = Number(url[2])+pos+1; return match(html, new RegExp('image\\['+num+'\\]="(.+?)"'), 1) ? url[1]+num : null; } }, { url: 'somemangas.com', img: function(html, pos){ if(!pos) selCss('option[value="traditional"][selected]', html); return selCss('center img', html); }, back: [/var prevpagelink = '(.+?)'/, 1], next: [/var nextpagelink = '(.+?)'/, 1], scrollx:'R' }, { url: 'multiplexcomic.com', back: '.="Previous"', next: '.="Next"' }, { url: 'johnandjohn.nl', img: '../write/', back: '@id="pointleft"', next: '@id="pointright"', extra: [function(html, pos){ var link = xpath('//a[img[@id="comicimg"]]/@href', html); return '<a href="'+link+'">'+link+'</a>'; }], txtcol: 'orange', layout: false }, { url: 'sorcery101.net', img: [['.comic img']] }, { url: 'treadingground.com', extra: [[['.entry']]] }, { url: 'jerkcity.com', img: [['.aidsy']], extra: [[['.slurping']]], style: '#wcr_div a{color:#000;}', js: function(dir){ if(!dir) document.onkeyup = ''; } }, { url: 'kiwiblitz.com|thepunchlineismachismo.com|zombieboycomics.com', img: [['#comic-1 img']], extra: [[['.entry']]], style: '#wcr_div button{float:none;}' }, { url: 'kafkaskoffee.com', img: [['.webcomic-object img']], extra: [[['.webcomic_post h1']], [['.content']]] }, { url: 'out-at-home.com', extra: [[['.comic']]], txtcol: '#fff' }, { url: 'occasionalcomics.com|bearandtiger.com', extra: [[['.entry']]] }, { url: 'babyblues.com', img: [['.comic img']] }, { url: 'mangatopia.net', img: 'manga/', back: ['//input[@id="left"]/@value'], next: ['//input[@id="right"]/@value'], extra: [[['.page_selector']]], scrollx:'R' }, { url: 'mankin-trad.net', img: 'read/', js: function(dir){ if(!dir){ var hn = get('hoverNav'); hn.parentNode.removeChild(hn); } }, extra: [[['.pagination']]], scrollx:'R' }, { url: '*.mangahere.co', img: [['#image']], back: function(html, pos){ var a = selCss('.prew_page', html); if(a.href.indexOf('javascript:')) return a; return xpath('//strong[.="Previous Chapter:" or .="Capítulo Anterior:"]/following-sibling::a/@href', html) + "last.html"; }, next: function(html, pos){ try{ return xpath('//select[@class="wid60"]/option[@selected]/following-sibling::option[1]/@value', html); } catch(e){ return xpath('//p[contains(., "es el siguiente...")]/a | //strong[.="Next Chapter:"]/following-sibling::a', html); } }, js: function(dir){ if(!dir) exec("previous_page = next_page = '';"); var selcap = selCss('#wcr_extra #top_chapter_list'); var caps = selcap.options; for(var i=0; i<caps.length; i++){ if(link[posActual].indexOf(caps[i].value) >= 0){ selcap.selectedIndex = i; break; } } }, extra: [function(html, pos){ return selCss('#top_chapter_list', pos ? document : html); }, [['.wid60']]], scrollx:'R' }, { url: 'spaceavalanche.com', img: [['.entry img']] }, { url: 'schlockmercenary.com', img: [['#comic img']], back: '.="Previous Comic"', next: '.="Next Comic"', extra: [[['#comic img', '', 1]], [['div.footnote']]], style: '#wcr_extra{width:780px; margin:0 auto;}' }, { url: 'warehousecomic.com', extra: [[['.newsBox p', '']]] }, { url: 'nerfnow.com', extra: [[['.comment']]] }, { url: 'zapcomic.com', img: 'http://www.zapcomic.com?comic_object=' }, { url: 'shortpacked.com', img: 'http://www.shortpacked.com/comics/' }, { url: 'axecop.com', img: [['#comic img']], back: '.="Prev"', next: '.="Next"', extra: [[['.entry-content']]], txtcol: '#fff' }, { url: 'somethingofthatilk.com', img: '/comics/', back: '@class="prev"', next: '@class="next"', extra: [[['#captioning']]] }, { url: 'reddit.com', img: function(html, pos){ var posts = selCss('#siteTable>.thing:not(.promoted)', html, true); var post = posts[((pos%25)+25)%25]; var tit = selCss('a.title', post).href; if(tit.match(/\.(jpg|png|gif)(\?.+)?$/i)) return tit; else if(tit.match(/http:\/\/imgur\.com\/\w+$/i)) return 'http://i.imgur.com/'+tit.match(/http:\/\/imgur\.com\/(\w+)$/i)[1]+'.jpg'; else if(tit.match(/http:\/\/www\.quickmeme\.com\/meme\/\w+\/?$/i)) return 'http://i.qkme.me/'+tit.match(/http:\/\/www\.quickmeme\.com\/meme\/(\w+)/i)[1]+'.jpg'; else if(tit.match(/http:\/\/qkme\.me\//i)) return 'http://c0016417.cdn2.cloudfiles.rackspacecloud.com/'+tit.match(/http:\/\/qkme\.me\/(\w+)/i)[1]+'.jpg'; try{ return selCss('a.thumbnail img', post); } catch(e){} try{ return selCss('img#header-img', html); } catch(e){ return '/favicon.ico'; } }, back: function(html, pos){ if(pos%25) return '##'+(pos-1); return selCss('a[rel~="prev"]', html); }, next: function(html, pos){ if((pos+1)%25) return '##'+(pos+1); return selCss('a[rel~="next"]', html); }, extra: [function(html, pos){ var posts = selCss('#siteTable>.thing:not(.promoted)', html, true); return posts[((pos%25)+25)%25]; }], js: function(dir){ exec("expando_child($('.expando-button'))"); }, layelem:'//body/div[contains(@class,"content")]' }, { url: 'blankitcomics.com', img: 'http://blankitcomics.com/bicomics/' }, { url: 'anime-source.com', img: 'http://www.anime-source.com/html/images/', scrollx:'R' }, { url: 'mangarush.com', img: 'http://www.mangarush.com/files/mangas/', back: function(html, pos){ var path = match(html, /var path = '(.+)';/, 1); var manga = match(html, /var thisManga = '(.+)';/, 1); var chapter = match(html, /var thisChapter = '(.+)';/, 1); var page = Number(match(html, /var thisPage = (.+);/, 1)); if(page > 1) return path + "manga/" + escape(manga) + "/" + escape(chapter) + "/p-" + (page-1); var prevChap = xpath('//select[@id="chapters_list"]/option[@selected]/preceding-sibling::option[1]/@value', html); return path + "manga/" + escape(manga) + "/" + escape(prevChap) + "/p-1"; }, next: function(html, pos){ var path = match(html, /var path = '(.+)';/, 1); var manga = match(html, /var thisManga = '(.+)';/, 1); var chapter = match(html, /var thisChapter = '(.+)';/, 1); var page = Number(match(html, /var thisPage = (.+);/, 1)); var pages = Number(match(html, /var pages = (.+);/, 1)); var nextChapter = match(html, /var nextChapter = '(.*)';/, 1); if(page < pages) return path + "manga/" + escape(manga) + "/" + escape(chapter) + "/p-" + (page+1); if(nextChapter != "") return path + "manga/" + escape(manga) + "/" + escape(nextChapter) + "/p-1"; throw 'fin'; }, extra: [[['.mangareader select', '']]], scrollx:'R' }, { url: 'citymanga.com', img: '/files/images/', back: [/id="previousbutton" onclick="javascript:window.location='(.+?)';"/, 1], next: [/id="nextbutton" onclick="javascript:window.location='(.+?)';"/, 1], extra: [[['#chapterselector']], [['#pageselector']]], scrollx:'R' }, { url: 'dctp.ws|dctpws.thetrogdor.com', img: [['center>img']], back: 'img[@src="leftarrow.GIF"]', next: 'img[@src="rightarrow.GIF"]', scrollx:'R' }, { url: 'luscious.net', img: [['#single_picture']], fixurl: function(url, img, link){ if(img) return url.replace(/(\.\d+x\d+)(\.\w+$)/, '$2'); return url; }, style: '#wcr_div button{display:inline;}', scrollx:'R' }, { url: 'old.lu.scio.us', img: 'http://static.lu.scio.us/hentai/', fixurl: function(url, img, link){ if(img) return url.replace('normal__', ''); return url; }, scrollx:'R' }, { url: 'geekculture.com', img: [['p > img']] }, { url: 'geeklifecomic.com', extra: [[['.entry']]] }, { url: 'thedoujin.com', img: 'http://img', back: [/<a href="#" onclick="document.location='([^']+?)'; return false;">Previous/, 1], next: [/<a href="#" onclick="document.location='([^']+?)'; return false;">Next/, 1], scrollx:'R' }, { url: 'eatmanga.com', img: [['#eatmanga_image, #eatmanga_image_big, #bigimage, .eatmanga_bigimage']], back: function(html, pos){ try{ return selCss('#page_previous:not([onclick])', html); } catch(e){ return xpath('//select[@id="bottom_chapter_list"]/option[contains("'+link[pos]+'", @value)]/following-sibling::option[1]/@value', pos ? '<div>'+extra[0]+'</div>' : document); } }, next: function(html, pos){ try{ return selCss('#page_next:not([onclick])', html); } catch(e){ return xpath('//select[@id="bottom_chapter_list"]/option[contains("'+link[pos]+'", @value)]/preceding-sibling::option[1]/@value', pos ? '<div>'+extra[0]+'</div>' : document); } }, extra: [[['.navigation select', ' ', 2]]], js: function(dir){ var selchap = selCss('#wcr_extra #bottom_chapter_list'); if(dir) selchap.innerHTML = selCss('#bottom_chapter_list', '<div>'+extra[0]+'</div>').innerHTML; selchap.value = xpath('//select[@id="bottom_chapter_list"]/option[contains("'+link[posActual]+'", @value)]/@value', selchap); }, scrollx:'R' }, { url: 'oslevadosdabreca.com', img: 'http://www.oslevadosdabreca.com/tiras/', first: [['.nav-first a']], last: [['.nav-last a']] }, { url: 'faans.com', back: '@rel="prev"', next: '@rel="next"' }, { url: 'cheercomic.com', img: 'comics/', back: 'img[@id="navimg3"]', next: 'img[@id="navimg4"]' }, { url: 'drunkduck.com', img: [['#comic img']], back: 'img[@class="arrow_prev"]', next: 'img[@class="arrow_next"]', first: 'img[@class="arrow_first"]', last: 'img[@class="arrow_last"]', extra: [[['#author_note_holder']]], style: '#wcr_extra #author_note_holder{float:none;text-align:left;min-height:0;} #wcr_extra .thumbnailleft img{width:60px;} #wcr_extra .postcontent{width:auto;}' }, { url: 'ephralon.de', img: '/seekers/' }, { url: 'sgvy.com', img: [['#comic']] }, { url: 'truefork.org', extra: [[['.plaintext']]] }, { url: /anelnoath\.com\/\w+\d+\.htm/, img: [['img']] }, { url: 'nsfw-comix.com', img: 'comix/', extra: [[['img[src^="comix/"]', '<br/>', 1]]] }, { url: 'thewotch.com', img: 'comics/', back: 'img[contains(@src,"nav_prevpage")]', next: 'img[contains(@src,"nav_nextpage")]', extra: [[['.comments']]] }, { url: 'thedevilbear.com', img: 'comixx/' }, { url: 'terinu.com', img: function(html, pos){ if(!pos) return selCss('#Image1'); var cappag = imagen[0].match(/Comic(\d+)Pg(\d+)/); var nombre = 'Chapter '+parseInt(cappag[1])+' Page '+parseInt(cappag[2]); var op = xpath('//option[.="'+nombre+'"]/'+ (pos>0?'following':'preceding')+'-sibling::option['+Math.abs(pos)+']'); var cappagimg = op.textContent.match(/Chapter (\d+) Page (\d+)/); var cap = cappagimg[1]; while(cap.length<2) cap='0'+cap; var pag = cappagimg[2]; while(pag.length<3) pag='0'+pag; return '/Comic/Comic'+cap+'Pg'+pag+'.jpg'; }, back: function(html, pos){ return '##'+(pos-1); }, next: function(html, pos){ return '##'+(pos+1); } }, { url: 'las-historietas.blogspot.com', img: ['//div[contains(@class, "post-body")]//a[img and (contains(@href, ".png") or contains(@href, ".jpg") or contains(@href, ".gif"))]/@href'], back: '@id="blog-pager-older-link"', next: '@id="blog-pager-newer-link"', extra: [function(html, pos){ var div = selCss('.post-body', html); var aimgs = selCss('[href$=".png"]>img,[href$=".jpg"]>img,[href$=".gif"]>img,[href$=".PNG"]>img,[href$=".JPG"]>img,[href$=".GIF"]>img', div, true); aimgs[0].parentNode.removeChild(aimgs[0]); for(var i=1; i<aimgs.length; i++){ var img = aimgs[i]; var href = img.parentNode.href; if(img.src != href){ img.src = href; img.removeAttribute('width'); img.removeAttribute('height'); } } return div; }], layelem:'//div[contains(@class, "post-body")]', style: '.content-outer{max-width:none !important;}' }, { url: 'dcisgoingtohell.com', back: '@class="navi navi-prev"', next: '@class="navi navi-next"' }, { url: 'palcomix.com|palcomix.org', img: '../images/', extra: [[['form']]] }, { url: 'soulsymphonycomic.com', img: [['#comic>img']] }, { url: 'whiteninjacomics.com', img: [['[valign="top"]>[src^="/images/comics/"]']], back: 'img[@src="/images/previous.jpg"]', next: 'img[@src="/images/next.jpg"]', extra: [[['[valign="bottom"]>[src^="/images/comics/"]']]] }, { url: 'apenotmonkey.com', back: '@rel="prev"', next: '@rel="next"' }, { url: 'malandchad.com', back: '@rel="prev"', next: '@rel="next"' }, { url: 'goodmanga.net', img: [['#manga_viewer img']], back: [['a.previous_page']], next: [['a.next_page']], extra: [[['#asset_1 select.chapter_select']], '<span>Page ', [['#asset_2 select.page_select']], ' ', ['//select[@class="page_select"]/following-sibling::span'], '</span>'], xelem: '//div[@id="manga_nav_top"]', style: '#manga_nav_bottom{display:none}', scrollx:'R' }, { url: 'digitalcomicmuseum.com/preview', img: 'cache/' }, { url: 'goldenagecomics.co.uk', img: function(html, pos){ return get('img_'+pos).href; }, back: function(html, pos){ if(!pos) throw 'fail'; return '##'+(pos-1); }, next: function(html, pos){ if(!get('img_'+(pos+1))) throw 'fail'; return '##'+(pos+1); }, layelem:'//div' }, { url: 'fourcolorshadows.blogspot.com|thehorrorsofitall.blogspot.com', img: function(html, pos){ var aimgs = xpath('//div[contains(@class,"blog-posts")]//div/a[img[not(@class="icon-action")]]', html, true); var num = pos ? Number(link[pos].match(/##(\d+);/)[1]) : 0; return aimgs[pos-num].href; }, back: function(html, pos){ throw 'fail'; }, next: function(html, pos){ if(!pos) return '##0;1'; var aimgs = xpath('//div[contains(@class,"blog-posts")]//div/a[img[not(@class="icon-action")]]', html, true); var num = Number(link[pos].match(/##(\d+);/)[1]); if(num+aimgs.length > pos+1) return '##' + num + ';' + (pos+1); return selCss('#Blog1_blog-pager-older-link', html).href + '##' + (num+aimgs.length) + ';' + (pos+1); }, extra: [function(html, pos){ var post = xpath('//div[contains(@class,"post-body") and .//a[@href="'+imagen[pos]+'"]]', html); return outerHTML(selCss('h3', post.parentNode)) + '<br/>' + post.textContent + outerHTML(selCss('.post-footer', post.parentNode)); }], layelem:'//div[@id="header-wrapper"]' }, { url: 'bato.to', img: [['#comic_page']], back: function(html, pos){ try{ return xpath('//a[img[@title="Previous Page"]]', html); } catch(e){ return xpath('//a[img[@title="Previous Chapter"]]', html); } }, next: function(html, pos){ try{ return xpath('//a[img[@title="Next Page"]]', html); } catch(e){ return xpath('//a[img[@title="Next Chapter"]]', html); } }, extra: [['//img[@id="comic_page" and not(./ancestor::div[contains(@style, "display: none;")])]', '<br/>', 1], [['.moderation_bar']]], fixurl: function(url, img, link){ if(img) return encodeURI(url); return url; }, layelem:'//img[@id="comic_page"]', scrollx:'R' }, { url: 'nedroid.com', extra: ['<br/>', [['.post-comic h2']]] }, { url: 'lovemenicecomic.com', img: 'http://www.lovemenicecomic.com/wp-content/webcomic/', back: '@rel="previous"', next: '@rel="next"' }, { url: 'manga-access.com', img: [['#pic img']], back: function(html, pos){ try{ return xpath('//select[@id="page_switch"]/option[@selected]/preceding-sibling::option[1]/@value', html); } catch(e){ var chap = xpath('//select[@id="chapter_switch"]/option[@selected]/following-sibling::option[1]', html); return chap.value + '/' + chap.getAttribute('pages'); } }, next: function(html, pos){ try{ return xpath('//select[@id="page_switch"]/option[@selected]/following-sibling::option[1]/@value', html); } catch(e){ return xpath('//select[@id="chapter_switch"]/option[@selected]/preceding-sibling::option[1]/@value', html); } }, js: function(dir){ if(!dir) exec("$('#pic img').unbind(); $(document).unbind();"); setEvt(selCss('#wcr_div #chapter_switch, #wcr_div #page_switch', document, true), 'change', function(evt){ redirect(evt.target.value); }); }, extra: ['Chapter ', [['#chapter_switch']], ' / Page ', [['#page_switch']]], bgcol: '#fff', scrollx:'R' }, { url: 'ju-ni.net', img: function(html, pos){ return xpath('//a[.=" +High res+ "]/@href', html).replace('?display=', '?displaypic='); }, back: '.="<- Previous"', next: '.="Next ->"', extra: [['//div[@id="picnav"]/text()', '']], layelem:'//img[@class="picture"]', scrollx:'R' }, { url: 'scarygoround.com', img: 'strips', back: '.="Previous"', next: '.="Next"' }, { url: 'mangastream.to', back: function(html, pos){ var manga = html.match(/n_topic = "(.+?)";/)[1]; try{ var pag = xpath('//select[@id="id_page"]/option[@selected]/preceding-sibling::option[1]/@value', html); var chap = xpath('//select[@id="id_chapter"]/option[@selected]/@value', html); return "/" + manga + "-chapter-" + chap + "-page-" + pag + ".html"; } catch(e){ chap = xpath('//select[@id="id_chapter"]/option[@selected]/preceding-sibling::option[1]/@value', html); return "/" + manga + "-chapter-" + chap + ".html"; } }, next: function(html, pos){ var manga = html.match(/n_topic = "(.+?)";/)[1]; try{ var pag = xpath('//select[@id="id_page"]/option[@selected]/following-sibling::option[1]/@value', html); var chap = xpath('//select[@id="id_chapter"]/option[@selected]/@value', html); return "/" + manga + "-chapter-" + chap + "-page-" + pag + ".html"; } catch(e){ chap = xpath('//select[@id="id_chapter"]/option[@selected]/following-sibling::option[1]/@value', html); return "/" + manga + "-chapter-" + chap + ".html"; } }, extra: [[['#change select', ' ']]], js: function(dir){ if(!dir) exec("$(document).unbind('keyup');"); }, scrollx:'R' }, { url: 'kingfeatures.com', img: [['#comic img']], back: function(html, pos){ var date = xpath('//select[@name="date"]/option[@selected]/preceding-sibling::option[1]/@value', html); return 'aboutMaina.php?date='+date; }, next: function(html, pos){ var date = xpath('//select[@name="date"]/option[@selected]/following-sibling::option[1]/@value', html); return 'aboutMaina.php?date='+date; } }, { url: 'thezombiehunters.com', extra: [[['#ranttext']]] }, { url: 'syacartoonist.com|satwcomic.com|stupidfox.net', img: [['[src*="/art/"]:not([class])']], extra: [['//div[@class="stand_high"][1]']] }, { url: 'casualvillain.com', img: [['#comic img']], back: '.="Back"', next: '.="Forward"' }, { url: 'fanboys-online.com', extra: [[['.post-content']]], bgcol: '#490606' }, { url: 'truyen.vnsharing.net', img: function(html, pos){ var pags = html.match(/lstImages.push\(".+"\);/g); var num = link[pos].match(/##(\d+)/); num = num ? parseInt(num[1]) : 0; return pags[num].match(/"(.+)"/)[1]; }, back: function(html, pos){ var num = link[pos].match(/##(\d+)/); num = num ? parseInt(num[1]) : 0; if(num) return link[pos].split('##')[0] + '##' + (num-1); var base = html.match(/\$\('#selectChapter'\).change[^\}]+'(.+)'/)[1]; var chap = xpath('//select[@id="selectChapter"]/option[@selected]/preceding-sibling::option[1]/@value', html); return base + chap + '##0'; }, next: function(html, pos){ var pags = html.match(/lstImages.push\(".+"\);/g); var num = link[pos].match(/##(\d+)/); num = num ? parseInt(num[1]) : 0; if(num < pags.length-1) return link[pos].split('##')[0] + '##' + (num+1); var base = html.match(/\$\('#selectChapter'\).change[^\}]+'(.+)'/)[1]; var chap = xpath('//select[@id="selectChapter"]/option[@selected]/following-sibling::option[1]/@value', html); return base + chap; }, layelem:'//div[@id="divImage"]', scrollx:'R' }, { url: 'lovehentaimanga.com', img: 'mangas/', back: 'img[@title="Previous Page"]', next: 'img[@title="Next Page"]', extra: [['//div[@class="pager"]']], xelem: '//tr[last()]//div[@class="pager"]', scrollx:'R' }, { url: 'freefall.purrsia.com', img: '/ff', back: 'contains(.,"Previous")', next: 'contains(.,"Next")' }, { url: 'mangachapter.net', img: [['#mangaImg']], back: function(html, pos){ try{ return xpath('//a[.="Previous page"]', html); } catch(e){ return xpath('//span[.="Previous Chapter:"]/following-sibling::a[1]', html); } }, next: function(html, pos){ try{ return xpath('//a[.="Next page"]', html); } catch(e){ return xpath('//span[.="Next Chapter:"]/following-sibling::a[1]', html); } }, extra: [[['#top_chapter_list']], [['.mangaread-bt .page-select select']]], scrollx:'R' }, { url: 'shd-wk.com', style: '#wcr_div{text-align:left !important;} #wcr_listabm{padding-top:100px;}' }, { url: 'pebbleversion.com', img: [['img[src*="ComicStrips"]']], extra: [[['td[rowspan="2"] div']], [['td[colspan="4"] font']]] }, { url: 'accurseddragon.com', extra: [[['.webcomic_post']]] }, { url: 'krakowstudios.com', back: '.="Previous Comic"', next: '.="Next Comic"' }, { url: 'victorycomic.comicgenesis.com', img: [['img[alt="Comic"]']] }, { url: 'flakypastry.runningwithpencils.com', img: 'comics/' }, { url: 'gogetaroomie.chloe-art.com', img: [['.comicpane img']] }, { url: 'springiette.net', back: 'img[contains(@alt,"previous")]', next: 'img[contains(@alt,"next")]' }, { url: 'mindmistress.comicgenesis.com', img: '/comics/', extra: [[['img[src^="/comics/"]', '', 1]]] }, { url: 'kastlecomics.comicgenesis.com', img: [['img[src*="/comics/"]']] }, { url: 'evernightcomic.com', style: '#wcr_imagen{height:auto !important;}' }, { url: '*.xindm.cn', img: [['img[src*="../book/"]']], back: '@id="prev" and not(contains(@href, "page=0"))', next: '@id="next" and not(//select[@name="page"]/option[last()][@selected])', extra: [[['select[name="page"]']]], scrollx:'R' }, { url: 'manga123.com', img: 'http://cdn.images.manga123.com/', back: [/var back = '(.+?)';/, 1], next: [/var next = '(.+?)';/, 1], fixurl: function(url, img, link){ // if this is a link to an interstitial page - fix it if(link && !url.match(/\/read(\/[^\/]+){3}/)) return url + '/1'; return url; }, scrollx:'R' }, { url: 'reader.eternalmanga.net|sakicow.com', img: function(html, pos){ var num = link[pos].match(/##.*_(\d+)/); num = num ? parseInt(num[1]) : 0; return html.match(new RegExp("imageArray\\["+num+"\\]='(.+?)';"))[1]; }, back: function(html, pos){ var num = link[pos].match(/##.*_(\d+)/); num = num ? parseInt(num[1])-1 : -1; if(num>0) return '##'+(pos-1)+'_'+num; return xpath('//div[@class="selector2" and starts-with(., "chapter:")]//a[contains("'+link[pos]+'", @href)]/preceding-sibling::a[1]/@href', html)+'##'+(pos-1)+'_0'; }, next: function(html, pos){ var num = link[pos].match(/##.*_(\d+)/); num = num ? parseInt(num[1])+1 : 1; if(html.match(new RegExp("imageArray\\["+num+"\\]='(.+?)';"))) return '##'+(pos+1)+'_'+num; return xpath('//div[@class="selector2" and starts-with(., "chapter:")]//a[contains("'+link[pos]+'", @href)]/following-sibling::a[1]/@href', html)+'##'+(pos+1)+'_0'; }, js: function(dir){ if(!dir) exec("$(document).unbind('keyup');"); }, layelem:'//div[@id="thePic"]', scrollx:'R' }, { url: 'foolrulez.org|manga.redhawkscans.com|mangatopia.net|simple-scans.com|mudascantrad.com|fallensyndicate.com|slide.extrascans.net|reader.fth-scans.com|reader.japanzai.com|manga-tu.be|friendshipscans.com|yuri-ism.net', img: [['#page img']], back: function(html, pos){ try{ var relpath = xpath('//div[@class="topbar_right"]/span[@class="numbers"]/div[contains(concat(" ",@class," ")," current_page ")]/following-sibling::div[1]//@href', html); if (relpath.match(/^http/i)) return relpath; var basepath = ""; try{ basepath = html.match(/var\s+base_?url\s*=\s*(['"])(.*?)\1\s*;/i)[2]; } catch(e){} return basepath + relpath; } catch(e){ var chap = xpath('//div[@class="topbar_left"]/div[2]/ul/li[.//text()=//div[@class="topbar_left"]/div[2]/div/a/text()]/following-sibling::li[1]//@href', html); var request = new XMLHttpRequest(); request.open('GET', chap, false); request.send(null); if (request.status === 200) { return xpath('//div[@class="topbar_right"]/div[1]/ul/li[last()]//@href', request.responseText); } } }, next: function(html, pos){ try{ var relpath = xpath('//div[@class="topbar_right"]/span[@class="numbers"]/div[contains(concat(" ",@class," ")," current_page ")]/preceding-sibling::div[1]//@href', html); if (relpath.match(/^http/i)) return relpath; var basepath = ""; try{ basepath = html.match(/var\s+base_?url\s*=\s*(['"])(.*?)\1\s*;/i)[2]; } catch(e){} return basepath + relpath; } catch(e){ return xpath('//div[@class="topbar_left"]/div[2]/ul/li[.//text()=//div[@class="topbar_left"]/div[2]/div/a/text()]/preceding-sibling::li[1]//@href', html); } }, js: function(dir){ if(!dir) exec("$(document).unbind('keydown');"); }, extra: [function(html, pos){ var topbar = selCss('div.topbar', html); if (!topbar) return; var basepath = ""; try{ basepath = html.match(/var\s+base_?url\s*=\s*([\'\"])(.*?)\1\s*;/i)[2]; } catch(e){} var relpaths = xpath('//a[starts-with(@href,"page/")]', topbar, true); for (var x = 0; x < relpaths.length; ++x) { relpaths[x].setAttribute('href', basepath + relpaths[x].getAttribute('href')); } var pagesLinks = xpath('//a[@onclick]', topbar, true); for (var x = 0; x < pagesLinks.length; ++x) { pagesLinks[x].removeAttribute('onclick'); } return topbar.outerHTML; }], xelem: '//div[@class="panel"]', layelem:'//div[@id="page"]', scrollx:'R', style: '#wrapper{overflow:visible !important;}' }, { url: 'manga-go.com', img: [['#page1']], back: '@class="prev_page"', next: '@class="next_page"', scrollx:'R' }, { url: 'comicstriplibrary.org', img: '/images/comics/', back: '.="<< Previous"', next: '.="Next >>"' }, { url: 'wirepop.com', img: [['center>a>img, center>img']], scrollx:'R' }, { url: 'fantasyrealmsonline.com', img: [['img[border="1"]']] }, { url: 'psychopandas.com', img: '/files/', style: '.imgPage span{display:none !important;}', scrollx:'R' }, { url: 'readonline.egscans.org|read.egscans.org', img: function(html, pos){ var num = link[pos].match(/(##.*_|\/)(\d+)$/); num = num ? parseInt(num[2])-1 : 0; return html.match(/img_url.push\('.+' \);/g)[num].match(/'(.+)'/)[1]; }, back: function(html, pos){ var num = link[pos].match(/(##.*_|\/)(\d+)$/); num = num ? parseInt(num[2])-1 : 0; if(!num){ var base = '/' + html.match(/var prev_chap = '(.+)';/)[1] + '/'; var htmlPrev = syncRequest(base, pos); num = parseInt(htmlPrev.match(/var page_max = parseInt\('(\d+)'\);/)[1]); base += num + '/'; } else{ var selpag = selCss('[name="page"]', html); base = selpag.getAttribute('onchange').match(/'(.+)', '(.+)'/); base = base[1]+'/'+base[2]+'/'+num; } return base+'##'+(pos-1)+'_'+num; }, next: function(html, pos){ var num = link[pos].match(/(##.*_|\/)(\d+)$/); num = num ? parseInt(num[2])+1 : 2; var page_max = parseInt(html.match(/var page_max = parseInt\('(.+)'\);/)[1]); if(num > page_max){ var base = html.match(/var next_chap = '(.+)';/)[1]+'/1'; num = 1; } else{ var selpag = selCss('[name="page"]', html); base = selpag.getAttribute('onchange').match(/'(.+)', '(.+)'/); base = base[1]+'/'+base[2]+'/'+num; } return base+'##'+(pos+1)+'_'+num; }, extra: [[['.pager>*', '']]], xelem: '//div[@class="pager"]', style: '#page_select a{display:none;} #wcr_div button{background-color:#ccc;}', txtcol: '#fff', fixurl: function(url, img, link){ if(link && document.location.host == 'read.egscans.org'){ var base = selCss('base'); if(base) base.href = base.href.replace('readonline.egscans.org', 'read.egscans.org'); return url.replace('readonline.egscans.org', 'read.egscans.org'); } return url; }, scrollx:'R' }, { url: 'gallery.ryuutama.com/view.php', img: [['img']], back: function(html, pos){ if(!pos){ var manga = html.match(/current_manga = "(.+?)";/)[1]; var page = parseInt(html.match(/current_page = "(.+?)";/)[1]) - 1; var total = parseInt(html.match(/total_pages = "(.+?)";/)[1]); if(page) return '/api.php?grab=manga&id='+manga+'&page='+page+'##'+total; } else{ page = parseInt(link[pos].match(/page=(\d+)/)[1]) - 1; if(page) return link[pos].replace(/page=(\d+)/,'page='+page); } throw 'fail'; }, next: function(html, pos){ if(!pos){ var manga = html.match(/current_manga = "(.+?)";/)[1]; var page = parseInt(html.match(/current_page = "(.+?)";/)[1]); var total = parseInt(html.match(/total_pages = "(.+?)";/)[1]); return '/api.php?grab=manga&id='+manga+'&page='+page+'##'+total; } else{ page = parseInt(link[pos].match(/page=(\d+)/)[1]) + 1; total = parseInt(link[pos].match(/#(\d+)/)[1]); if(page <= total) return link[pos].replace(/page=(\d+)/,'page='+page); } throw 'fail'; }, scrollx:'R', layelem:'//div[@id="imageContainer"]' }, { url: 'gallery.ryuutama.com/api.php', img: function(html, pos){ redirect(link[0].replace('api.php?grab=manga&id=', 'view.php?manga=')); } }, { url: '*.tiraecol.net', img: [['img[src*="tiraecol.net/modules/comic/cache/images/"]']], back: ['//td[@width="200px" and @align="left"]/a[2]'], next: ['//td[@width="200px" and @align="right"]/a[1]'], extra: [[['.title']]] }, { url: 'conejofrustrado.com', back: '@class="navAnterior"', next: '@class="navSiguiente"' }, { url: 'e2w-illustration.com', img: 'http://www.e2w-illustration.com/images/' }, { url: '2gamerz.com', img: 'http://2gamerz.com/wp-content/webcomic/' }, { url: 'mymangaspot.com', img: [['.mng_rdr a img']], back: '.="Prev"', next: '.="Next"', extra: [[['.wpm_nav select', ' ', 0, 2]]], style: '.mng_rdr>div{overflow:visible !important;}', scrollx:'R' }, { url: 'comic.naver.com', img: [['.wt_viewer img']], back: [['.pre a']], next: [['.next a']], extra: [[['.wt_viewer img', '<br/>', 1]]], style: '.wt_viewer>img{display:none;}' }, { url: 'mangatraders.com', img: [['#image']], back: [/value="Prev Page" onclick="window.location.href='([^']+)'"/, 1], next: [/value="Next Page" onclick="window.location.href='([^']+)'"/, 1], js: function(dir){ exec('window.removeEventListener("keydown", handleKey, true)'); }, scrollx:'R', extra: [[['div#viewerHeader>div', '']], '<div class="clear"></div>', [['div#file_dropdown_top', '']], [['div#page_dropdown_top']], [['div#reportLink']], [['div#image_display div']]], xelem: '//div[@id="viewerHeader"]', layelem:'//div[@id="image_display"]', style: '#page_dropdown_top,#file_dropdown_top,#page_path_bottom,#reportLink{display:none} #viewerHeader>div{display:block} #reportLink{padding-top:0 !important' }, { url: 'hentaifromhell.net', img: [['img.imageborder']], scrollx:'R' }, { url: 'trenchescomic.com', img: [['.comic img']] }, { url: 'goominet.com', img: [['center>img[src^="uploads/"]']], extra: [[['center>img[src^="t"]']]] }, { url: 'doesnotplaywellwithothers.com', extra: [[['#sidebar-undercomic p']]] }, { url: 'aikoniacomic.com', style: '#comic{height:auto;}', extra: [[['#blurb']]] }, { url: 'grrlpowercomic.com', extra: [[['.post-comic']]] }, { url: 'the-whiteboard.com', img: [['center>img']] }, { url: 'mezzacotta.net', extra: [[['h2']], ['//h2/following-sibling::p', '', 2]] }, { url: 'hbrowse.com', img: [['.pageImage img']], back: ['//a[not(@href)]/preceding-sibling::a[1] | //a[@name="prev" and not(starts-with(@href, "javascript"))]'], next: ['//a[not(@href)]/following-sibling::a[1] | //a[@name="next" and not(starts-with(@href, "javascript"))]'] }, { url: 'vexxarr.com', img: [['img[src^="Vexxarr"]:not([src*="header"])']], extra: [[['b']]] }, { url: 'aptitude.surfacingpoint.com', img: 'comics/', extra: [[['.rant']]] }, { url: 'fancyadventures.com', extra: [[['.entry p']]] }, { url: 'chron.com', img: [['div.hst-comic li>img']], back: 'img[@id="hst_galleryitem_index_prev_en"]', next: 'img[@id="hst_galleryitem_index_next_en"]' }, { url: 'heroeslocales.com', img: [['#comic img']], back: 'img[contains(@src, "/b_ant.png")]', next: 'img[contains(@src, "/b_sig.png")]' }, { url: 'readhentaionline.com', img: [['div[align="center"] img']], next: [['div[align="center"] a']] }, { url: 'darklegacycomics.com', img: [['td[background="comic_mid.gif"] img']] }, { url: 'bearmageddon.com', extra: [[['.post']]] }, { url: 'betweenfailures.net', img: 'http://betweenfailures.net/wp-content/webcomic/', extra: [[['.webcomic_post h1']], [['.webcomic_post .content']]] }, { url: 'sisterclaire.com', back: function(html, pos){ try{ return xpath('//a[.="Previous"]', html); } catch(e){ return xpath('//a[.="Previous Chapter"]', html); } }, next: '.="Next" or .="Next Chapter"', extra: [[['.entry']]] }, { url: 'fayerwayer.com|niubie.com', img: [['.attachment-post-full-galeria']], back: '.="Anterior"', next: '.="Próxima"' }, { url: 'awesomehospital.com', extra: [[['.post-comic']]] }, { url: 'ars.userfriendly.org', img: 'http://www.userfriendly.org/cartoons/archives/', back: [['[alt="Previous Cartoon"]']], next: [['[alt="Next Day\'s Cartoon"]']] }, { url: 'friendswithboys.com', img: [['.entry img']], extra: [[['.entry>*', '', 1]]] }, { url: 'calamitiesofnature.com', img: [['#comic img']] }, { url: 'irregularwebcomic.net', extra: [[['#annotation']]], style: 'div.hide {display: block; text-align: left;}', }, { url: 'adistantsoil.com', back: '@title="Previous"', next: '@title="Next"', extra: [['//div[@class="post-content"]']], bgcol: '#f4eebc' }, { url: 'kronos.mcanime.net', img: [['#current-image img']], back: function(html, pos){ try{ return xpath('//select[@id="pages"]/option[@selected]/preceding-sibling::option[1]/@value', html); } catch(e){ var cap = xpath('//select[@id="chapters"]/option[@selected]/following-sibling::option[1]/@value', html); var pag = xpath('//input[@id="lastpage"]/@value', html); return cap.replace(/\/\d+$/, pag); } }, next: function(html, pos){ try{ return xpath('//select[@id="pages"]/option[@selected]/following-sibling::option[1]/@value', html); } catch(e){ return xpath('//select[@id="chapters"]/option[@selected]/preceding-sibling::option[1]/@value', html); } }, scrollx:'R' }, { url: 'ghastlycomic.com', extra: [function(html, pos){ iframe = xpath('//iframe[@id="newsbox"]', html); blockquote = iframe.parentNode; blockquote.removeChild(iframe); return blockquote; }], }, { url: 'walkingdeadbr.com', img: 'albums/' }, { url: 'mangapanda.com', scrollx:'R' }, { url: 'mangable.com', img: [['#image']], scrollx:'R' }, { url: 'dragonflyscans.org', img: [['#page img']], scrollx:'R' }, { url: 'readincesthentai.com|hentaistreamer.com', img: [['.picture']], scrollx:'R', style: '#container{width:auto;}' }, { url: 'kissmanga.com', img: function(html, pos){ var imgs = html.match(/lstImages\.push\(".+?"\);/g); var num = pos ? Number(link[pos].match(/##(\d+);/)[1]) : 0; return imgs[pos-num].match(/"(.+)"/)[1]; }, back: function(html, pos){ throw 'fail'; }, next: function(html, pos){ if(!pos) return '##0;1'; var imgs = html.match(/lstImages\.push\(".+?"\);/g); var num = Number(link[pos].match(/##(\d+);/)[1]); if(num+imgs.length > pos+1) return '##' + num + ';' + (pos+1); return xpath('//select[@id="selectChapter"]/option[@selected]/following-sibling::option[1]/@value', html) + '##' + (num+imgs.length) + ';' + (pos+1); }, scrollx:'R', layelem:'//img[@id="imgCurrent"]' }, { url: 'readmangahentai.com', img: function(html, pos){ var imgs = html.match(/lstImages\.push\(".+?"\);/g); var num = pos ? Number(link[pos].match(/##(\d+);/)[1]) : 0; return imgs[pos-num].match(/"(.+)"/)[1]; }, back: function(html, pos){ throw 'fail'; }, next: function(html, pos){ if(!pos) return '##0;1'; var imgs = html.match(/lstImages\.push\(".+?"\);/g); var num = Number(link[pos].match(/##(\d+);/)[1]); if(num+imgs.length > pos+1) return '##' + num + ';' + (pos+1); return xpath('//select[@id="chapter_select"]/option[@selected]/preceding-sibling::option[1]/@value', html) + '.html##' + (num+imgs.length) + ';' + (pos+1); }, scrollx:'R', layelem:'//div[@id="image"]', js: function(dir){ if(!dir) document.onkeyup = ''; } }, { url: 'masterbloodfer.org', scrollx:'R' }, { url: 'mangatank.com|mangapark.com|mangawindow.com', img: [['.img-link img']], style: '#wcr_div{line-height:1;}', js: function(dir){ if(!dir) document.onkeyup = ''; }, scrollx:'R' }, { url: 'snowflakescomic.com', back: './img[contains(@src, "nav_prior")]' }, { url: 'mangafox.mobi', img: [['a img']], back: '.="Previous Page"', next: 'img', scrollx:'R' }, { url: 'mangainn.me', img: [['#imgPage']], back: function(html, pos){ var m = link[pos].match(/^(.+\/chapter\/)([^\/]+)/); try{ return m[1] + m[2] + '/page_' + xpath('//select[@id="cmbpages"]/option[@selected]/preceding-sibling::option[1]/@value', html); }catch(e){ return m[1] + xpath('//select[@id="chapters"]/option[@selected]/preceding-sibling::option[1]/@value', html) + '/page_1'; } }, next: function(html, pos){ var m = link[pos].match(/^(.+\/chapter\/)([^\/]+)/); try{ return m[1] + m[2] + '/page_' + xpath('//select[@id="cmbpages"]/option[@selected]/following-sibling::option[1]/@value', html); }catch(e){ return m[1] + xpath('//select[@id="chapters"]/option[@selected]/following-sibling::option[1]/@value', html) + '/page_1'; } }, scrollx:'R' }, { url: 'shiftylook.com', img: [['.comicMainImage img']], back: '@class="prev"', next: '@class="next"', style: '.comicMainImage{height:auto !important;}' }, { url: 'onlinereader.mangapirate.net', img: [['#page']], back: '@id="prev"', next: '@id="next"' }, { url: '8comic.com', img: function(html, pos){ var ch = link[pos].match(/ch=([\d-]+)/)[1].split('-'); var p = ch.length > 1 ? parseInt(ch[1]) : 1; ch = parseInt(ch[0]); var chs = parseInt(html.match(/var chs=(\d+)/)[1]); var itemid = parseInt(html.match(/var itemid=(\d+)/)[1]); var codes = html.match(/var codes="([^\"]+)"/)[1].split('|'); var code=""; var cid=0; for(i=0;i<codes.length;i++){if(codes[i].indexOf(ch+" ")==0){cid=i;code=codes[i];break;};} if(code=="") for(i=0;i<codes.length;i++){if(parseInt(codes[i].split(' ')[0])>ch) {cid=i;code=codes[i];ch=parseInt(codes[i].split(' ')[0]);break;}} if(code=="") {cid=codes.length-1;code=codes[cid];ch=chs;} var previd=cid>0?parseInt(codes[cid-1].split(' ')[0]):ch; var nextid=cid<codes.length-1?parseInt(codes[cid+1].split(' ')[0]):ch; var num=code.split(' ')[0]; var sid=code.split(' ')[1]; var did=code.split(' ')[2]; var page=code.split(' ')[3]; var code=code.split(' ')[4]; var img=""; if(p<10) img="00"+p;else if(p<100) img="0"+p;else img=p; var m=(parseInt((p-1)/10)%10)+(((p-1)%10)*3); img+="_"+code.substring(m,m+3); return "http://img"+sid+".8comic.com/"+did+"/"+itemid+"/"+num+"/"+img+".jpg"; }, back: function(html, pos){ var ch = link[pos].match(/ch=([\d-]+)/)[1].split('-'); var p = ch.length > 1 ? parseInt(ch[1]) : 1; ch = parseInt(ch[0]); var chs = parseInt(html.match(/var chs=(\d+)/)[1]); var itemid = parseInt(html.match(/var itemid=(\d+)/)[1]); var codes = html.match(/var codes="([^\"]+)"/)[1].split('|'); var code=""; var cid=0; for(i=0;i<codes.length;i++){if(codes[i].indexOf(ch+" ")==0){cid=i;code=codes[i];break;};} if(code=="") for(i=0;i<codes.length;i++){if(parseInt(codes[i].split(' ')[0])>ch) {cid=i;code=codes[i];ch=parseInt(codes[i].split(' ')[0]);break;}} if(code=="") {cid=codes.length-1;code=codes[cid];ch=chs;} var previd=cid>0?parseInt(codes[cid-1].split(' ')[0]):ch; var nextid=cid<codes.length-1?parseInt(codes[cid+1].split(' ')[0]):ch; var num=code.split(' ')[0]; var sid=code.split(' ')[1]; var did=code.split(' ')[2]; var page=code.split(' ')[3]; var code=code.split(' ')[4]; var x = ch+'-'+(p-1); if(p<=1){ if(ch<=1) throw 'first'; x = previd; } return link[pos].replace(/ch=.+/, 'ch='+x); }, next: function(html, pos){ var ch = link[pos].match(/ch=([\d-]+)/)[1].split('-'); var p = ch.length > 1 ? parseInt(ch[1]) : 1; ch = parseInt(ch[0]); var chs = parseInt(html.match(/var chs=(\d+)/)[1]); var itemid = parseInt(html.match(/var itemid=(\d+)/)[1]); var codes = html.match(/var codes="([^\"]+)"/)[1].split('|'); var code=""; var cid=0; for(i=0;i<codes.length;i++){if(codes[i].indexOf(ch+" ")==0){cid=i;code=codes[i];break;};} if(code=="") for(i=0;i<codes.length;i++){if(parseInt(codes[i].split(' ')[0])>ch) {cid=i;code=codes[i];ch=parseInt(codes[i].split(' ')[0]);break;}} if(code=="") {cid=codes.length-1;code=codes[cid];ch=chs;} var previd=cid>0?parseInt(codes[cid-1].split(' ')[0]):ch; var nextid=cid<codes.length-1?parseInt(codes[cid+1].split(' ')[0]):ch; var num=code.split(' ')[0]; var sid=code.split(' ')[1]; var did=code.split(' ')[2]; var page=code.split(' ')[3]; var code=code.split(' ')[4]; var x = ch+'-'+(p+1); if(p>=page){ if(ch>=chs) throw 'last'; x = nextid; } return link[pos].replace(/ch=.+/, 'ch='+x); }, scrollx:'R' }, { url: 'mangahead.com', img: [['#mangahead_image']], back: '@id="page_previous"', next: '@id="page_next"', scrollx:'R' }, { url: 'vickifox.com', img: [['.comic']] }, { url: 'spinnyverse.com', back: [['.nav-previous a']], next: [['.nav-next a']] }, { url: 'zenpencils.com', extra: [[['.comicpress_comic_blog_post_widget']]] }, { url: 'wootmanga.com', fixurl: function(url, img, link){ if(link && url.split('/').length == 5) url += '/1'; return url; }, scrollx:'R' }, { url: 'hentai2read.com', img: [['.prw img']], back: function(html, pos){ var baseurl = xpath('(//select[@class="cbo_wpm_chp"])/@onchange', html).replace(/^.*?'|'.*$/gi, ''); try{ var pag = xpath('(//select[@class="cbo_wpm_pag"])/option[@selected]/preceding-sibling::option[1]/@value', html); var chap = selCss('select.cbo_wpm_chp > option[selected]', html).value; return baseurl + chap +'/' + pag + '/'; } catch(e){ var chap = xpath('(//select[@class="cbo_wpm_chp"])/option[@selected]/following-sibling::option[1]/@value', html); var htmlPrev = syncRequest(baseurl + chap +'/', pos); var pag = xpath('(//select[@class="cbo_wpm_pag"])/option[last()]/@value', htmlPrev); return baseurl + chap +'/' + pag + '/'; } }, next: ['//div[@class="wpm_seo"]/a[.="Next" and not(@href="")]'], extra: [[['.wpm_nav']]], style: '#wcr_imagen{max-width:none;} .prw{overflow:visible !important;} div.wpm_nav{display:none} #wcr_extra>div.wpm_nav{display:block}', fixurl: function(url, img, link) { if (link) return url.replace('m.hentai2read.com', 'hentai2read.com'); return url; }, scrollx:'R' }, { url: 'm.hentai2read.com', img: [['.prw img']], back: function(html, pos){ var baseurl = xpath('//select[@class="cbo_wpm_chp"]/@onchange', html).replace(/^.*?'|'.*$/gi, ''); try{ var pag = xpath('//select[@class="cbo_wpm_pag"]/option[@selected]/preceding-sibling::option[1]/@value', html); var chap = selCss('select.cbo_wpm_chp > option[selected]', html).value; return baseurl + chap +'/' + pag + '/'; } catch(e){ var chap = xpath('//select[@class="cbo_wpm_chp"]/option[@selected]/following-sibling::option[1]/@value', html); var htmlPrev = syncRequest(baseurl + chap +'/', pos); var pag = xpath('//select[@class="cbo_wpm_pag"]/option[last()]/@value', htmlPrev); return baseurl + chap +'/' + pag + '/'; } }, next: ['//img[contains(concat(" ",@class," ")," cmd ") and @alt="Next Page" and starts-with(../@href,"http")]/..'], extra: ['<span style="float:left">Chapter ', [['.cbo_wpm_chp']], '</span><span style="float:right">Page ', [['.cbo_wpm_pag']], '</span><span class="clr"></span>'], style: '.header{position:relative;} .content-box{padding-top:20px;} #wcr_imagen{max-width:none;} .prw{overflow:visible !important;} div.wpm_nav{display:none}', scrollx:'R' }, { url: 'komikmy.com', img: [['.wpm_pag img']], style: '.bmk + div{overflow:visible !important;}', scrollx:'R' }, { url: 'hentaifr.net', img: 'http://www.hentaifr.net/contenu/', back: 'img[contains(@src, "previous")]', next: 'img[contains(@src, "suivant")]', scrollx:'R' }, { url: 'sientoymiento.cl', img: [['.entry-content img']] }, { url: 'mangasky.com', img: [['.manga-page']], scrollx:'R' }, { url: 'mangapirate.net', img: [['#mangapage']], scrollx:'R' }, { url: 'nomanga.com', img: [['div.prw>a>img']], extra: [[['.wpm_nav']]], scrollx:'R' }, { url: 'pipi.cl', img: [['#tira']], back: [['#prev']], next: [['#next']] }, { url: 'hentaimangaonline.com', img: [['#p']], back: function(html, pos){ var pageid = match(html, /var pageid = (\w+);/, 1); var pages = match(html, /var pages=new Array\((.+?)\);/, 1).split(','); var idx = pages.indexOf(pageid); if(!pages[idx-1]) throw 'fail'; return link[pos].replace(pageid, pages[idx-1]); }, next: function(html, pos){ var pageid = match(html, /var pageid = (\w+);/, 1); var pages = match(html, /var pages=new Array\((.+?)\);/, 1).split(','); var idx = pages.indexOf(pageid); if(!pages[idx+1]) throw 'fail'; return link[pos].replace(pageid, pages[idx+1]); }, style: '.pull-left{max-width:none !important;}', scrollx:'R' }, { url: 'webcomics.yaoi911.com', img: [['.webcomic-object img']], back: '@rel="previous"', next: '@rel="next"' }, { url: 'actiontimebuddies.com', img: [['#comic img']], back: function(html, pos){ try{ return selCss('a.navi-prev-in', html); } catch(e){ return selCss('a.navi-prevchap', html); } }, extra: [[['#comic img', '', 1]], [['.entry']]] }, { url: 'superbrophybrothers.com', img: [['.post-body img']], back: '.="Back"', next: '.="Next"', extra: [['//div[contains(@class, "post-body")]//span[@title]/@title'], '<br/>', ['//u[.="News"]/following::span[./ancestor::*[contains(@class, "post-body")] and not(./ancestor::span/ancestor::*[contains(@class, "post-body")])]', '<br/>']] }, { url: 'surasplace.com', img: function(html, pos){ var data = document.querySelectorAll('a.sigProLink'), x = link[0].match(/[&?]ipage=(.*?)(&|$)/i); x = Number(x ? x[1] : 0) + pos; if(!x) return '.'; if(x<0 || x>data.length) throw 'fail'; return data[x-1].getAttribute('image-src') || data[x-1].href; }, back: function(html, pos){ var data = document.querySelectorAll('a.sigProLink'), pgregex = /(\\?|\\&)ipage=(.*?)(?=(&|$))/i, x = link[0].match(pgregex); x = Number(x ? x[2] : 0) + pos - 1; if (x<0 || x>data.length) throw 'fail'; if (!x) return link[0].replace(/#.*$|(\\?|\\&)ipage=(.*?)(&|$)/gi, ''); if (pgregex.test(link[0])) return link[0].replace(pgregex, '$1ipage=' + x); return link[0].replace(/#.*$/, '') + (/\?./.test(link[0])?'&':'?') + 'ipage=' + x; }, next: function(html, pos){ var data = document.querySelectorAll('a.sigProLink'), pgregex = /(\\?|\\&)ipage=(.*?)(?=(&|$))/i, x = link[0].match(pgregex); x = Number(x ? x[2] : 0)+pos+1; if(x<0 || x>data.length) throw 'fail'; if (pgregex.test(link[0])) return link[0].replace(pgregex, '$1ipage=' + x); return link[0].replace(/#.*$/, '') + (/\?./.test(link[0])?'&':'?') + 'ipage=' + x; }, extra: ['Images from article: ', ['//div[@class="page-header"]/following-sibling::p[1]/text()'], function(html, pos){ var data = document.querySelectorAll('a.sigProLink'), x = link[0].match(/[&?]ipage=(.*?)(&|$)/i); if (!(data && data.length)) throw 'fail'; x = Number(x ? x[1] : 0)+pos; if (!x) return "<br/>Thumbs"; var filename = data[x-1].getAttribute('image-src') || data[x-1].href; return "<br/>Image " + x + " of " + data.length + " (File: '" + filename.replace(/^.*\//, '') + "')"; } ], js: function(dir){ var pgregex = /(\\?|\\&)ipage=.*?(?=(&|$))/i, x; x = link[0].match(pgregex); x = Number(x ? x[2] : 0)+posActual; if (!x) scrollTo(0,0); if (!dir) { function changeIPage(url, pagenum) { if (pgregex.test(url)) return url.replace(pgregex, '$1ipage=' + pagenum); return url.replace(/#.*$/, '') + (/\?./.test(url)?'&':'?') + 'ipage=' + pagenum; } var contentLinks = document.querySelectorAll('a.sigProLink'); for (x = 0; x < contentLinks.length;) { contentLinks[x].removeAttribute('rel'); contentLinks[x].removeAttribute('target'); contentLinks[x].setAttribute('image-src', contentLinks[x].href); contentLinks[x].href = changeIPage(link[0], ++x); } } }, scrollx:'R', layelem:'//div[@class="sigProPrintMessage"]', style: '#header, .navbar-fixed-top, .navbar-fixed-bottom {position:static;}' }, { url: 'mangacow.me', img: [['.prw img']], back: function(html, pos){ var baseurl = xpath('(//select[@class="cbo_wpm_chp"])/@onchange', html).replace(/^.*?'|'.*$/g, ''); try{ var pag = xpath('(//select[@class="cbo_wpm_pag"])/option[@selected]/preceding-sibling::option[1]/@value', html); var chap = selCss('select.cbo_wpm_chp > option[selected]', html).value; return baseurl + chap +'/' + pag + '/'; } catch(e){ var chap = xpath('(//select[@class="cbo_wpm_chp"])/option[@selected]/following-sibling::option[1]/@value', html); var request = new XMLHttpRequest(); request.open('GET', baseurl + chap +'/', false); request.send(null); if (request.status === 200) { var pag = xpath('(//select[@class="cbo_wpm_pag"])/option[last()]/@value', request.responseText); return baseurl + chap +'/' + pag + '/'; } } }, extra: [[['div.wpm_nav']]], style: 'div.wpm_nav {display:none} #wcr_extra>div.wpm_nav {display:block}', scrollx:'R' }, { url: 'thedevilspanties.com', extra: [['//div[@class="entry"]']], }, { url: 'hentai4manga.com', img: [['#textboxContent img']], back: [['#sub_page_left a']], next: [['#sub_page_right a']], style: '#innerWrapper, .content{width: auto !important; max-width: none !important;} .textbox > div{float: none !important;}', scrollx:'R' }, { url: 'bradcolbow.com', img: [['.entry img']], extra: [[['h2']], [['h5']]] }, { url: 'gaomanga.com', img: [['#slice0']], back: ['//div[@class="pageButtonDivSelected"]/preceding-sibling::div[1]/a'], scrollx:'R' }, { url: 'guildedage.net', img: [['#comic img']], back: [['.navi-prev']], next: [['.navi-next']] }, { url: 'betweenfailures.com', img: [['.webcomic-image img']] }, { url: 'claudeandmonet.com', img: [['.webcomic-object img']] }, { url: 'phobia.subcultura.es', img: [['#tira img']], back: '.="Anterior"', next: '.="Siguiente"' }, { url: 'de.ninemanga.com', img: [['.manga_pic']], back: [['.blue']], next: '.=">>"', scrollx:'R' }, { url: 'proxer.me', img: [['.open']], back: function(html, pos){ var c = parseInt(match(link[pos], /[?&]c=(\d+)/, 1, 1)); var p = parseInt(match(link[pos], /[?&]p=(\d+)/, 1, 1)) - 1; if(!p){ c--; p=1 } console.log([pos,-1,c,p]); if(!c) throw 'inicio'; return link[pos].replace(/&[cp]=\d+/g, '') + '&c='+c+'&p='+p; }, next: function(html, pos){ var c = parseInt(match(link[pos], /[?&]c=(\d+)/, 1, 1)); var p = parseInt(match(link[pos], /[?&]p=(\d+)/, 1, 1)) + 1; try { selCss('.number_'+p, html); } catch(e){ c++; p=1; } console.log([pos,1,c,p]); return link[pos].replace(/&[cp]=\d+/g, '') + '&c='+c+'&p='+p; }, scrollx:'R' }, { url: 'meinmanga.com', img: [['.pic_fragment,.pic_fragment_biggest']], back: function(html, pos){ try{ return xpath('//table[@class="pagebar"]//td[3]/select/option[@selected]/preceding-sibling::option[1]/@value', html) + '.html'; } catch(e){ return xpath('//table[@class="pagebar"]//td[1]/select/option[@selected]/following-sibling::option[1]/@value', html); } }, next: function(html, pos){ try{ return xpath('//table[@class="pagebar"]//td[3]/select/option[@selected]/following-sibling::option[1]/@value', html) + '.html'; } catch(e){ return xpath('//table[@class="pagebar"]//td[1]/select/option[@selected]/preceding-sibling::option[1]/@value', html); } }, extra: [[['.pic_fragment,.pic_fragment_biggest', '<br/>', 1]], '<br/>', [['.pagebar']]], layelem:'//div[@class="topad"]', style: '#content > table:not(.pagebar){display:none;} .pic_fragment_biggest{margin-left:0;} #content{overflow:visible;}', scrollx:'R' }, { url: '*.senmanga.com', img: function(html, pos){ try{ return match(html, /img\.src *= *'([^\']+)'/, 1); } catch(e){ return selCss('#picture', html); } }, back: function(html, pos){ try{ return xpath('//a[.="Back"]', html); } catch(e){ var manga = document.location.pathname.match(/^\/[^\/]+\//)[0]; return manga + xpath('//select[@name="chapter"]/option[@selected]/following-sibling::option[1]/@value', html); } }, next: function(html, pos){ try{ return xpath('//a[.="Next"]', html); } catch(e){ var manga = document.location.pathname.match(/^\/[^\/]+\//)[0]; return manga + xpath('//select[@name="chapter"]/option[@selected]/preceding-sibling::option[1]/@value', html); } }, scrollx:'R' }, { url: 'mangaesta.net|www.mabuns.web.id|manga4indo.com|neumanga.com', img: function(html, pos){ var page = match(link[pos], /page=(\d+)$/, 1, 1); var pages = html.match(/addpage\('(.+)?'.*\)/g); return pages[page-1].match(/'(.+?)'/)[1]; }, back: function(html, pos){ var page = match(link[pos], /page=(\d+)$/, 1, 1); if(--page) return link[pos].replace(/(##page=\d+)?$/, '##page='+page); throw 'first'; }, next: function(html, pos){ var page = match(link[pos], /page=(\d+)$/, 1, 1); var pages = html.match(/addpage\('(.+)?'.*\)/g); if(++page <= pages.length) return link[pos].replace(/(##page=\d+)?$/, '##page='+page); throw 'last'; }, layelem:'//span[@id="page"]', scrollx:'R' }, { url: 'bloomingfaeries.com', img: [['#comic img']] }, { url: 'neechan.net', img: [['.prw img']], scrollx:'R' }, { url: '*.komikid.com', img: [['td>a>img']], back: function(html, pos){ try{ return xpath('//a[img[@title="Previous Page"]]', html); } catch(e){ var chapter = xpath('//select[@name="chapter"]/option[@selected]/following-sibling::option[1]/@value', html); return link[pos].replace(/(\/\/([^\/]+\/){2}).*/, '$1' + chapter); } }, next: function(html, pos){ try{ return xpath('//a[img[@title="Next Page"]]', html); } catch(e){ var chapter = xpath('//select[@name="chapter"]/option[@selected]/preceding-sibling::option[1]/@value', html); return link[pos].replace(/(\/\/([^\/]+\/){2}).*/, '$1' + chapter); } }, scrollx:'R' }, { url: 'moonoverjune.com', img: [['.comicpage']] }, { url: 'shadbase.com|shagbase.com', img: [['#comic img']], extra: [['//div[@id="comic-1" and not(img)]'], [['#comic .comicpane', '', 1]]], layelem:'//div[@id="comic"]' }, { url: 'mangago.com', img: [['#page1']], scrollx:'R' }, { url: 'mrlovenstein.com', img: [['.comic_image div img']], back: 'img[contains(@src, "nav_left")]', next: 'img[contains(@src, "nav_right")]', layelem:'//div[@class="comic_image"]' }, { url: 'anticscomic.com', img: [['#comic img']] }, { url: 'octopuns.blogspot.com', img: [['.post-body img']], back: 'img[contains(@src,"Back.png")]', next: 'img[contains(@src,"Next.png")]', extra: [['//div[contains(@class, "post-body")]/*[not(@class="separator") or contains(@style, "text-align: left")] | //div[contains(@class, "post-body")]/text()', '']], fixurl: function(url, img, link){ if(link) return url.replace('.com.au/', '.com/'); return url; } }, { url: 'onemanga.me|mangabee.com', img: [['.manga-page']], scrollx:'R' }, { url: 'mangacow.co|mangadoom.co|omgmanga.com', img: [['.prw a img']], back: '.="Prev"', next: '.="Next"', style: '#wcr_imagen{max-width:none;}#sct_col_l.full_width{width:auto;}', scrollx:'R' }, { url: 'ver-manga.net', img: 'http://www.ver-manga.net/cdn/', back: '.="Anterior"', next: '.="Siguiente"', scrollx:'R' }, { url: 'powernapcomic.com', img: [['center > img']], extra: [[['.titulo2']], [['.titulo2 + .news']]] }, { url: 'ismanga.com', style: '#wcr_imagen{max-width:none;}', scrollx:'R' }, { url: 'mangabird.com', img: [['.content > a > img']], back: function(html, pos){ return link[pos].replace(/(page=)(\d+)/, function(s, p, n){ return n=='0' ? s : p + (parseInt(n) - 1); }); }, next: [['.content a']], style: '#wcr_imagen{max-width:none;}', scrollx:'R' }, { url: 'mangachrome.com', img: [/src="([^\"]+)".+name="img"/, 1], scrollx:'R' }, { url: '7manga.com', img: function(html, pos){ if(!pos) return get('TheImg'); var m = link[pos].match(/[&?]n=(\d+)/); var n = m ? parseInt(m[1]) : 1; return imagen[0].replace(/\/0\/.+$/, '/0/' + selCss('#pic', html).value.split('\n')[n-1] + '.jpg'); }, back: function(html, pos){ var m = link[pos].match(/[&?]n=(\d+)/); var n = m ? parseInt(m[1]) : 1; if(n > 1) return link[pos].replace(/([&?]n=)\d+/, '$1'+(n-1)); return link[pos].replace(/(\d+)\.html/, function(s, n){ return n=='1' ? s : (parseInt(n) - 1) + '.html'; }); }, next: function(html, pos){ var pc = html.match(/var pc=.*?(\d+)/)[1]; var m = link[pos].match(/[&?]n=(\d+)/); var n = m ? parseInt(m[1]) : 0; if(n != pc){ if(n) return link[pos].replace(/([&?]n=)\d+/, '$1'+(n+1)); return link[pos] + '?n=2'; } return link[pos].replace(/(\d+)\.html.+/, function(s, n){ return n=='1' ? s : (parseInt(n) + 1) + '.html'; }); }, scrollx:'R' }, { url: 'mangadevil.com', img: [['#manga_image img']], scrollx:'R' }, { url: 'mangamofo.com', img: [['.prw img']], style: '#wcr_imagen{max-width:none;}.prw{overflow:visible !important;}', scrollx:'R' }, { url: '*.hentai.ms', img: [['.index_box > table center img, .pagination img']], scrollx:'R' }, { url: 'view.mangamonger.com', img: [['#mainimage']], back: function(html, pos){ try{ var page = xpath('//select[@name="page"]/option[@selected]/preceding-sibling::option[1]/@value', html); var ch = xpath('//select[@name="ch"]/option[@selected]/@value', html); }catch(e){ var page = xpath('//input[@name="lastpage"]/@value', html); var ch = xpath('//select[@name="ch"]/option[@selected]/preceding-sibling::option[1]/@value', html); } return '?ch='+ch+'&page='+page; }, next: function(html, pos){ try{ var page = xpath('//select[@name="page"]/option[@selected]/following-sibling::option[1]/@value', html); var ch = xpath('//select[@name="ch"]/option[@selected]/@value', html); }catch(e){ var page = '1'; var ch = xpath('//select[@name="ch"]/option[@selected]/following-sibling::option[1]/@value', html); } return '?ch='+ch+'&page='+page; }, style: '#wcr_imagen{max-width:none;}', scrollx:'R' }, { url: 'blackbird.ashen-ray.com|carciphona.com', img: function(html, pos){ return selCss('.page', html).style.backgroundImage.match(/"(.+)"/)[1]; }, layelem:'//div[@class="page"]', scrollx:'R' }, { url: 'ahs-comic.com', img: [['.webcomic-image img']], extra: [[['#main article']]], style: '.webcomic-image{font-size: 1em; line-height: 1;}' }, { url: 'gogetaroomie.com', extra: [[['#newsarea > *', '', 0, -3]]] }, { url: 'sleepymaid.com', img: [['.image']] }, { url: 'squid-ops.com', img: [['#content img']] }, { url: 'endcomic.com', img: [['#comic img']], extra: [[['.entry']]] }, { url: 'thenoobcomic.com', back: [['.comic_nav_previous_button']], next: [['.comic_nav_next_button']] }, { url: '*.zizki.com', img: [['.back img']], back: [['.larr']], next: [['.rarr']] }, { url: 'pururin.com', img: [['.b']], style: '.imageView .block{width:auto !important;}', scrollx:'R' }, { url: 'pecintakomik.com', img: [['.picture']], back: function(html, pos){ try{ return xpath('//a[./img[contains(@src, "/previous.png")]]', html); } catch(e){ var chapter = xpath('//select[@name="chapter"]/option[@selected]/following-sibling::option[1]', html).value; return link[pos].replace(/(\/manga\/[^\/]+\/)(.+)/, '$1' + chapter); } }, next: function(html, pos){ try{ return xpath('//a[./img[contains(@src, "/next.png")]]', html); } catch(e){ var chapter = xpath('//select[@name="chapter"]/option[@selected]/preceding-sibling::option[1]', html).value; return link[pos].replace(/(\/manga\/[^\/]+\/)(.+)/, '$1' + chapter); } }, scrollx:'R' }, { url: 'schizmatic.com', img: [/src="(.+?)"/, 1], extra: [[['#authorText']]] }, { url: 'bringbackroomies.com', img: [['#comic img']] }, { url: 'blindsprings.com', img: [['#comic img']] }, { url: 'wtfcomics.com', img: function(html, pos){ var m = link[pos].match(/\?(\d+)_(\d+)?/); var id = Math.max(Math.min(Number(m[2] || '1'), Number(m[1])), 1); return html.match(/document.writeln\(\"<IMG SRC=\\"([^"]+)/)[1] + id + '.jpg'; }, back: function(html, pos){ var m = link[pos].match(/([^\/]+\?)(\d+)_(\d+)?/); var id = Math.max(Math.min(Number(m[3] || '1'), Number(m[2])), 1); if(id == 1) throw 'first'; return m[1] + m[2] + '_' + (id-1); }, next: function(html, pos){ var m = link[pos].match(/([^\/]+\?)(\d+)_(\d+)?/); var id = Math.max(Math.min(Number(m[3] || '1'), Number(m[2])), 1); if(id == m[2]) throw 'last'; return m[1] + m[2] + '_' + (id+1); }, layelem:'//img' }, { url: 'olympusoverdrive.com', style: '#comic{height:auto !important;}' }, { url: '*.troutcave.net', style: '#left-wrap, #comic{width:auto !important;}' }, { url: 'gingerhaze.com', img: 'http://gingerhaze.com/sites/default/files/nimona-pages' }, { url: 'gunnerkrigg.com', back: 'img[contains(@src, "prev_a")]', next: 'img[contains(@src, "next_a")]' }, { url: 'aiacrowd.com', img: [['#comic img']] }, { url: 'aspect.waywardstudios.net', img: 'comics/' }, { url: 'cucumber.gigidigi.com', img: [['.webcomic-image img']] }, { url: 'filteredfuzz.com', extra: [[['.entry']]] }, { url: 'dorktower.com', img: [['.entry-content > p > img']], back: '.="Previous"', next: '.="Next"' }, { url: 'mangajoy.com', img: [['.prw a img']], back: '.="Prev"', next: '.="Next"', style: '.prw{overflow: visible !important;}', scrollx:'R' }, { url: 'octopuspie.com', img: 'http://www.octopuspie.com/strippy/' }, { url: 'nhentai.net', img: ['//div[@id="image-container"]//img/@src | //div[@id="image-container"]//img/@data-cfsrc'], back: [['.previous']], next: [['.next']], extra: [[['#page-container > *', '<br/>', 2]]], style: '#page-container img{max-width: none;}', layelem:'//div[@id="content"]', scrollx:'R' }, { url: 'hejibits.com', extra: [[['.post-content']]] }, { url: 'mangaindo.co', img: [['.prw a img']], back: [['.pvs']], next: [['.nxt']], style: '.prw img{max-width:none !important;}', scrollx:'R' }, { url: '5.79.87.81', img: [['#gsImageView img']], back: [['.previous']], next: [['.next']], scrollx:'R' }, { url: 'gao-subs.com', img: [['#midManga img']], back: ['//div[@class="pageButtonDivSelected"]/preceding-sibling::div[1]/a'], js: function(dir){ if(!dir) document.onkeyup = null; }, scrollx:'R' }, { url: 'paintraincomic.com', img: [['#comic img']], extra: [[['.post-content']]] }, { url: 'extrafabulouscomics.com', style: '#page{width:auto;}' } /* , { url: '', img: '', back: '', next: '' } , { url: '', img: '', back: '', next: '', first: '', last: '', extra: [[['']]], fixurl: function(url, img, link){ }, js: function(dir){ }, scrollx:'R', xelem: '', layelem:'', txtcol: '', bgcol: '', style: '', layout: true } */ ]; /* xpath: X = elemento X @A = atributo A * = comodin . = self, innerHTML al usarla en condiciones, usar /text() para retornar el texto X[Y] = X q cumple Y (Y puede referenciar atributos o hijos) X[num o last()] = el X q es el num-esimo hijo de su padre .. = parentNode / = hijo // = descendiente contains(x, y) = x.indexOf(y)>=0 starts-with(x, y) = x.indexOf(y)==0 name() = nombre del tag EN MAYUSCULAS X | Y = lo q matchee el xpath X o el Y http://xpath.alephzarro.com/content/cheatsheet.html http://www.zvon.org/xxl/XPathTutorial/General/examples.html */ var imagen = new Array(); //src de la imagen[i] var imagenOK = [true]; //dice si la imagen[i] esta cargada var imagen64 = new Array(); //contenido de la imagen[i] como data:url en base64 var imgTitle = new Array(); //el alt text de la imagen[i] var titulo = new Array(); //titulo de la pagina[i] var link = new Array(); //url de la pagina[i] var extra = new Array(); //contenido extra de la pagina[i] var posActual = 0; //posicion actual relativa a donde se empezo var prefetcheado = new Array(); prefetcheado[-1] = prefetcheado[1] = 0; var layoutDefault = '<div id="wcr_div" style="text-align:center">'+ '<style id="wcr_style" type="text/css">#wcr_div button{float:none;}</style>'+ '<img id="wcr_imagen"/><br/>' + '<div id="wcr_title"></div>' + '<div id="wcr_extra"></div>' + '<div id="wcr_botones">'+ '<br/><div>'+ '<a id="wcr_first" href="#"><< First</a> '+ '<button id="wcr_btn-1">Back</button> '+ '<button id="wcr_btn1">Next</button> '+ '<a id="wcr_last" href="#">Last >></a>'+ '</div><br/>'+ '<div><button id="wcr_btnaddbm" style="background-color:#0f0">Remember this page</button></div>'+ '<div id="wcr_listabm"></div>'+ '<div id="wcr_div_listabm_todos" style="display:none">'+ '<br/><a id="wcr_toggle_bm" href="#toggleBms">See bookmarks for other sites</a>'+ '<div id="wcr_listabm_todos" style="display:none"></div>'+ '</div>'+ '<div id="wcr_ultimavisita"></div><br/>'+ '<div>'+ '<button id="wcr_btnfit">Enable Fit-to-screen</button> '+ '<button id="wcr_btnlayout">Use Original Layout</button> '+ '<button id="wcr_btnslide">Start Slideshow</button> '+ '<button id="wcr_btnsettings">Settings</button>'+ '</div>'+ '</div>'+ '<div id="wcr_imagenes" style="display:none"></div>'+ '<div id="wcr_links_imgs" style="display:none"></div>'+ '</div>'; //en vez de reemplazar el body.innerHTML, meter el layoutdefault donde estaba la imagen y dejar el resto de la pagina intacta function layoutIntacto(){ //hago q los links a las pags anterior/sgte funcionen como los botones back/next if(confBool('overwrite_links', true)){ try{ var next = contenido(document.documentElement.innerHTML, getNext, 0); var linksNext = xpath('//*[@href="'+next+'"]', document, true); for(var i=0;i<linksNext.length;i++){ linksNext[i].href = '#next'; setEvt(linksNext[i], 'click', btnnext); } }catch(e){} try{ var back = contenido(document.documentElement.innerHTML, getBack, 0); var linksBack = xpath('//*[@href="'+back+'"]', document, true); for(i=0;i<linksBack.length;i++){ linksBack[i].href = '#back'; setEvt(linksBack[i], 'click', btnback); } }catch(e){} } //reemplazo la imagen por el layout default var img; if(layoutElement) img = xpath(layoutElement); else{ img = contenido(document.documentElement.innerHTML, getImagen, 0); var src = typeof(img)=='string' ? match(img, /src="(.+?)"/i, 1, img) : xpath('@src', img); try{ img = xpath('//img[@src="'+src+'"]'); } catch(e){ img = xpath('//img[@src="'+decodeURI(src)+'"]'); } } var padre = img.parentNode; var div = document.createElement('div'); div.innerHTML = layoutDefault; padre.insertBefore(div, img); padre.removeChild(img); //si estoy dentro de un link, lo elimino while(padre){ if(padre.href){ while(padre.childNodes.length) padre.parentNode.insertBefore(padre.childNodes[0], padre); padre.parentNode.removeChild(padre); break; } else if(padre == document.body) break; padre = padre.parentNode; } get('wcr_btnlayout').innerHTML = 'Use Minimalistic Layout'; } function layoutMinimo(){ var elems = selCss('#AMRBar,#bookmarkData,#bookmarkPop,#navAMRav', document, true); if(elems.length){ var keep = []; for(var i=0; i<elems.length; i++){ var elem = elems[i]; while(elem != document.body){ keep.push(elem); elem = elem.parentNode; } } for(i=0; i<keep.length; i++){ var padre = keep[i].parentNode; var k=0; for(var j=padre.childNodes.length; j; j--){ var n = padre.childNodes[j-1]; for(k=keep.length; k; k--) if(n==keep[k-1]) break; if(!k) padre.removeChild(n); } } var div = document.createElement('div'); div.innerHTML = layoutDefault; document.body.appendChild(div); } else document.body.innerHTML = layoutDefault; } //[/regexp/, grupo], ['xpath'], o 'literal' para encontrar el contenido correspondiente var getImagen = false; var getBack = [/<a [^>]*href *= *"([^\"]+)"([^<]|<[^\/]|<\/[^a])*(back(?!ground)|prev)/i, 1]; var getNext = [/<a [^>]*href *= *"([^\"]+)"([^<]|<[^\/]|<\/[^a])*next/i, 1]; var getFirst = [/<a [^>]*href *= *"([^\"]+)"([^<]|<[^\/]|<\/[^a])*first/i, 1]; var getLast = [/<a [^>]*href *= *"([^\"]+)"([^<]|<[^\/]|<\/[^a])*(last|latest|newest|today)/i, 1]; var getExtras = false; //(opcional) arreglo de getters para meterlos al div extra var bgColor = false, txtColor = false; //(opcionales) fuerza el color de fondo/texto var funcionJs = false; //(opcional) ejecuta una funcion despues de mostrar una pagina var scrollx = confVal('scrollx', 'L'); //para donde se autoscrollea la pagina (L/M/R de la imagen, o pixeles) var scrolly = confVal('scrolly', 'U'); //idem (U/M/D) var extraElement = false; //donde se pone el extra cuando se use el layout completo var fixUrl = false; //f(url, origen (link/img)) q se aplica a los links y src de la imagen, para paginas raras (ej, en sinfest el link en el www apunta al no-www y el no-www redirige al www) var layoutElement = null; //donde se pone todo cuando se usa el layout completo var style = ''; //contenido de un <style/> var onerr = function(url, img, num){ if(num) return null; return {img: img}; }; //f(url de la pag, url de la img, num reintento (0..n)) retorna {url: pag alternativa, img: img alternativa} para reintentar despues de un error //configuracion default del teclado var teclado = defaultSettings.keyboardShortcuts; //achicar o agrandar la imagen para calzar en pantalla var fitSize = confBool('fit', defaultSettings.autozoom); var achw = confBool('achw', defaultSettings.shrinkWidth), achh = confBool('achh', defaultSettings.shrinkHeight); var agrw = confBool('agrw', defaultSettings.expandWidth), agrh = confBool('agrh', defaultSettings.expandHeight); var maxScale = confVal('maxScale', 0) * 1; var minScale = confVal('minScale', 0) * 1; var maxScaleReset = confBool('maxScaleReset', false); var minScaleReset = confBool('minScaleReset', false); var bordex = confVal('bordex', defaultSettings.borderLR); //borde a los lados de la imagen var bordey = confVal('bordey', defaultSettings.borderUD); //borde arriba y abajo var scrollRate = parseInt(confVal('scroll_rate', 50)); //borde a los lados de la imagen var dimScreen = confVal('dim', '0'); var colOK = 'rgb(204, 238, 204)'; //verde var colWait = 'rgb(238, 238, 238)'; //plomo var colLoad = 'rgb(238, 238, 204)'; //amarillo var colFail = 'rgb(238, 204, 204)'; //rojo var cursores_custom = { '1': 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABYdJREFUWIXtll+IXFcdxz+/c86dO3dmJ7ubNsaG1FhZW7fVBpvY1BJ8ia0PrRWpSgNWpT4Ilap5EB+aB0EqvimKYKONVUFBaKiCUCwohtQKeailtQQTa9Jsmmx2Zje7szsze+89v58PM7PJJs0m/kMf8oPDmcM9/L6f8/uePwPX4lr8j8P/M5Mnd0386IbJDZ8aDevfk/fyVp7nM/8tsEvivR+dOPBi+3fWitP2TOtpu/vz2w/9J/KGq5k0cdeWJ7/1w29+fFttJ2rKu5JJet1OAmzMyJJIrIVaVquntRGwhvPWkCAZUMvqWb2yLjQoWG6dWni5OTd9GDg7zC1XEn/HbZv3Pv7sV77xic2fo7QcJ54TnWM8+dz3aMgYlSwQqp5qNSNkniQNVNMqPvGklZQkVAg+kK1PaZ2d5S9/OsJ3d//s9qJYeuWKAJs2b3rkC88+9NRn3/0o3WIJw4EozhzBJ9jKTMOs34OBcv6bGeI9o/VRgg/89uSv+fRNX7w3svz8mhaMj4/f98mf3PPUA+98iNOLU5gAppgKaoZcsXYr+vjgkMwI5ukVPby3JEYcoG8JkIVs+337dv7q/skHeXPxJJhhppgJZoaZoarIVVCYGSEJ1GOGiCcnX/X9LQDSiY98/4N/uP/Oj/nphTN9MeuXdihuMWIYqnLew1U/LjDHjCRJWK9jOBy5La8JcP09T9xxcNeuXbVme4YY44pwjAARi0ZUGBotCIhQxJx23qaIyzjnGUkaVEMGGEmssKgbcebI9fIA1Q99edvBnQ/uuGGhvYBaxNSIGlE1TBU17eua0S16nF08TbMzzUz3DPO9eYzB3jBQjHqos6lxIzdvvI2bdAuiQnm5Cuz4zNbnGruZfOHE70GFIAl1N0Lma5j2Pc+LnNluk7lOk/ZyG439fSA4vPfIRYcq15zXzx3ldDHF224Zo2GjdOLSQDZfBVBZd2t6V5F3KaxEVenEJeZikzKWxKhoqUSNWFQ0Gk48/eUORO2880MMEcHhCBKIUjJfzrGgi6sg3aBPDj3+ysP2WlVd4jAzxPqZBI/D45zgncMFj0sgJA5XEVxiuMSQYIjvN3OGyfBuGPJdjLcaIO/G7qHDe47uqczUkeD6fht4Z7gg+IonqXpCFZLM4+oQRjyh4QgjjsqIJ9Q9PhN8KrjE9aEETM6TXGzT0IICmDvXPXfg8KPHx+98esvXF9N5KAwRj0hEnMMEnAuoi3hzRAwkIAYaFYuCRaAUYqlo0R+H4PH4S1Z/IQBAD5htzp7d/+pj1fVbf/z2Ly2GWRTFe49LDPOgHtQZJY5k4JMZmDqsNKwEzQVfCrpsxFxxiZC6CiqGWyn6pQAAXWD2jRNvfLu6J9nwvn0bdre1hXpFKmDBYd5Q5/q7X9zQYEzBSkXLgBaG9owyNaQHFefIXErpFC9+TQADOkDrry//bW/4anLdtn0b723aNEVYJoY42GggYjgHblABFDQKrhC0AE1BlqFMhATHuFtH1+fMyvyaAEOIJcC9dvDIY9nXbv/pHT/YtOOkHQcP4h1ZSJloT9KcWyBWCtRHokQKKykoiCjRRcqkf3RTaiwkixQ+0tEeAjoUW+s1ccAocOPdj7z/l1u/s+6WY3YU7zyNrMap3aN/P/Kb1/cnWVJ1IWQhUA31UEsynyU1V5PMpz6TzGcuTdcltarPitN/bh1tHTv30szc9H6gyeVew0EosABM/XH/Sw9Xrv/AgZuf2LK55ZtcJ2O8Wdf52U7z53TQCxbiBk0u6of5ikF124Pxlf8R0bdpDMKtH967/Zl6LZUzr84fP/VC8xdTJ6b20T89w1wXXI2rxsMnMgLloK1MuppIgPFBS+lf5HPA7GBV/3JcLQD0K1GlX9I4gPi3xK/F/0X8A9KAi5v8bApEAAAAAElFTkSuQmCC', '2': 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABYRJREFUWIXtlVuMXWUVx39rfXufM9feZnoZ0URISWgVi1KkKg/GJvog4ihG5YHEoCnEBAMPPNUHE0WNL14SH9BYBR/qS4mamHhBIk21IoKpBLBja6RtJu3cZ86cfTn7+77lwz4zHc4gnZgSX7qS7+zvXPb6/771X2sfuBbX4v8ccjWSDA0N7R1729h43/W615eheOX3Z75wNfJuON7/+f0njs3+xGbDJTvZetre+bHdT2703qTn/Y7RrTtvG7lu0z5Smp0l38rbeRvIzFseg7RAWu0yW/ZZnjlclpNXRZ6lN6R7GLTN3DpwB9/84dc/8dD4I4+d+fOr928YIE0Hb/7S0Xv//o4DNzGyYxv5XIkPnsp3KDsloQoUZUFVenweKIocXwQ6uadlC4TK06oWiRZ43+YP8chPHzz06Ph3zp976cLXNgQQK79r/637+fCuu/DBs9hYxEKApsBgt1kU6p0gsrKvX32omM4ugilC5CM7xrn4+ORXHxv/2eTkhckjVwJQ5ywtqoIlP4+3wEwxRfCxK3TlMAMVQdRAlIVynrve/lnmHp/90ROf+uWl+fn5X71hBQA6dGiFFmaB2WIaX3lkAwRmhqoiIt1liChUwp177mb2B3O/OHbPUwdyn//1jQGspB0WiURms2mqquoBEMC6qpcvqoYgiHOrECB1RQrhzvd+3C1/v/3Mz+//4z4oz/x3gFiyHJaIEpkrZqiqDiAUPme5ahFjIHVNhhvDpK4BZhi22iBOQZwADudYBXHecfDgwYH2o/nx3x0++S5g5nUBvJW0QwtT4+zSBBOXXmKydZ62b6MISO21IGzu28z2/l2MDuxkx9AY/WlfLaigoogqqoJThwRBK8cdd98+Vk51jh//7vPvAYoegIQstPlXcZqWLPLMhd+Qt3NUlIZrvNZzjOXOMq3OBGcXTqNOGW4Os3VglG39ozTSRt0TKuQhox2X8VaBGsP3JHtun9/362efOPXBdRVYigsQPJZGEknqk4j02s7l8XOIGCpK4UsutSeZKi7i1KGJ4pySuATnEpxTVBQ6kU17+w8ADaDT8ySU1ROuntYAqX1e7cfX7IVEFVFQdagIqoLiELT+rXUnJVXs5b544vCL9wLpOgBZ899kYrWIM0QVcYY4ut7W3680nwokOETAiQMUQXBiYEIkkiQpjelBTj488XAe8hNAZ50FKxAOR5I4tE8QB5qCSxwkhrgaRp3DpC6RQxBRNDpcVMQUi6DmMAOXOgY7w/zli//+ykK+8CQwD1TrABQllaQuYVNIVHANRZuCJoI2DEkUSQTRFRsMMyFB0ahoUCQosRIIdc4ht4VTD1z83szc1BFgju4ErANw4mhqg0SVRr9SNRXtU5JU0D5BU0GTLoSutgxmRmKKRkGCIl6wjqBBGdYRXjw0ffTcq+e+3RXP12r2AAhDboB+bZAO1m2U9AmuKWijBpAUtLYZEYgYMRpiEQuRGALOO9Jmk1HZyfOHZn47cersl4FZIGPtMK0FEIhZLMj6cirt0GwMYNT+Jao4HA4l9SlpSHDm0OBwnZTRTZs4M/wKuS+xYCRBeKu8hRcemH/25eP/eLAr3u4V53IRUWB0+9ad943s3vLusVtGbixCnpZLVRbyWIbccstDWWUxq/KQ+7bPvKeI3udVXhU3ffSG+647unh9K88IMbBbbuTUQ0un/3Tkb58GzgOLQOwVXwsA0A9sAQapZ1S7n8cu+drrSjID9AOfu+3YzT/WW6ZtjpEwysRhf+EP33ruk8DZrnh4PXEAt2bvqbtzGWh1b1xYsxaBpZ7VAjo2r2n7uebIwMT25tRTPnv6Gy98BuI/ryTeW4H/NVJgG7CV+vFaUs/56qy/2QArEA3qikbqSvqrlPtavLnxH1JHdHLMfy8nAAAAAElFTkSuQmCC', '3': confVal('cursor_custom_3', false), '4': confVal('cursor_custom_4', false), '5': 'iVBORw0KGgoAAAANSUhEUgAAABsAAAApCAYAAADEZlLzAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAZdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjbQg61aAAAC10lEQVRYR+2V7UvTURTHfWYqCP5dvRYsytJCdFagWRkOLU1dayaJNSHRVJYltnQ+Zj7NhyJxYWaZ+ZtmtuWeik2de/52z019kQYzN1/9Dhzuiwv3c7/fc869UVFiiA6IDogOiA6IDogORKWkpODYbIiJiSHYsQHhdDqPBxgdHY3t7W1sbm5GHkiwra0tDqRITU2NnKUEW19f5yCj0Qiz2YzExMTIAAlGIQgCX4PBYORqSDC/388hXq8Xdrudq6PY6dTwTQbB6HBKAhLY4/EgEAhweFjHYtdGUmK1WnlXWiwWuN1uOBwODpZIJOGpIcHoYJPJxFcKUkeKkpOT+RobGxs2hXC5XDzj4+N5zUhNpDoSPp9vrxkSEhL2RuFI9ZqzuNA3a0Dve8NeDQ6wiNeNhvy/unFqxY0bqm6cLFZB1jQKqfIFTlyuw231O5CSv3s7Li6OqyXgodT1f3TgTEkzrjwcQmZVB/LrRyHXCsi9P46MiiGUNOoP6jRsbGzwTEpKCq0TlzzAVdUgLtzpZgdrUNT6GsMWYOIXoOhdQXbNBNKuq6FsGdx34O5IEDCkP29Y8OB0aRukNa9Q0DAJzZIb9Cg9X3LiXHU7zrJLZFd1Iudm/YHqbDZb6L/BA+08sso1yL07gDdMzQoDzbOcDQA6uws69ipN24A5K9tzYh9wR1FoNipaJpEn70HpYz3mXMBXBvrG8gvLNZbfWRq8wA96PYL7YYd6FDWTAi5VMmWVWlQ+0WPa/gfQODaDDFkdCpUDKK4dQVH1Uwzol0NT8K8bCD+Bi+VqSBlQquhCmVqHD+yPJKCyfQanCtXIu9WJIkXL0UB0AcHsx7ORReTf60R6cTPOM2B1vwGPpqyQtc4gq6obORVtePvJdHQYARctQTQNLqCgrh9pslakl3UgQ65FprwL1xp0aHw5Hx7Qrr1GNm8Tyz40j6+htu8zansW0DS2ivHV4KFAvwES0XcvxVHSmgAAAABJRU5ErkJggg==', '6': 'iVBORw0KGgoAAAANSUhEUgAAACUAAAApCAYAAACyXOB4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAZdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjbQg61aAAAC5klEQVRYR+2W2U9TQRSH2cOSkPB3+UyCRlHQEBY1AVExNKAgUGuRSFBIJCCQihKsUFaRrSwaCTWIKCK3VMRWumlaoHSh/TlnpI0S4hPt5eGe5GQe55tvzjkzUVFSSAYkA5IByYBkQDIgGZAMiGogNTUVogIctnlMTAxBHTswOJ3O4wUWHR2N3d1dbG9vHx8wgtrZ2eFgFGlpaeJfJUFtbm5yIKPRCLPZjKSkJHHBCIpCEAS+BgIB8WuMoPb29jiM1+uF3W7ntij2OzPyE4OgCIKSwAjQ4/HA7/dzSFHGRfD6yIzVauVdaLFY4Ha74XA4OGBiYmJka4ygCMBkMvGVgmyRoZSUFL7GxsZG3BhcLhfP+Ph4XlNkR+wOhM/nCxV1QkJCaESIUk/UVodcDa8rGqb/676B93oMLuixaHEdfb2RmYM9HxcXx+0R2EFbt1XvcOJyA/KVLyBrncDJ0kbcaOzDrMF99HAHwLC1tcUzOTk5tFlZiw6ZVaPIuz8FuUZAYdMEsmq6ceXhKM6UtWHooyO8YMFRQWD051K2jyD9ugo5ddNQDBgw/QsYswAlHa8ZqBoX7vThauMIVj0IKxhsNlvo95B7swk5NT04yzY/V9uF56tO0MOkXnWjqHkG+XWvcLq8E2OCJ6xQUfu/UhicwKIVmLMBWvYCae0uLPiBJQZlYPmGWcu7O4zsSjUeaJbCCxWsM2sA+ME213uB72zdYPmF5TeWX1kuuoDyxzoUyPuhaJ+JDNSwbg0ltU9RWj+OYuUwMmUNaJmc54BzdqD6iQ551RpcqlZDPSNEBoqMlSjaUXCrB6eKVVB2/QH6wP6FFSot8hW9yGdAFytVEH6Gt9D/mRJvP5mQW9WJ7Jo+yDrm8WjWitohPc4zoIzSNhTe68Gz8RUIZv5uRi5aXi7hWrMWWfJeZMo1yKjoRrqsA0UNQ2gdWcaKJRBZoODRp9YDaJ1cR33/MuoHP6NtagPTaz4Y/5pPvwHk5XcvVBI4VwAAAABJRU5ErkJggg==' }; var ultimoevt = null; //para acordarme en q mitad de la img estaba parado el cursor la ultima vez var listabm = []; var listabmTodos = null; var elemImagen = null; var slider = 0; // = setInterval(slideshow, secs); var flipControls = false; //invertir flechas/clicks/botones para mangas u otros q se lean al reves var clickImgNavigates = confBool('clickImgNavigates', true); function run_script(){ try{ if(useHistoryAPI && history.pushState){ setEvt(window, 'popstate', function(evt){ if(evt.state && evt.state.wcr_url){ var dir = evt.state.wcr_pos - posActual; if(dir*dir == 1) cambiaPag(dir, true); else redirect(evt.state.wcr_url); } }); } var p = getConfPagina(); if(p){ //si esta deshabilitada esta pag p===null, si no es siempre un objeto link[0] = document.location.href; listabm = getListaBookmarks(); if(goToBookmark && listabm.length == 1 && listabm[0]['url'].split('#')[0] != link[0].split('#')[0] && confirm('Go to last saved page?\n'+ listabm[0]['title']+'\n'+ listabm[0]['url']+ '\n\n(This confirmation dialog can be disabled in the script settings)')){ redirect(listabm[0]['url']); return; } listabmTodos = getListaBookmarksTodos(); if(p.img) getImagen = typeof(p.img) == 'string' ? ['//img[starts-with(@src,"'+p.img.replace(/\|/g, '") or starts-with(@src,"')+'")]'] : p.img; if(p.back) getBack = typeof(p.back) == 'string' ? ['//a['+p.back+']/@href'] : p.back; if(p.next) getNext = typeof(p.next) == 'string' ? ['//a['+p.next+']/@href'] : p.next; if(p.first) getFirst = typeof(p.first) == 'string' ? ['//a['+p.first+']/@href'] : p.first; if(p.last) getLast = typeof(p.last) == 'string' ? ['//a['+p.last+']/@href'] : p.last; if(p.extra) getExtras = p.extra; if(p.bgcol) bgColor = p.bgcol; if(p.txtcol) txtColor = p.txtcol; if(p.js) funcionJs = p.js; if(p.scrollx) scrollx = confVal('scrollx', scrollx, p.scrollx); if(p.scrolly) scrolly = confVal('scrolly', scrolly, p.scrolly); if(p.xelem) extraElement = p.xelem; if(p.layout !== undefined) keepLayout = confKeepLayout(keepLayout, p.layout); if(p.fixurl) fixUrl = p.fixurl; if(p.layelem) layoutElement = p.layelem; if(p.style) style = p.style; if(p.onerr) onerr = p.onerr; if(!getImagen){ //si no tenia conf especial, tratar de reconocer automaticamente la imagen... var next, back, html = document.documentElement.innerHTML; try{next = contenido(html, getNext, 0);}catch(e){} try{back = contenido(html, getBack, 0);}catch(e){} if(next || back){ var subs = ["", "/comics/", "/comic/", "/strips/", "/strip/", "/archives/", "/archive/", "/wp-content/uploads/", "comics", "comic", "strips", "strip", "archives", "archive", "/manga/"]; for(var s = 0; s < subs.length; s++){ var query = '//img[contains(@src, "'+subs[s]+'")]'; try{ var imgs = xpath(query, html, true); if(imgs && imgs.length == 1){ getImagen = [query]; break; } }catch(e){} } } } if(getImagen) iniciar(); else{ if(defaultSettings.showSettingsOnFail) mostrarSettings(); else error('no settings found for this site'); } if(GM_registerMenuCommand){ GM_registerMenuCommand('Webcomic Reader - Disable for this site', function(){ if(confirm('Are you sure you want to disable Webcomic Reader on this site?\n'+ '(It can be re-enabled later with this menu)')){ setData('confpag', 'dis'); redirect(link[posActual]); } }); } } else if(GM_registerMenuCommand){ GM_registerMenuCommand('Webcomic Reader - Enable for this site', function(){ delData('confpag'); redirect(link[posActual]); }); } }catch(e){ error('loadpag: '+e); } } //setear el html nuevo y rellenarlo con los datos de la pag actual, aparte de prefetchear la de adelante y atras function iniciar(){ try{ if(firstRun && confirm( 'This seems to be your first time using Webcomic Reader. '+ 'Do you want to look at the settings?\n'+ '(You can change them at any time with the settings button or the option in the Greasemonkey menu)')) mostrarSettings(); setear(document.documentElement.innerHTML, 0, 0); //seteo el contenido de la pag inicial if(imagen[0] == null) return; try{ var first = getLink(document.documentElement.innerHTML, getFirst, 0); } catch(e){ error('first: '+e); } try{ var last = getLink(document.documentElement.innerHTML, getLast, 0); } catch(e){ error('last: '+e); } if(keepLayout) layoutIntacto(); else layoutMinimo(); var sombrear = dimScreen=='I' ? 'wcr_imagen' : (dimScreen=='S' ? 'wcr_div' : ''); if(sombrear){ var sombra = document.createElement('div'); sombra.setAttribute('style', 'opacity:0.8; position:fixed; z-index:2322; background:#000; top:0; left:0; right:0; bottom:0; pointer-events:none;'); var sombreado = get(sombrear); sombreado.style.position = 'relative'; sombreado.style.zIndex = '2323'; sombreado.parentNode.insertBefore(sombra, sombreado); } if(!showButtons) get('wcr_botones').style.display = 'none'; //dejar de usar scroll* para el borde, usar borde* if(typeof(scrollx)=='number' && scrollx){ bordex = scrollx<0 ? -scrollx : scrollx; scrollx = scrollx<0 ? 'R' : 'L'; } if(typeof(scrolly)=='number' && scrolly){ bordey = scrolly<0 ? -scrolly : scrolly; scrolly = scrolly<0 ? 'D' : 'U'; } if(scrollx == 'R' && confBool('flipControlsManga', false)){ flipControls = true; } elemImagen = get('wcr_imagen'); if(bordex){ elemImagen.style.paddingLeft = elemImagen.style.paddingRight = bordex + 'px'; } if(bordey){ get('wcr_div').style.paddingBottom = get('wcr_div').style.paddingTop = bordey + 'px'; } if(first) get('wcr_first').href = first; else get('wcr_first').style.visibility = 'hidden'; if(last) get('wcr_last').href = last; else get('wcr_last').style.visibility = 'hidden'; if(bgColor){ get('wcr_div').style.backgroundImage = 'none'; get('wcr_div').style.backgroundColor = bgColor; } if(txtColor) get('wcr_div').style.color = txtColor; if(style) get('wcr_style').innerHTML += style; if(fitSize) get('wcr_btnfit').innerHTML = 'Disable Fit-to-screen'; for(var i=0;i<listabm.length;i++) addLista(listabm[i]); if(listabmTodos){ var html = '<table align="center">'; for(var sitio in listabmTodos){ var lista = listabmTodos[sitio]; html+='<tr><td rowspan="'+lista.length+'">'+sitio+'</td>'; for(i=0; i<lista.length; i++){ if(i) html+='<tr>'; html+='<td><a href="'+lista[i].url+'" title="'+lista[i].url+'">'+lista[i].title+'</a></td></tr>'; } } html+='</table>'; get('wcr_listabm_todos').innerHTML = html; setEvt('wcr_toggle_bm', 'click', function(e){ var lista = get('wcr_listabm_todos'); lista.style.display = lista.style.display == 'none' ? '' : 'none'; e.stopPropagation(); e.preventDefault(); }); get('wcr_div_listabm_todos').style.display = ''; } getUltima(); teclado = getTeclas(); setEvt(window, 'keydown', teclaHandler); setEvt(window, 'resize', fitImagen); setEvt('wcr_btn1', 'click', btnnext); setEvt('wcr_btn-1', 'click', btnback); if(clickImgNavigates){ setEvt(elemImagen, 'click', imgClick); setEvt(elemImagen, 'mousemove', imgCursor); } setEvt(elemImagen, 'load', function(){ fitImagen(); scrollear(); }); setEvt('wcr_btnaddbm', 'click', addBookmark); setEvt('wcr_btnfit', 'click', toggleConfFit); setEvt('wcr_btnlayout', 'click', toggleConfKeepLayout); setEvt('wcr_btnslide', 'click', slideshow); setEvt('wcr_btnsettings', 'click', mostrarSettings); //setEvt(window, 'touchstart', touchstart); //setEvt(window, 'touchend', touchend); var imgelem = document.createElement('img'); imgelem.id = 'wcr_imagen0'; imgelem.src = imagen[0]; get('wcr_imagenes').appendChild(imgelem); agregarLink(0); cambiaPag(0); prefetch(1, 1, prefetchSizeStart[1]); if(link[1] || prefetchNoNext){ prefetch(-1, -1, prefetchSizeStart[0]); } else{ disableBtn(-1, false); setCol(-1, colOK); imagen[-1] = null; } } catch(e){ error('init: '+e); if(defaultSettings.showSettingsOnFail) mostrarSettings(); } } //setea la imagen y el link como vars globales para actualizar function setear(html, pos, dir){ try{ var pag = document.createElement('div'); pag.innerHTML = html; var img = contenido(pag, getImagen, pos); var src; if(typeof(img)=='object'){ src = xpath('@src', img); //img.src absolutiza la url basandose en la pag inicial imgTitle[pos] = img.title; } else{//getImagen es regexp q retorna el elemento <img .../> o directamente su url src = match(img, /src *= *"(.+?)"/i, 1, img); imgTitle[pos] = match(img, /title *= *"(.+?)"/i, 1, null); } if(fixUrl) src = fixUrl(src, true, false, pos); imagen[pos] = absUrl(src, pos); if(pos){ var poslink = pos+dir; try{ link[poslink] = getLink(pag, dir > 0 ? getNext : getBack, pos); } catch(e){ link[poslink] = null; error('set['+pos+']/link['+poslink+']: '+e); } } else{ try{ link[1] = getLink(pag, getNext, pos); } catch(e){ link[1] = null; error('set['+pos+']/link[1]: '+e); } try{ link[-1] = getLink(pag, getBack, pos); } catch(e){ link[-1] = null; error('set['+pos+']/link[-1]: '+e); } } try{ titulo[pos] = xpath('//title', pag).innerHTML; } catch(ex){ try{ titulo[pos] = match(html, /<title>(.+?)<\/title>/i, 1); } catch(e){ error('set['+pos+']/titulo: '+e); titulo[pos] = link[pos]; } } extra[pos] = ''; if(getExtras){ for(var i=0;i<getExtras.length;i++){ try{ var x = contenido(pag, getExtras[i], pos); if(typeof(x)=='object') x = outerHTML(x); extra[pos] += x; }catch(e){error('set['+pos+']/extras['+i+']: '+e);} } } if(dir) get('wcr_btn'+dir).innerHTML = (dir>0?'Next':'Back')+' ('+((pos-posActual)*dir)+(link[pos+dir]?'':'!')+')'; } catch(e){ error('set['+pos+']: '+e); imagen[pos] = null; if(dir){ get('wcr_btn'+dir).innerHTML = (dir>0?'Next':'Back')+' ('+((pos-posActual)*dir-1)+'...)'; if((pos-posActual)*dir == 1) get('wcr_btn'+dir).title = link[pos] + ' (image not found)'; } } } //saca el link, y si me llega un <a> le saco el href function getLink(pag, getter, pos){ var linkpag = contenido(pag, getter, pos); if(linkpag && typeof(linkpag)=='object' && !linkpag.href) //array[url, postdata] return linkpag; if(linkpag && linkpag.href) //<a href=...>...<a/> linkpag = linkpag.href; if(fixUrl) linkpag = fixUrl(linkpag, false, true, pos); linkpag = absUrl(linkpag, pos); if(linkpag == link[pos]) return null; return linkpag; } //convierte un url relativo en absoluto basandose en el url de una posicion function absUrl(url, pos){ if(!url.indexOf('javascript:')) return null; url = decodeURI(url.replace(/(^|[^#])#([^#].*|$)/, '$1').replace(/^\.\//, '').replace(/&/g,'&')).trim(); if(!url) return null; if(!url.match(/^\w+:/)){ //path relativo var base = link[pos]; try{ base = xpath('//base/@href'); } catch(e){} if(url.indexOf('/') == 0){ if(url.indexOf('//') == 0) url = base.match(/^\w+:/) + url; else url = base.match(/^\w+:\/\/[^\/]+/) + url; } else if(url.indexOf('##') == 0) url = base.split('##')[0] + url; else{ var ipars = base.indexOf('?'); if(ipars < 0) ipars = base.length; if(url[0] == '?') return base.substr(0, ipars) + url; base = base.substr(0, base.lastIndexOf('/', ipars)); while(url.indexOf('../') == 0){ url = url.substr(3); if(!base.match(/:\/\/[^\/]+$/)) base = base.substr(0, base.lastIndexOf('/')); } url = base + '/' + url; } } return url; } //muestra la imagen q viene en esta direccion y prefetchea el link futuro function cambiaPag(dir, poppedState, slidden){ try{ if(dir && imagenOK[posActual+dir]===undefined && imagen[posActual+dir]!==null && (!moveWhileLoading || imagen[posActual+dir]===undefined)) return; if(imagen[posActual+dir]===null && link[posActual+dir] || imagenOK[posActual+dir]===false){ redirect(link[posActual+dir]); return; } posActual+=dir; //seteo el contenido actual document.title = titulo[posActual]; if(imagen64[posActual]) get('wcr_imagen').src = imagen64[posActual]; else get('wcr_imagen').src = imagen[posActual]; get('wcr_imagen').title = imgTitle[posActual]; if(get('wcr_title')) get('wcr_title').innerHTML = imgTitle[posActual]; get('wcr_btnaddbm').title = link[posActual]; get('wcr_btn1').title = link[posActual + 1] + (imagen[posActual + 1] === null ? ' (image not found)' : ''); get('wcr_btn-1').title = link[posActual - 1] + (imagen[posActual - 1] === null ? ' (image not found)' : ''); var xel = get('wcr_extra'); if(keepLayout && extraElement){ try{ xel = xpath(extraElement); } catch(e){ error('extraElement: ' + e); } } if(xel) xel.innerHTML = extra[posActual]; var maxok; for(maxok=posActual; imagen[maxok+1]; maxok++) continue; get('wcr_btn1').innerHTML = 'Next ('+(maxok-posActual)+(link[maxok+1]?(imagen[maxok+1]===null?'...':''):'!')+')'; for(maxok=posActual; imagen[maxok-1]; maxok--) continue; get('wcr_btn-1').innerHTML = 'Back ('+(posActual-maxok)+(link[maxok-1]?(imagen[maxok-1]===null?'...':''):'!')+')'; if(useHistoryAPI && history.pushState && !poppedState){ if(dir) history.pushState( {wcr_url: link[posActual], wcr_pos: posActual}, titulo[posActual], link[posActual]); else history.replaceState( {wcr_url: link[posActual], wcr_pos: posActual}, titulo[posActual], link[posActual]); } try{ if(funcionJs) funcionJs(dir); } catch(e){ error('js('+dir+'): '+e); } saveUltima(); setCursores(); if(slider && !slidden) slideshow(); if(dir){ var pd = posActual+dir; //(des)habilito los botones segun corresponda setCol(-dir, colOK); if(!get('wcr_imagen'+pd) && imagen[pd]!==null) disableBtn(dir, true); disableBtn(-dir, false); var posAtras = posActual-dir*(maximgs[-dir]+1); var atras = get('wcr_imagen'+posAtras); if(atras){ atras.parentNode.removeChild(atras); imagen64[posAtras] = null; } var adelante = posActual+dir*maximgs[dir]; if(imagen[adelante] && !get('wcr_imagen'+adelante)){ cargarImagen(adelante); } //prefetcheo la pag q viene en esta direccion prefetch(dir, pd, prefetchSize[dir>0?1:0]); } } catch(e){ error('cambia['+dir+']: '+e); } } //si la conf lo pide, ajustar la imagen al tamaño de la ventana function fitImagen(reintentando){ var size = winsize(); var wihi = imgsize(); var wi = wihi.wi, hi = wihi.hi; var ww = size.w - 2*bordex; var hw = size.h - 2*bordey; if(fitSize){ if(!achw && !agrw && !achh && !agrh){ achw = achh = true; scrollear(); mostrarSettingsZoom(); } if(achw && wi>ww || agrw && wi<ww){ hi = hi*ww/wi; wi = ww; } if(achh && hi>hw || agrh && hi<hw){ wi = wi*hw/hi; hi = hw; if(achw && wi>ww){ hi = hi*ww/wi; wi = ww; } } var scale = wi/wihi.wi * 100; if(maxScale && scale > maxScale){ if(maxScaleReset){ wi = wihi.wi; hi = wihi.hi; } else{ wi = wihi.wi*maxScale/100; hi = wihi.hi*maxScale/100; } } else if(minScale && scale < minScale){ if(minScaleReset){ wi = wihi.wi; hi = wihi.hi; } else{ wi = wihi.wi*minScale/100; hi = wihi.hi*minScale/100; } } } if(wi && hi){ cambiarPorte(wi, hi); //para ver si (des)aparecen las scrollbars y hay q recalcular //"reintentando" para evitar posibles loops infinitos if(!reintentando && size.p!=winsize().p) fitImagen(true); } else get('wcr_imagen').setAttribute('style', ''); } //obtiene el porte original de la imagen function imgsize(){ var img = get('wcr_imagen'); if(img.naturalWidth) return {wi: img.naturalWidth, hi: img.naturalHeight}; img = get('wcr_imagen'+posActual); return img ? {wi: img.width, hi: img.height} : {wi:0, hi:0}; } //cambia el porte de la imagen por css function cambiarPorte(wi, hi){ get('wcr_imagen').style.width = wi+'px'; get('wcr_imagen').style.height = hi+'px'; } //scrollea al punto inicial de la imagen function scrollear(){ var left = 0; var top = 0; var img = elemImagen; var offset = img; while(offset){ left += offset.offsetLeft; top += offset.offsetTop; offset = offset.offsetParent; } var size = winsize(); var x = scrollx; if(x == 'L') x = left; else if(x == 'R') x = left + img.offsetWidth - size.w; else if(x == 'M') x = left + (img.offsetWidth - size.w)/2; else if(typeof(x) == 'function') x = x(); var y = scrolly; if(y == 'U') y = top - bordey; else if(y == 'D') y = top + img.offsetHeight - size.h + bordey; else if(y == 'M') y = top + (img.offsetHeight - size.h)/2; else if(typeof(y) == 'function') y = y(); scroll(x, y); } //calcula el porte de la ventana sin contar scrollbars function winsize(){ var div = document.createElement('div'); div.style.width = div.style.height = '100%'; div.style.left = div.style.top = '0'; div.style.position = 'fixed'; document.body.appendChild(div); var s = {w: div.clientWidth, h: div.clientHeight}; s.p = s.w*1000+s.h; document.body.removeChild(div); return s; } //avanza solo las paginas cada cierto tiempo function slideshow(){ if(slider){ clearInterval(slider); slider = 0; get('wcr_btnslide').innerHTML = 'Start Slideshow'; } else{ var secs = Number(prompt('Enter the number of seconds for turning a page (enter a negative number to advance backwards)\n\n'+ 'Press the slideshow button, the ESC key or manually turn pages to stop', 10)); if(secs){ var dir = secs > 0 ? 1 : -1; secs *= dir*1000; slider = setInterval(function(){cambiaPag(dir, false, true);}, secs); get('wcr_btnslide').innerHTML = 'Stop Slideshow'; } } } //prefetchea la pagina q viene en la direccion dir (+/-1) function prefetch(dir, pos, prof, reintento){ if(dir*pos<0 || !prof) return; //si estoy tratando de prefetchear el lado del q vengo, o si ya termine de profundizar var esSgte = pos==posActual+dir; if(!link[pos]){ //link null o a si mismo, cuenta como fail if(!esSgte) return; //si no es el siguiente el fallado, no faileo el boton setCol(dir, colFail); disableBtn(dir, true); return; } //ya pase por aca if(pos*dir <= prefetcheado[dir]*dir && !reintento) return prefetch(dir, pos+dir, prof-1); prefetcheado[dir] = pos; setCol(dir, colWait); //boton gris mientras no ha loadeado if(esSgte) disableBtn(dir, true); //y si estoy loadeando el sgte, lo deshabilito var url = link[pos]; var meth = 'GET'; var pars = null; if(typeof(url)=='object'){ pars = url[1]; url = url[0]; meth = 'POST'; } var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange=function(){ if (xmlhttp.readyState == 4){ if(xmlhttp.status == 200){ try{ setear(xmlhttp.responseText, pos, dir); if(!esSgte || !imagen[pos]) disableBtn(dir, false); //si el otro estaba rojo no lo habilito disableBtn(-dir, get('wcr_btn'+(-dir)).style.backgroundColor == colFail); if(imagen[pos]){ agregarLink(pos); setCol(dir, colLoad); //boton amarillo mientras prefetchea cargarImagen(pos, dir, prof, reintento); } else setCol(dir, colOK); } catch(e){ error('pre['+pos+']: '+e); } } else{ prefetcheado[dir] = pos-dir; //hago q pase de nuevo por aca if(esSgte){ disableBtn(dir, true); disableBtn(-dir, get('wcr_btn'+(-dir)).style.backgroundColor == colFail); setCol(dir, colFail); } error('pre['+pos+']: status '+xmlhttp.status+' ('+url+(pars?' ; '+pars:'')+')'); } setCursores(); } }; try{ xmlhttp.open(meth, url, true); try{ var enc = xpath('//meta/@content'); xmlhttp.overrideMimeType(enc); }catch(e){} if(pars){ xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlhttp.setRequestHeader("Content-length", pars.length); xmlhttp.setRequestHeader("Connection", "close"); } xmlhttp.send(pars); } catch(e){ if(e.toString().indexOf('Component returned failure code: 0x805e000a') > -1) alert('Error when trying to load '+url+'\nIf you\'re using AdBlock Plus, NoScript or some other extension that might be blocking the request, temporarily disable it (or whitelist this page) and try again'); error('ajax '+url+(pars?' ; '+pars:'')+': '+e); } } function cargarImagen(pos, dir, prof, reintento){ var img = document.createElement('img'); img.id = 'wcr_imagen'+pos; get('wcr_imagenes').appendChild(img); function loadOK(){ if(!dir) return; imagenOK[pos] = true; setCursores(); setCol(dir, colOK); prefetch(dir, pos+dir, prof-1); } function loadFail(){ if(onerr){ reintento = reintento || 0; var nueva = onerr(link[pos], imagen[pos], reintento, pos); error('loadFail('+pos+','+dir+','+prof+','+reintento+') - load: '+JSON.stringify(nueva)); if(nueva){ if(nueva.img){ imagen[pos] = nueva.img; cargarImagen(pos, dir, prof, reintento+1); } else{ link[pos] = nueva.url; prefetch(dir, pos, prof, reintento+1); } return; } } if(!dir) return; imagenOK[pos] = false; setCursores(); setCol(dir, colFail); } if(usarb64 && GM_xmlhttpRequest){ setTimeout(function() { GM_xmlhttpRequest({ method: 'GET', url: imagen[pos], overrideMimeType: 'text/plain; charset=x-user-defined', onload: function(resp) { imagen64[pos] = 'data:'+ resp.responseHeaders.match(/Content-Type: (.*)/i)[1]+ ';base64,'+btoa(resp.responseText.replace(/[\u0100-\uffff]/g, function(c) { return String.fromCharCode(c.charCodeAt(0) & 0xff); })); loadOK(); }, onerror: loadFail, onabort: loadFail }); }, 0); return; } img.src = imagen[pos]; //ok, boton verde setEvt(img, 'load' , loadOK); //nok, boton rojo setEvt(img, 'error', loadFail); setEvt(img, 'abort', loadFail); } //agrega un link a la imagen cargada para usarlo con DownThemAll function agregarLink(pos){ var linkimg = document.createElement('a'); linkimg.href = imagen[pos]; linkimg.textContent = 'wcrimg ' + pos + ' - ' + imagen[pos].match(/\/([^\/]+$)/)[1]; var cont = get('wcr_links_imgs'); if(pos<0) cont.insertBefore(linkimg, cont.firstChild); else cont.appendChild(linkimg); } //getElementById function get(id){ return document.getElementById(id); } //agrega la funcion fun al evento evt del elemento get(id) function setEvt(elem, evt, fun){ if(typeof(elem) == 'string') elem = get(elem); if(!elem) return; if(isArray(elem)) for(var i=0; i<elem.length; i++) setEvt(elem[i], evt, fun); else if(isArray(evt)) for(i=0; i<evt.length; i++) setEvt(elem, evt[i], fun); else elem.addEventListener(evt, fun, true); } //dice si el objeto es un array (o nodelist, lo q retorna querySelectorAll) function isArray(o){ return '[object Array];[object NodeList]'.indexOf(Object.prototype.toString.call(o)) >= 0; } //si puede retorna s.match(re)[g], si no puede y se paso def, retorna def, y si no tira una excepcion function match(s, re, g, def){ var r = s.match(re); if(r && r.length > g) return r[g]; if(def!==undefined) return def; throw 'match: '+re+'['+g+']'; } //evalua una query xpath sobre un elemento (o su html), si se pide explicitamente se devuelve el arreglo de resultados, si no el primero q encuentre function xpath(query, elem, arreglo){ if(!elem) elem = document; if(!isFirefox() && elem!=document && query.charAt(0)!='.') query = (query.charAt(0)=='/' ? '.' : './') + query; if(typeof(elem)=='string'){ var div = document.createElement('div'); div.innerHTML = elem; elem = div; } var res = document.evaluate(query, elem, null, arreglo ? XPathResult.ORDERED_NODE_SNAPSHOT_TYPE : XPathResult.FIRST_ORDERED_NODE_TYPE, null); if(arreglo && !res.snapshotLength || !arreglo && !res.singleNodeValue) throw 'xpath: '+query; if(!arreglo){ res = res.singleNodeValue; //si es un atributo retorno el valor, si no retorno el nodo if(query.match(/@[\w-]+$/)) return res.value; return res; } var arr = new Array(); for (i = 0; i < res.snapshotLength; i++) arr.push(res.snapshotItem(i)); return arr; } //evalua una query css sobre un elemento (o su html), si se pide explicitamente se devuelve el arreglo de resultados, si no el primero q encuentre function selCss(query, elem, arreglo){ if(!elem) elem = document; if(typeof(elem)=='string'){ var div = document.createElement('div'); div.innerHTML = elem; elem = div; } if(arreglo) return elem.querySelectorAll(query); var resp = elem.querySelector(query); if(resp === null) throw 'selcss: '+query; return resp; } //busca el contenido definido por el getter dentro del elemento elem //el getter puede ser 'literal', [/regexp/, numgrupo], ['xpath q retorna arreglo', 'pegamento'], o ['xpath'] function contenido(elem, getter, pos){ //'texto plano' if(typeof(getter)=='string') return getter; //function((string)elem, pos) if(typeof(getter)=='function'){ if(typeof(elem)!='string') elem = elem.innerHTML; return getter(elem, pos); } //[/regexp/, grupo] if(typeof(getter[0])!='string' && !isArray(getter[0])){ if(typeof(elem)!='string') elem = elem.innerHTML; return match(elem, getter[0], getter[1]); } var arr; //[['query css', etc?]] if(typeof(getter[0])!='string'){ getter = getter[0]; arr = selCss(getter[0], elem, getter.length > 1); } //['query xpath', etc?] else arr = xpath(getter[0], elem, getter.length > 1); //['query'] if(getter.length == 1) return arr; //['query q retorna un arreglo', 'string entre los elementos del arreglo', idx inicio?, idx fin?] var inicio = getter.length > 2 ? getter[2] : 0; if(inicio < 0) inicio += arr.length; if(inicio < 0) inicio = 0; var fin = getter.length > 3 ? getter[3] : arr.length; if(fin < 0) fin += arr.length; var res = []; for(var i=inicio; i<arr.length && i<fin; i++) res.push(outerHTML(arr[i])); return res.join(getter[1]); } //retorna el outerHTML de un elemento function outerHTML(elem){ var div = document.createElement('div'); div.appendChild(elem.cloneNode(true)); return div.innerHTML; } //setea el color del boton correspondiente a una direccion function setCol(dir, col){ get('wcr_btn' + dir).style.backgroundColor = col; } //(des)habilita los botones back/next, y desfocusea los deshabilitados para no perder el control function disableBtn(dir, dis){ get('wcr_btn'+dir).disabled = dis; if(dis) get('wcr_btn'+dir).blur(); } //manejar el tecleo function teclaHandler(evt){ var wcr_settings = get('wcr_settings'); if(wcr_settings) { if(evt.keyCode == 27) document.body.removeChild(wcr_settings); if(tabSettingActual != 'wcr_teclas') evt.stopPropagation(); return; } //no toco nada si estoy escribiendo if(evt.target.tagName == 'INPUT' && evt.target.type == 'text' || evt.target.tagName == 'TEXTAREA') return; var left = document.documentElement.scrollLeft; if(!left) left = document.body.scrollLeft; var top = document.documentElement.scrollTop; if(!top) top = document.body.scrollTop; if(checkTecla('back', evt)) btnback(evt); else if(checkTecla('next', evt)) btnnext(evt); else if(checkTecla('scroll_left', evt)) scroll(left - scrollRate, top); else if(checkTecla('scroll_right', evt)) scroll(left + scrollRate, top); else if(checkTecla('scroll_up', evt)) scroll(left, top - scrollRate); else if(checkTecla('scroll_down', evt)) scroll(left, top + scrollRate); else if(checkTecla('reload', evt)) redirect(link[posActual]); else if(checkTecla('set_bm', evt)) setBookmark(); else if(checkTecla('add_bm', evt)) addBookmark(); else if(checkTecla('layout', evt)) toggleConfKeepLayout(); else if(checkTecla('fit', evt)) toggleConfFit(); else if(checkTecla('debug_mode', evt)) toggleConfDebug(); else if(checkTecla('debug_info', evt)) debugInfo(); else if(checkTecla('botones', evt)) toggleConfShowButtons(); else if(checkTecla('slide', evt)) slideshow(); else if(evt.keyCode == 116 && !evt.ctrlKey) redirect(link[posActual]); //F5 else if(evt.keyCode == 27 && !evt.ctrlKey && slider) slideshow(); //ESC para el slideshow else return; evt.stopPropagation(); evt.preventDefault(); //frena el scrolleo con las flechas o el reloadeo original con f5 } //revisa si se apreto la tecla configurada function checkTecla(nombre, evt){ var t = teclado[nombre]; if(!t) return false; if(!isArray(t)) t = [t]; var ats = ['keyCode', 'ctrlKey', 'shiftKey', 'altKey']; for(var i=0; i<t.length; i++){ var ok = true; for(var a=0; a<ats.length; a++){ if(t[i][ats[a]] != evt[ats[a]]){ if(ats[a] == 'keyCode'){ //- y + en chrome, ff15+ y ff14- if(mismaTecla([189, 173, 109], t[i], evt) || mismaTecla([189, 173, 109], t[i], evt)) continue; } ok = false; break; } } if(ok) return true; } return false; } //compara distintos keycodes para una misma tecla xq los browsers no tienen xq estar de acuerdo con lo que piensan function mismaTecla(eqs, t, e){ return eqs.indexOf(parseInt(t.keyCode)) >= 0 && eqs.indexOf(parseInt(e.keyCode)) >= 0; } //alert con url y img.src de las primeras pags, las alrededor de la actual, y las ultimas function debugInfo(){ if(!debug) return; var s = '', min, max; for(min=posActual; link[min-1]!==undefined; min--) continue; s+= mostrarLinks(min, min+3); if(min+4 < posActual-3) s+= '...\n' + mostrarLinks(posActual-3, posActual+3); else s+= mostrarLinks(min+4, posActual+3); for(max=posActual; link[max+1]!==undefined; max++) continue; if(posActual+4 < max-3) s+= '...\n' + mostrarLinks(max-3, max); else s+= mostrarLinks(posActual+4, max); alert(s); } //retorna una lista con la url de cada pagina y el src de su imagen function mostrarLinks(inicio, fin){ var s = ''; for(var i=inicio; i<=fin && link[i]!==undefined; i++){ if(i==posActual) s+= '\n<<--actual-->>\n';//'<actual>\n\t'; s += i + ':\t' + (link[i] && typeof(link[i])=='object' ? link[i][0]+' ; '+link[i][1] : link[i]) + '\n\t' + imagen[i] + '\n'; if(i==posActual) s+= '<<--actual-->>\n\n';//'</actual>\n'; } return s; } //onclick next, avanza function btnnext(evt){ cambiaPag(flipControls ? -1 : 1); evt.stopPropagation(); evt.preventDefault(); return false; } //onclick back, retrocede function btnback(evt){ cambiaPag(flipControls ? 1 : -1); evt.stopPropagation(); evt.preventDefault(); return false; } //para recordar donde parten los swipes var touchpos = {x:0, y:0, t:0}; //graba el punto de partida de un swipe function touchstart(evt){ var touches = evt.originalEvent.touches; if (touches && touches.length) { touchpos = { x: touches[0].pageX, y: touches[0].pageY, t: new Date().getTime() }; } } //si es rapido, horizontal y de >50px, se considera un swipe y cambio de pag function touchend(evt){ var touches = evt.originalEvent.touches; if (touches && touches.length) { var dx = touches[0].pageX - touchpos.x; var dy = touches[0].pageY - touchpos.y; var dt = new Date().getTime() - touchpos.t; if(dt < 500 && Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 50){ if(dx > 0) btnback(evt); else btnnext(evt); } } } //segun la mitad de la imagen donde se clickeo, avanza o retrocede function imgClick(evt){ return imgDerecha(evt) ? btnnext(evt) : btnback(evt); } //retorna true si el cursor esta sobre la mitad derecha de la imagen function imgDerecha(evt){ if(!leftImageClick) return true; var img = evt.currentTarget; var left = 0; var offset = img; while(offset){ left += offset.offsetLeft; offset = offset.offsetParent; } if(img.style.paddingLeft) left += Number(img.style.paddingLeft.match(/\d+/)[0]); left -= window.scrollX; var x = evt.clientX - left; var w = img.width || img.offsetWidth; return x/w>0.5; } //muestra el cursor correspondiente al estado de la prox pag segun este en la mitad izq o der de la imagen function imgCursor(evt){ if(!evt || !evt.currentTarget) return; var img = evt.currentTarget; var dir = imgDerecha(evt) ? 1 : -1; img.style.cursor = cursor(dir, 'img'); ultimoevt = evt; } //setea el cursor de la imagen y los botones function setCursores(){ imgCursor(ultimoevt); get('wcr_btn-1').style.cursor = cursor(-1, 'btns'); get('wcr_btn1').style.cursor = cursor(1, 'btns'); } //retorna el cursor correspondiente segun el estado de la proxima pag (y aprovecha de (des)habilitar el boton) function cursor(dir, elem){ if(!link[posActual+dir]){ //no hay link disableBtn(dir, true); return confCursor('nolink', elem, 'not-allowed'); } if(imagen[posActual+dir]===null || imagenOK[posActual+dir]===false){ //no hay img disableBtn(dir, false); return confCursor('noimg', elem, 'pointer'); } if(imagenOK[posActual+dir]===undefined){ //cargando img disableBtn(dir, !moveWhileLoading); return confCursor('loading', elem, 'progress'); } disableBtn(dir, false); return confCursor(dir>0 ? 'next' : 'back', elem, dir>0 ? 2 : 1); } //redirige a una url o postea si es q es necesario function redirect(url){ if(!url){ document.location.reload(); return; } if(typeof(url)=='string'){ document.location.href = url.split('#')[0]; return; } form = document.createElement('form'); form.method = 'POST'; form.action = url[0]; form.name = 'jsform'; var pars = url[1].split('&'); for(var i=0; i<pars.length; i++){ var input = document.createElement('input'); input.type='hidden'; var par = pars[i].split('='); input.name = par[0]; input.id = par[0]; input.value = par[1]; form.appendChild(input); } document.body.appendChild(form); form.submit(); } //mostrar mensajes de error en modo debug function error(msg){ msg = (link[posActual] || document.location.href) + '\n\n' + msg; if(console && console.log) console.log(msg); if(debug) alert(msg); } //ejecutar un script fuera del sandbox function exec(script){ document.location.href = 'javascript:(function(){' + script + '})();'; } //ejecuta un request sincrono y retorna el html function syncRequest(url, pos){ var request = new XMLHttpRequest(); request.open('GET', absUrl(url, pos), false); request.send(null); if(request.status === 200) return request.responseText; throw request.statusText; } //si se especifica no se toca, si no se usa el host sin el "www." function dominioData(dominio){ if(!dominio) return document.location.host.replace(/^www\./, ''); return dominio; } //guarda la configuracion usando una pura variable (json) function setData(key, val, dominio){ var data = JSON.parse(GM_getValue('wcr.settings', '{}')); dominio = dominioData(dominio); if(data[dominio] === undefined) data[dominio] = {}; if(key) data[dominio][key] = val; else data[dominio] = val; dataCache = data; return GM_setValue('wcr.settings', JSON.stringify(data)); } //recupera un valor de la configuracion, y si esta en el formato viejo lo guarda en el nuevo y bora el viejo function getData(key, defval, dominio, reloadCache){ if(reloadCache || !dataCache) dataCache = JSON.parse(GM_getValue('wcr.settings', '{}')); var data = dataCache; dominio = dominioData(dominio); var val; try{ val = key ? data[dominio][key] : data[dominio]; } catch(e){} if(val === undefined) val = defval; return val; } //borra un valor de la configuracion function delData(key, dominio){ var data = JSON.parse(GM_getValue('wcr.settings', '{}')); dominio = dominioData(dominio); if(data[dominio]){ if(key) delete data[dominio][key]; if(!key || JSON.stringify(data[dominio]) == '{}') delete data[dominio]; } var json = JSON.stringify(data); if(json == '{}') GM_deleteValue('wcr.settings'); else GM_setValue('wcr.settings', json); dataCache = data; } //retorna la ultima pagina visitada para este sitio function getUltima(){ var pag = getData('last', ''); if(pag == '') return; //convierte el formato viejo if(typeof(pag) == 'string'){ var pags = pag.split('|wcrbmtit|'); pag = {url: pags[0], title: pags[1]}; } get('wcr_ultimavisita').innerHTML = '<br/>Last visited: <a href="'+pag['url']+'" title="'+pag['url']+'">'+pag['title']+'</a>'; } //graba la ultima pagina visitada para este sitio function saveUltima(){ setData('last', {url: link[posActual], title: titulo[posActual]}); } //retorna una lista con las pags bookmarkeadas para este sitio en formato [{url:'...', title:'...'}] function getListaBookmarks(reloadCache){ var lista = getData('bm', '', '', reloadCache); if(lista == '') return []; //convierte el formato viejo if(typeof(lista) == 'string'){ lista = lista.split('|wcrbm|'); for(var i=0;i<lista.length;i++){ var pags = lista[i].split('|wcrbmtit|'); lista[i] = {url: pags[0], title: pags[1]}; } } return lista; } //retorna una lista con las pags bookmarkeadas de todos los sitios en formato {'sitio1': [...], ...} function getListaBookmarksTodos(reloadCache){ var listaTodos = {}, lista = null, este = dominioData(); for(var sitio in dataCache){ if(!dataCache[sitio].bm || sitio == este) continue; lista = dataCache[sitio].bm //convierte el formato viejo if(typeof(lista) == 'string'){ lista = lista.split('|wcrbm|'); for(var i=0;i<lista.length;i++){ var pags = lista[i].split('|wcrbmtit|'); lista[i] = {url: pags[0], title: pags[1]}; } } listaTodos[sitio] = lista; } return lista ? listaTodos : null; } //graba la lista de pags bookmarkeadas function saveListaBookmarks(lista){ if(lista.length) setData('bm', lista); else delData('bm'); } //agrega un item al div con los bookmarks function addLista(item){ var a = document.createElement('a'); a.href = a.title = item['url']; a.innerHTML = item['title']+' '; var btndel = document.createElement('button'); btndel.innerHTML = 'Delete'; btndel.style.backgroundColor = '#f00'; setEvt(btndel, 'click', delBookmark); var div = document.createElement('div'); div.appendChild(a); div.appendChild(btndel); get('wcr_listabm').appendChild(div); } //agrega la pag actual a la lista de bookmarks function addBookmark(evt){ var lista = getListaBookmarks(true); for(var i=0;i<lista.length;i++){ if(lista[i]['url']==link[posActual]) return; } var item = {url: link[posActual], title: titulo[posActual]}; lista.push(item); addLista(item); saveListaBookmarks(lista); if(evt) evt.stopPropagation(); } //borra un bookmark de la lista function delBookmark(evt){ var lista = getListaBookmarks(true); var div = evt.target.parentNode; var divs = div.parentNode.childNodes; var num; for(num=0; div!=divs[num] && num<divs.length; num++) continue; lista.splice(num, 1); div.parentNode.removeChild(div); saveListaBookmarks(lista); evt.stopPropagation(); } //borra todos los bookmarks function clearBookmarks(){ get('wcr_listabm').innerHTML = ''; saveListaBookmarks([]); } //setea la pag actual como unico bookmark function setBookmark(){ clearBookmarks(); addBookmark(); } //retorna la configuracion de layout para esta pag (true/false: usar el layout original/limpio) //busca la conf especifica para esta pag, si no hay usa la default, si tampoco hay usa defval function confKeepLayout(defval, defpag){ return confBool('layout', defval, defpag); } //retorna el num de pags a prefetchear en cada dir function confPrefetchSize(defval){ return [confVal('prefetch_izq', defval[0]), confVal('prefetch_der', defval[1])]; } //retorna el num de pags a prefetchear en cada dir cuando parte la pag function confPrefetchSizeStart(defval){ return [confVal('prefetch_start_izq', defval[0]), confVal('prefetch_start_der', defval[1])]; } //si es true, al hacer click en la mitad izquierda de la img se avanza para atras, si no siempre es para adelante function confLeftImageClick(defval){ return confBool('click_img_izq', defval); } //saca de la conf el cursor q corresponde al estado y elemento pedido, y si es un custom lo convierte function confCursor(conf, elem, defval){ var val = defval; if(conf){ if(!confBool('chcursor_'+elem, true)) return elem == 'img' ? 'pointer' : 'auto'; val = confVal('cursor_'+conf, defval); } if(!Number(val)) return val; return cursorUrl(cursores_custom[val]); } //convierte un cursor custom (url o base64) al formato url function cursorUrl(val){ if(!val) return 'auto'; if(val.match(/[^a-z0-9+\/=]/i)) return "url("+val+") 16 16, auto"; return "url('data:image/cursor;base64,"+val+"') 16 16, auto"; } //busca una conf booleana (guardada como '0'/'1') especifica para esta pag, si no hay usa la default, si tampoco hay usa defval function confBool(conf, defval, defpag, reloadCache){ var val = confVal(conf, defval, defpag, reloadCache); return val == '1' || val === true; } //busca una conf especifica para esta pag, si no hay usa la default, si tampoco hay usa defval function confVal(conf, defval, defpag, reloadCache){ var val = getData(conf, '', undefined, reloadCache); if(val == ''){ if(defpag !== undefined) val = defpag; else val = getData(conf, '', 'default'); } if(val == '') return defval; return val; } //alterna la configuracion de layout del dominio (si no se pasa el dominio se usa la de este host) function toggleConfKeepLayout(){ toggleConfBool('layout', keepLayout); redirect(link[posActual]); } //dice si mostrar o no todos los botones (back/next, bookmarks, fit/layout/settings) function confShowButtons(defval){ return confBool('botones', defval); } //alterna entre mostrar o no todos los botones (back/next, bookmarks, fit/layout/settings) function toggleConfShowButtons(){ showButtons = toggleConfBool('botones', showButtons); get('wcr_botones').style.display = showButtons ? '' : 'none'; } //alterna entre fittear y no fittear la imagen function toggleConfFit(){ fitSize = toggleConfBool('fit', fitSize); fitImagen(); scrollear(); get('wcr_btnfit').innerHTML = (fitSize ? 'Disable' : 'Enable') + ' Fit-to-screen'; } //alterna una conf booleana para esta pag function toggleConfBool(conf, defval){ var val = confBool(conf, defval, undefined, true); setData(conf, val ? '0' : '1'); return !val; } //retorna si esta pag esta en modo debug leyendo la configuracion function confDebug(defval){ return getData('debug', defval); } //alterna el modo debug en esta pagina function toggleConfDebug(){ debug = !debug; setData('debug', debug); alert('Debug mode '+ (debug ? 'ON' : 'OFF')); } //leer la configuracion de las teclas, o cargar las default si no existen function getTeclas(){ var teclas = getData('teclas', teclado, 'default'); for(var t in teclas) teclado[t] = teclas[t]; return teclado; } //retorna el nombre de la tecla apretada con sus modificadores function nombreTecla(evt){ var pre = ''; if(evt.ctrlKey) pre += 'CTRL + '; if(evt.shiftKey) pre += 'SHIFT + '; if(evt.altKey) pre += 'ALT + '; if(evt.charCode) return pre + String.fromCharCode(evt.charCode).toUpperCase(); if(evt.keyCode >= 112 && evt.keyCode <= 135) return pre + 'F' + (evt.keyCode - 111); var kc = { 3: 'CANCEL', 6: 'HELP', 8: 'BACK_SPACE', 9: 'TAB', 12: 'CLEAR', 13: 'RETURN', 14: 'ENTER', 16: 'SHIFT', 17: 'CONTROL', 18: 'ALT', 19: 'PAUSE', 20: 'CAPS_LOCK', 27: 'ESCAPE', 32: 'SPACE', 33: 'PAGE_UP', 34: 'PAGE_DOWN', 35: 'END', 36: 'HOME', 37: 'LEFT', 38: 'UP', 39: 'RIGHT', 40: 'DOWN', 44: 'PRINTSCREEN', 45: 'INSERT', 46: 'DELETE', 93: 'CONTEXT_MENU', 106: 'MULTIPLY', 107: 'ADD', 108: 'SEPARATOR', 109: 'SUBTRACT', 110: 'DECIMAL', 111: 'DIVIDE', 144: 'NUM_LOCK', 145: 'SCROLL_LOCK', 188: 'COMMA', 190: 'PERIOD', 191: 'SLASH', 192: 'BACK_QUOTE', 219: 'OPEN_BRACKET', 220: 'BACK_SLASH', 221: 'CLOSE_BRACKET', 222: 'QUOTE', 224: 'META' }; return pre + (kc[evt.keyCode] || ('??? ('+evt.keyCode+')')); } //un solo menu q abre la pantalla de configuracion con todas las opciones if(GM_registerMenuCommand){ GM_registerMenuCommand('Webcomic Reader - Settings', mostrarSettings); } //Script update checker from http://userscripts.org/scripts/review/20145 if (GM_xmlhttpRequest) { var SUC_script_num = 59842; // Change this to the number given to the script by userscripts.org (check the address bar) try { function updateCheck(forced) { var dias = getData('updateDays', 1, 'default'); if ((forced) || dias && (parseInt(GM_getValue('SUC_last_update', '0')) + dias*86400000 <= (new Date().getTime()))) { try { GM_xmlhttpRequest({ method: 'GET', url: 'http://userscripts.org/scripts/source/' + SUC_script_num + '.meta.js?' + new Date().getTime(), headers: { 'Cache-Control': 'no-cache' }, onload: function(resp) { var local_version, remote_version, rt, script_name; rt = resp.responseText; GM_setValue('SUC_last_update', new Date().getTime() + ''); remote_version = parseInt(/@uso:version\s*(.*?)\s*$/m.exec(rt)[1]); local_version = parseInt(GM_getValue('SUC_current_version', '-1')); if (local_version != -1) { script_name = (/@name\s*(.*?)\s*$/m.exec(rt))[1]; if (remote_version > local_version) { //version oficial (yyyy-mm-dd(.n)?) var version = rt.match(/@version\s+(.+)/)[1]; //comentarios del ultimo cambio var cambios = rt.match(/@lastchanges\s+(.+)/); cambios = cambios ? cambios[1] : false; //flags con el tipo de cosas del update. si ninguna me importa, me salgo var tipo = rt.match(/@updatetype +(\d+)/); if(!forced && tipo && !(getData('updateFlags', (1<<16)-1, 'default') & Number(tipo[1]))) return; var accion = getData('updateAction', 0, 'default'); if (accion & 2 || confirm( 'There is an update available for the Greasemonkey script "' + script_name + '" ('+version+')' + (cambios ? '\n\nLast changes: ' + cambios : '') + '\n\nWould you like to '+ (accion & 1 ? 'install it now?' : 'go to the install page now?'))){ GM_setValue('SUC_current_version', remote_version); if(accion & 1) document.location.href = 'http://userscripts.org/scripts/source/' + SUC_script_num + '.user.js'; else GM_openInTab('http://userscripts.org/scripts/show/' + SUC_script_num); } } else if (forced) alert('No update is available for "' + script_name + '."'); } else GM_setValue('SUC_current_version', remote_version + ''); } }); } catch(err) { if (forced) alert('An error occurred while checking for updates:\n' + err); } } } if(getData('autoUpdate', true, 'default')) updateCheck(false); } catch(err) {} } var tabSettingActual = 'wcr_general'; //para acordarse por mientras del tab q deje abierto en los settings //mostrar la pantalla de configuracion function mostrarSettings(){ try{ if(get('wcr_settings')) return; //si ya esta abierta la pantalla, no hacer nada dataCache = null; //forzar a q se cargue todo de nuevo, por si cambiaron algo en otro tab //propiedades editables de la configuracion del sitio var propsSitio = { url:{ desc: 'URL', title: "Define what sites will use these settings", tipos:{ str:{ desc: 'Beginning of URL', val:{ elem: 'input', title: "Beginning of the url without the http://www.", size: 60 } }, re:{ desc: "RegExp", val:{ elem: 'input', title: "Regular expression that matches the url", size: 60 } } } }, img:{ desc:'Image', title:"Method for obtaining the main image", tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: '<img> that is the only one with a "src" containing one of the following strings: "/comics/", "/comic/", "/strips/", "/strip/", "/archives/", "/archive/", "/wp-content/uploads/", "comics", "comic", "strips", "strip", "archives", "archive", "/manga/"' } }, str:{ desc: 'Beginning of src', val:{ elem: 'input', title: "Beginning of the "src" attribute of the <img>", size: 60 } }, re:{ desc: 'RegExp', val:{ elem: 'input', title: "Regular expression that captures the whole <img> (or at least the "src" and "title" attributes)", size: 50 }, grp:{ elem: 'input', title: "Number of the group that captured the <img>", size: 1 } }, xp:{ desc: 'XPath', val:{ elem: 'input', title: "XPath query that returns the <img>", size: 60 } }, css:{ desc: 'CSS selector', val:{ elem: 'input', title: "CSS query that returns the <img>", size: 60 } }, fn:{ desc: 'function(html, pos)', val:{ elem: 'textarea', title: "Function that receives the html of the page and its position relative to the starting page (0 being where you started reading), and returns the <img> element (either as string or object)", rows:3, cols:45 } } } }, back:{ desc: 'Back', title: 'Method for obtaining the link to the previous page', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: '<a> that has the word "back" or "prev" somewhere in its innerHTML or one of its attributes' } }, str:{ desc: 'XPath condition', val:{ elem: 'input', title: 'Condition for the following XPath query: //a[condition]/@href', size: 60 } }, re:{ desc: 'RegExp', val:{ elem: 'input', title: "Regular expression that captures the URL of the previous page", size: 50 }, grp:{ elem: 'input', title: "Number of the group that captured the URL", size: 1 } }, xp:{ desc: 'XPath', val:{ elem: 'input', title: "XPath query that returns the URL of the previous page, or the <a> element that links to it", size: 60 } }, css:{ desc: 'CSS selector', val:{ elem: 'input', title: "CSS query that returns the <a> element that links to the previous page", size: 60 } }, fn:{ desc: 'function(html, pos)', val:{ elem: 'textarea', title: "Function that receives the html of the page and its position relative to the starting page (0 being where you started reading), and returns the URL of the previous page", rows:3, cols:45 } } } }, next:{ desc: 'Next', title: 'Method for obtaining the link to the next page', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: '<a> that has the word "next" somewhere in its innerHTML or one of its attributes' } }, str:{ desc: 'XPath condition', val:{ elem: 'input', title: 'Condition for the following XPath query: //a[condition]/@href', size: 60 } }, re:{ desc: 'RegExp', val:{ elem: 'input', title: "Regular expression that captures the URL of the next page", size: 50 }, grp:{ elem: 'input', title: "Number of the group that captured the URL", size: 1 } }, xp:{ desc: 'XPath', val:{ elem: 'input', title: "XPath query that returns the URL of the next page, or the <a> element that links to it", size: 60 } }, css:{ desc: 'CSS selector', val:{ elem: 'input', title: "CSS query that returns the <a> element that links to the next page", size: 60 } }, fn:{ desc: 'function(html, pos)', val:{ elem: 'textarea', title: "Function that receives the html of the page and its position relative to the starting page (0 being where you started reading), and returns the URL of the next page", rows:3, cols:45 } } } }, first:{ desc: 'First', title: 'Method for obtaining the link to the first page', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: '<a> that has the word "first" somewhere in its innerHTML or one of its attributes' } }, str:{ desc: 'XPath condition', val:{ elem: 'input', title: 'Condition for the following XPath query: //a[condition]/@href', size: 60 } }, re:{ desc: 'RegExp', val:{ elem: 'input', title: "Regular expression that captures the URL of the first page", size: 50 }, grp:{ elem: 'input', title: "Number of the group that captured the URL", size: 1 } }, xp:{ desc: 'XPath', val:{ elem: 'input', title: "XPath query that returns the URL of the first page, or the <a> element that links to it", size: 60 } }, css:{ desc: 'CSS selector', val:{ elem: 'input', title: "CSS query that returns the <a> element that links to the first page", size: 60 } }, fn:{ desc: 'function(html)', val:{ elem: 'textarea', title: "Function that receives the html of the page and returns the URL of the first page", rows:3, cols:45 } } } }, last:{ desc: 'Last', title: 'Method for obtaining the link to the last page', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: '<a> that has the word "last", "latest", "newest" or "today" somewhere in its innerHTML or one of its attributes' } }, str:{ desc: 'XPath condition', val:{ elem: 'input', title: 'Condition for the following XPath query: //a[condition]/@href', size: 60 } }, re:{ desc: 'RegExp', val:{ elem: 'input', title: "Regular expression that captures the URL of the last page", size: 50 }, grp:{ elem: 'input', title: "Number of the group that captured the URL", size: 1 } }, xp:{ desc: 'XPath', val:{ elem: 'input', title: "XPath query that returns the URL of the last page, or the <a> element that links to it", size: 60 } }, css:{ desc: 'CSS selector', val:{ elem: 'input', title: "CSS query that returns the <a> element that links to the last page", size: 60 } }, fn:{ desc: 'function(html)', val:{ elem: 'textarea', title: "Function that receives the html of the page and returns the URL of the last page", rows:3, cols:45 } } } }, fixurl:{ desc: 'Fix URL', title: 'Fix URLs coming from a link or img.src for sites that may need it (like relative URLs that don\'t behave normally, or links from http://something.com to http://www.something.com that wouldn\'t work because of cross site request limitations)', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Do nothing' } }, fn:{ desc: 'function(url, img, link, pos)', val: { elem: 'textarea', title: 'Function that receives an URL, and flags telling if it came from an img.src or link to another page, and returns the fixed url', rows:3, cols:45 } } } }, extra:{ desc: 'Extra Content', title: 'Other content besides the main image to get from each page', tipos:{ str:{ desc: 'Literal string', val:{ elem: 'input', title: 'HTML string, this will be output literally', size: 60 } }, re:{ desc: 'RegExp', val:{ elem: 'input', title: "Regular expression that captures the desired content", size: 50 }, grp:{ elem: 'input', title: "Number of the group that captured the content", size: 1 } }, xp:{ desc: 'XPath', val:{ elem: 'input', title: "XPath query that returns the desired content", size: 60 }, arr:{ elem: 'select', html: '<option value="">First element</option><option value="1">List of elements</option>'}, glue:{ elem: 'input', title: 'String to put between each pair of elements returned', size: 20}, first:{ elem: 'input', title: 'Index of the first element to return (starting from 0, negative means counting from the last)', size: 1}, last:{ elem: 'input', title: 'Index of the last element to return (starting from 0, negative means counting from the last)', size: 1} }, css:{ desc: 'CSS selector', val:{ elem: 'input', title: "CSS query that returns the desired content", size: 60 }, arr:{ elem: 'select', html: '<option value="">First element</option><option value="1">List of elements</option>'}, glue:{ elem: 'input', title: 'String to put between each pair of elements returned', size: 20}, first:{ elem: 'input', title: 'Index of the first element to return (starting from 0, negative means counting from the last)', size: 1}, last:{ elem: 'input', title: 'Index of the last element to return (starting from 0, negative means counting from the last)', size: 1} }, fn:{ desc: 'function(html, pos)', val:{ elem: 'textarea', title: "Function that receives the html of the page and its position relative to the starting page (0 being where you started reading), and returns the desired content", rows:3, cols:45 } } } }, xelem:{ desc: 'Extras Container', title: 'Element for placing the extra content when using the full layout', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Inside the WCR container (between the image and the back/next buttons)' } }, str:{ desc: 'XPath', val: { elem: 'input', title: 'XPath query that returns the element where the extra content will be placed as its innerHTML', size:60 } } } }, layelem:{ desc: 'Layout Container', title: 'Element for placing the image and the rest of the script content when using the full layout', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Where the original image was' } }, str:{ desc: 'XPath', val: { elem: 'input', title: 'XPath query that returns the element where the content will be placed as its innerHTML', size:60 } } } }, js:{ desc: 'Custom Action', title: 'Custom function to execute after each page change', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Do nothing' } }, fn:{ desc: 'function(dir)', val: { elem: 'textarea', title: 'Function that receives the direction in which the page was changed (0 when the starting page is loaded, 1 when going forward and -1 when going backwards)', rows:3, cols:45 } } } }, style:{ desc: 'Custom CSS', title: 'Custom CSS styles', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Don\'t change anything' } }, str:{ desc: 'CSS rules', val: { elem: 'textarea', title: 'CSS rules', rows:3, cols:45 } } } }, bgcol:{ desc: 'Background Color', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Keep original' } }, str:{ desc: 'Custom', val: { elem: 'input', title: '#RRGGBB or #RGB', size:6 } } } }, txtcol:{ desc: 'Text Color', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Keep original' } }, str:{ desc: 'Custom', val: { elem: 'input', title: '#RRGGBB or #RGB', size:6 } } } }, scrollx:{ desc: 'Default Horizontal Autoscroll', title: 'Scroll to this position of the image each time you change the page', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Left' } }, str:{ desc: 'Relative to image', val: { elem: 'select', html: '<option value="L">Left</option><option value="R">Right</option><option value="M">Middle</option>' } }, num:{ desc: 'Pixels', val: { elem: 'input', title: 'X coordinate in pixels', size: 5 } }, fn:{ desc: 'function()', val:{ elem: 'textarea', title: "Function that returns the numbers of pixels to scroll", rows:3, cols:45 } } } }, scrolly:{ desc: 'Default Vertical Autoscroll', title: 'Scroll to this position of the image each time you change the page', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Top' } }, str:{ desc: 'Relative to image', val: { elem: 'select', html: '<option value="U">Top</option><option value="D">Bottom</option><option value="M">Middle</option>' } }, num:{ desc: 'Pixels', val: { elem: 'input', title: 'Y coordinate in pixels', size: 5 } }, fn:{ desc: 'function()', val:{ elem: 'textarea', title: "Function that returns the numbers of pixels to scroll", rows:3, cols:45 } } } }, layout:{ desc: 'Default Layout', title: 'Layout to use when no custom layout settings are defined for this site', tipos:{ def:{ desc: 'Default', val:{ elem: 'span', html: 'Use default settings' } }, bool:{ desc: 'Custom', val: { elem: 'select', html: '<option value="false">Minimalistic</option><option value="true">Keep original</option>' } } } } }; //tipos de actualizaciones var listaTipos = [ 'Bug fixes (Firefox)', 'Bug fixes (Other browsers)', 'New features', 'New sites', 'Fixes for old sites', 'Graphic changes', 'New options']; var t, tiposUp = {}; for(t=0; t<listaTipos.length;t++) tiposUp[1<<t] = listaTipos[t]; tiposUp[(1<<16)-(1<<t)] = 'Other stuff (???)'; //teclas configurables var teclas = { back: ['Back', 'Go back 1 page'], next: ['Next', 'Go forward 1 page'], scroll_left: ['Scroll left', ''], scroll_right: ['Scroll right', ''], scroll_up: ['Scroll up', ''], scroll_down: ['Scroll down', ''], reload: ['Reload', 'Reload the current page (in old browsers, pressing the reload button will take you back to where you started). F5 will always do this (unless set to another action)'], set_bm: ['Set as only bookmark', 'Delete other bookmarks and add this page, so that the next time you visit the site you will be taken back to this page'], add_bm: ['Add to bookmarks', ''], layout: ['Toggle layout', 'Switch between the "clean layout" (show only image and buttons) and "full layout" (show the whole original page)'], botones: ['Toggle buttons', 'Switch between showing or hiding all the script\'s buttons (back/next, bookmarks, settings, etc...)'], fit: ['Toggle Fit-to-screen', 'Switch between always showing the image in its original size or fitting it to the screen when needed'], slide: ['Toggle Slideshow', 'Start or stop the slideshow mode (pages turn automatically after the selected time). Slideshow will also stop by pressing ESC or manually turning a page'], debug_mode: ['Toggle debug mode', 'In debug mode you\'ll get alerts to see what isn\'t working. Useful when adding new sites'], debug_info: ['Debug info (on debug mode)', 'Show a list of URLs of the preloaded pages and images'] }; var arrcursores = ['default', 'none', 'context-menu', 'help', 'pointer', 'progress', 'wait', 'cell', 'crosshair', 'text', 'vertical-text', 'alias', 'copy', 'move', 'no-drop', 'not-allowed', 'all-scroll', 'col-resize', 'row-resize', 'n-resize', 'e-resize', 's-resize', 'w-resize', 'ne-resize', 'nw-resize', 'se-resize', 'sw-resize', 'ew-resize', 'ns-resize', 'nesw-resize', 'nwse-resize']; if(isFirefox()) arrcursores.push('-moz-grab', '-moz-grabbing', '-moz-zoom-in', '-moz-zoom-out'); if(isWebKit()) arrcursores.push('-webkit-grab', '-webkit-grabbing', '-webkit-zoom-in', '-webkit-zoom-out'); var cursores = { '1': 'Left green arrow', '2': 'Right green arrow', '5': 'Left blue arrow', '6': 'Right blue arrow', '3': 'Custom cursor #1', '4': 'Custom cursor #2' }; for(var c=0; c<arrcursores.length; c++) cursores[arrcursores[c]] = arrcursores[c]; //opciones generales var opsGeneral = { clickImgNavigates:{ desc:'Click image to navigate', title:'If enabled, clicking the image will let you go to the next or previous page', def: defaultSettings.clickImgNavigates ? '1' : '0', vals:{ '0':'Disabled', '1':'Enabled' } }, click_img_izq:{ desc:'Click left half of<br/>image to go back', title:'If enabled, clicking the left half of the image will take you to the previous page, and the right half to the next one. Otherwise, clicking anywhere will always take you to the next page', def: defaultSettings.clikLeftHalfGoesBack ? '1' : '0', vals:{ '0':'Disabled', '1':'Enabled' } }, flipControlsManga:{ desc:'Flip controls<br/>for mangas', title:'If enabled, flips the controls (L/R arrows, L/R image click, back/next buttons) for mangas or other right-to-left content', def: defaultSettings.flipControlsManga ? '1' : '0', vals:{ '0':'Disabled', '1':'Enabled' } }, overwrite_links:{ desc:'Overwrite links', title:'If enabled, overwrites the original back/next links (when using the original layout) to work like the script\'s buttons', def:'1', vals:{ '0':'Disabled', '1':'Enabled' } }, goToBookmark:{ desc: 'Go to bookmark', title: 'If you have 1 bookmark saved for a site, asks you if you want to go there when you visit the site', def: defaultSettings.goToBookmark ? '1' : '0', vals:{ '0':'Disabled', '1':'Enabled' } }, scroll_rate:{ desc:'Scroll rate', title:'Number of pixels to scroll when using the keyboard', def:'50'}, b64_images:{ desc:'Force cache (experimental)', title:'Chache images as base64 strings, so the browser doesn\'t unload them to save memory', def:'0', vals:{ '0':'Disabled', '1':'Enabled' } }, useHistoryAPI:{ desc: 'Use browser history', title: 'Changes the URL and keeps track of the visited pages in the browser history, so you can navigate with the browser\'s back/forward buttons as usual', def: '1', vals:{ '0':'Disabled', '1':'Enabled' } }, moveWhileLoading:{ desc: 'Force loading next page', title: 'Lets you move to the next or previous page before the image for that page has finished loading', def: defaultSettings.moveWhileLoading ? '1' : '0', vals:{ '0':'Disabled', '1':'Enabled' } }, _grp_fit:{ desc:'AutoZoom', title:'Automatically zoom the image, either shrinking or expanding it to make it fit in the screen' }, fit:{ desc:'Fit image to screen', title:'Apply options below to fit the image to the screen (if none of them are selected and you enable this option, you will be prompted to select the settings the first time you visit each site). This setting can also be toggled for this site with a keyboard shortcut (+ by default)', def: defaultSettings.autozoom ? '1' : '0', vals:{ '0':'Disabled', '1':'Enabled' } }, achw:{ desc:'Shrink to fit width', title:'If the image is wider than the window, it will be shrunk to fit the screen without needing to scroll', def: defaultSettings.shrinkWidth ? '1' : '0', vals:{ '0':'Never shrink', '1':'Shrink when needed' } }, achh:{ desc:'Shrink to fit height', title:'If the image is longer than the window, it will be shrunk to fit the screen without needing to scroll', def: defaultSettings.shrinkHeight ? '1' : '0', vals:{ '0':'Never shrink', '1':'Shrink when needed' } }, agrw:{ desc:'Expand to fit width', title:'If the image is smaller than the window, it will be expanded to fit the screen', def: defaultSettings.expandWidth ? '1' : '0', vals:{ '0':'Never expand', '1':'Expand when needed' } }, agrh:{ desc:'Expand to fit height', title:'If the image is smaller than the window, it will be expanded to fit the screen', def: defaultSettings.expandHeight ? '1' : '0', vals:{ '0':'Never expand', '1':'Expand when needed' } }, maxScale:{ desc:'Max scale', title: 'Maximum scale (as a percentage, > 100) to which the image should be expanded (leave blank for no limit)'}, minScale:{ desc:'Min scale', title: 'Minimum scale (as a percentage, < 100) to which the image should be shrunk (leave blank for no limit)'}, maxScaleReset:{ desc:'Over max scale', title: 'Action to be taken when the AutoZoom would expand the image over the max scale', def: '0', vals: { '0': 'Keep the max scale', '1': 'Reset to original size' } }, minScaleReset:{ desc:'Under min scale', title: 'Action to be taken when the AutoZoom would shrink the image over the min scale', def: '0', vals: { '0': 'Keep the min scale', '1': 'Reset to original size' } }, _grp_scroll:{ desc: 'AutoScroll', title:'Scroll to this position of the image each time you change the page' }, scrollx:{ desc:'Horizontal', title:'Scroll to this position of the image each time you change the page', vals:{ 'L':'Left', 'R':'Right', 'M':'Middle' } }, scrolly:{ desc:'Vertical', title:'Scroll to this position of the image each time you change the page', vals:{ 'U':'Top', 'D':'Bottom', 'M':'Middle' } }, _grp_prefetch:{ desc:'Page Preloading', title:'Adjust the number of pages to preload in each direction' }, prefetch_der:{ desc:'Forward', title:'The number of next pages to preload (>0)', def:defaultSettings.prefetchNext}, prefetch_izq:{ desc:'Backwards', title:'The number of previous pages to preload (>0)', def:defaultSettings.prefetchBack}, prefetch_start_der:{ desc:'Initial forward', title:'The number of next pages to preload (>0) when the page is first loaded (to avoid wasting bandwith if you only wanted to see that page)', def:defaultSettings.prefetchNextStart}, prefetch_start_izq:{ desc:'Initial backwards', title:'The number of previous pages to preload (>0) when the page is first loaded (to avoid wasting bandwith if you only wanted to see that page)', def:defaultSettings.prefetchBackStart}, prefetchNoNext:{ desc:'Prefetch when no next page', title:'Disable this to stop preloading the previous page when visiting the last page (ie, the next page was not found)', def:defaultSettings.prefetchNoNext ? '1' : '0', vals:{ '0':'Disabled', '1':'Enabled' }} }; //opciones visuales var opsLayout = { layout:{ desc:'Layout', title:'Minimalistic layout will show only the image, the defined extra content, and this script\'s buttons. Keeping the original layout will stuff that same content in the place where the image used to be, leaving the rest of the page untouched. This setting can also be toggled for this site with a keyboard shortcut (- by default)', def: defaultSettings.fullLayout ? '1' : '0', vals:{ '0':'Minimalistic', '1':'Keep original' } }, botones:{ desc:'Buttons', title:'Show or hide all the script\'s buttons (back/next, bookmarks, settings, etc...). This setting can also be toggled for this site with a keyboard shortcut (Shift + - by default)', def: defaultSettings.showButtons ? '1' : '0', vals:{ '0':'Hide', '1':'Show' } }, dim:{ desc:'Screen Dimmer', title:'Add a shadow to the rest of the site so the image (or script content) gets a better focus', def: '0', vals:{ '0':'Disabled', 'S':'Focus script content', 'I':'Focus image' } }, _grp_border:{ desc: 'Border', title:'Space to leave around the image (affects AutoScroll and AutoZoom)' }, bordex:{ desc:'Horizontal border', title:'Extra pixels to the left/right of the image', def: defaultSettings.borderLR }, bordey:{ desc:'Vertical border', title:'Extra pixels to the top/bottom of the image', def: defaultSettings.borderUD }, _grp_cursor:{ desc:'Cursors', title:'Change the cursor according to the current state' }, chcursor_img:{ desc:'Change over image', title:'Enable/Disable this to see a different cursor over the image depending on the state, or always the same one', def:'1', vals:{ '0':'Disabled', '1':'Enabled' } }, chcursor_btns:{ desc:'Change over buttons', title:'Enable/Disable this to see a different cursor over the back/next buttons depending on the state, or always the same one', def:'1', vals:{ '0':'Disabled', '1':'Enabled' } }, cursor_back:{ desc:'Previous page', title:'Cursor for the previous page', def:'1', vals: cursores }, cursor_next:{ desc:'Next page', title:'Cursor for the next page', def:'2', vals: cursores }, cursor_loading:{ desc:'Loading', title:'Cursor for when the next page is loading', def:'progress', vals: cursores }, cursor_nolink:{ desc:'No link', title:'Cursor for when there is no next page', def:'not-allowed', vals: cursores }, cursor_noimg:{ desc:'No image', title:'Cursor for when there is a next page but it has no image', def:'pointer', vals: cursores }, cursor_custom_3:{ desc:'Custom cursor #1', title:'Custom image to use in the above options, either as an url or base64 (suggested size of 32x32 px, hotspot is at 16,16)'}, cursor_custom_4:{ desc:'Custom cursor #2', title:'Custom image to use in the above options, either as an url or base64 (suggested size of 32x32 px, hotspot is at 16,16)'} }; var divsets = document.createElement('div'); divsets.id = 'wcr_settings'; divsets.style.textAlign = 'center'; divsets.innerHTML = '<div style="position:fixed; z-index:232322; background:#000; top:0; left:0; right:0; bottom:0; opacity:0.8;"></div>'+ '<div id="wcr_settings_popup" style="position:absolute; left:50%; z-index:232323; background-color:#fff; color:#000; padding: 20px;">'+ '<div id="wcr_settings_links">'+ '<span class="wcr_general">General</span> | '+ '<span class="wcr_layout">Graphic settings</span> | '+ '<span class="wcr_sitio">Site settings</span> | '+ '<span class="wcr_teclas">Keyboard shortcuts</span>'+ (GM_xmlhttpRequest ? ' | <span class="wcr_updater">Updater</span>' : '')+ '</div><hr/>'+ '<div id="wcr_settings_content" style="text-align:left">'+ '<div class="wcr_general">'+htmlLayout(opsGeneral, 'general')+'</div>'+ '<div class="wcr_layout">'+htmlLayout(opsLayout, 'layout')+'</div>'+ '<div class="wcr_sitio">'+htmlSitio(propsSitio)+'</div>'+ '<div class="wcr_teclas">'+htmlTeclas(teclas)+'</div>'+ (GM_xmlhttpRequest ? '<div class="wcr_updater">'+htmlUpdater(tiposUp)+'</div>' : '')+ '</div><hr/>'+ '<div>'+ 'Import / Export '+ '<select id="wcr_set_sel_impexp">'+ '<option value="">data for '+dominioData()+'</option>'+ '<option value="default">default settings</option>'+ '<option value="all">ALL data</option>'+ '</select> '+ '<button id="wcr_set_btn_impexp">GO</button> - '+ 'Reset '+ '<select id="wcr_set_sel_reset">'+ '<option value="">data for '+dominioData()+'</option>'+ '<option value="default">default settings</option>'+ '<option value="all">ALL data</option>'+ '</select> '+ '<button id="wcr_set_btn_reset">GO</button>'+ '</div><br/>'+ '<div>'+ '<button id="wcr_set_btn_guardar">Save</button> '+ '<button id="wcr_set_btn_aplicar">Apply</button> '+ '<button id="wcr_set_btn_cancelar">Cancel</button>'+ '</div>'+ '</div>'+ '<style>'+ '#wcr_settings_popup *{color:#000;}'+ '#wcr_settings_popup input, #wcr_settings_popup select, #wcr_settings_popup textarea{background-color:#fff;}'+ '#wcr_settings_links span{cursor:pointer; text-decoration:underline;}'+ 'div{position:static; float:none;}'+ '#wcr_settings [title]{cursor:help;}'+ '#wcr_settings tr:nth-of-type(odd){background-color:#fff; color:#000;}'+ '#wcr_settings tr:nth-of-type(even){background-color:#eef; color:#000;}'+ '#wcr_settings tr.wcr_settings_group{background-color:#ccf; color:#000; text-align:center; font-style:italic;}'+ '.wcr_settings_group td:nth-of-type(1):not([colspan]){background-color:#fff;}'+ '</style>'; document.body.appendChild(divsets); initLayout(opsGeneral, 'general'); initLayout(opsLayout, 'layout'); initSitio(propsSitio); initTeclas(teclas); if(GM_xmlhttpRequest) initUpdater(tiposUp); //setear eventos para tabs/guardar/cancelar var tabs = xpath('//div[@id="wcr_settings_links"]/span', document, true); for(var i=0; i<tabs.length; i++) setEvt(tabs[i], 'click', function(evt){ cambiarTabSettings(evt.target.className); }); for(var o in opsGeneral) opsLayout[o] = opsGeneral[o]; setEvt('wcr_set_btn_guardar', 'click', function(){ if(guardarSettings(teclas, propsSitio, tiposUp, opsLayout)){ redirect(link[posActual]); } }); setEvt('wcr_set_btn_aplicar', 'click', function(){ guardarSettings(teclas, propsSitio, tiposUp, opsLayout); }); setEvt('wcr_set_btn_cancelar', 'click', function(){ document.body.removeChild(divsets); }); setEvt('wcr_set_btn_impexp', 'click', function(){ if(confirm('Save the changes?')) guardarSettings(teclas, propsSitio, tiposUp, opsLayout); var dominio = get('wcr_set_sel_impexp').value; var data = dominio == 'all' ? GM_getValue('wcr.settings', '') : JSON.stringify(getData('', '', dominio)); var resp = prompt( 'Copy this and save it somewhere to export your settings.\n' + 'Replace this with your saved settings to restore them.', data); if(resp && resp != data && confirm('Are you sure you want to replace your current settings?')){ try{ var nuevaData = JSON.parse(resp); if(dominio == 'all') GM_setValue('wcr.settings', resp); else setData('', nuevaData, dominio); alert('Settings updated successfully'); redirect(link[posActual]); } catch(e){ alert('Error parsing the settings, nothing has been changed'); } } }); setEvt('wcr_set_btn_reset', 'click', function(){ var msgConfirm = 'This will reset all data for '+dominioData()+': graphic options, bookmarks, and last visited page.\nYou may want to export and backup your settings first...\n\nAre you sure you want to delete this data?'; var msgOK = 'All settings for '+dominioData()+' cleared'; var dominio = get('wcr_set_sel_reset').value; if(dominio == 'all'){ msgConfirm = 'This will reset EVERYTHING to the default settings, and all data will be lost for all sites.\nYou may want to export and backup your settings first...\n\nAre you REALLY sure you want to do delete this data?'; msgOK = 'Everything is gone... everything...\n\n\n\n...forever'; } else if(dominio == 'default'){ msgConfirm = 'This will reset all the default graphic options, keyboard shortcuts and autoupdater settings.\nYou may want to export and backup your settings first...\n\nAre you sure you want to do delete this data?'; msgOK = 'All default settings cleared'; } if(confirm(msgConfirm)){ if(dominio == 'all') GM_deleteValue('wcr.settings'); else delData('', dominio); alert(msgOK); redirect(link[posActual]); } }); cambiarTabSettings(tabSettingActual); } catch(e){ alert('Error while initializing the settings window: ' + e); if(get('wcr_settings')) document.body.removeChild(get('wcr_settings')); } } //inicializar los valores y eventos de layout function initLayout(ops, nombre){ for(var o in ops){ if(!o.indexOf('_')) continue; var id = 'wcr_sel_layout_'+o; var val = getData(o, ''); var valdef = getData(o, ops[o].def || '', 'default'); if(!o.indexOf('scroll')){ if(typeof(val)=='number'){ get('wcr_sel_layout__offset_'+o).value = val<0 ? -val : val; if(o=='scrollx') val = val>0 ? 'L' : 'R'; else val = val>0 ? 'D' : 'U'; } if(typeof(valdef)=='number'){ get('wcr_sel_layout__offset_'+o+'_def').value = valdef<0 ? -valdef : valdef; if(o=='scrollx') valdef = valdef>0 ? 'L' : 'R'; else valdef = valdef>0 ? 'D' : 'U'; } } get(id).value = val; get(id+'_def').value = valdef; if(!o.indexOf('cursor_custom_')){ setEvt(id+'_def', 'mouseover', function(evt){ evt.target.style.cursor = cursorUrl(evt.target.value); }); setEvt(id, 'mouseover', function(evt){ evt.target.style.cursor = cursorUrl(evt.target.value); }); } else if(!o.indexOf('cursor_')){ setEvt(id+'_def', 'mouseover', function(evt){ evt.target.style.cursor = confCursor(null, null, evt.target.value); }); setEvt(id, 'mouseover', function(evt){ evt.target.style.cursor = confCursor(null, null, evt.target.value || get(evt.target.id+'_def').value); }); } } } //inicializar los valores y eventos del sitio function initSitio(props){ var lista = getConfPagina('lista'); var selConf = get('wcr_sel_confpag'); for(var i=0; i<lista.length; i++){ selConf.innerHTML += '<option value="'+escape(lista[i])+'">'+ (lista[i][0]=='d'?'(default) ':'(custom) ')+ lista[i].substr(3)+ '</option>'; } if(!lista.length){ selConf.innerHTML += '<option value="">Default settings</option>'; } setEvt('wcr_btn_delconfpag', 'click', function(evt){ if(!confirm('Are you sure you want to delete these settings?')) return; var customs = getData('confpags', {}, 'custompages'); var nombre = unescape(get('wcr_sel_confpag').value); delete customs[nombre]; setData('confpags', customs, 'custompages'); if(getData('confpag') == nombre) delData('confpag'); var selConf = get('wcr_sel_confpag'); selConf.removeChild(selConf.options[selConf.selectedIndex]); if(selConf.options.length == 2){ selConf.innerHTML += '<option value="">Default settings</option>'; } selConf.selectedIndex = selConf.options.length-1; initValoresSitio(props, selConf.value); }); setEvt('wcr_btn_editconfpag', 'click', function(evt){ selConf.selectedIndex = 0; initValoresSitio(props, selConf.value); }); for(var p in props){ var seltipo = get('wcr_sitio_tipo_'+p); setEvt(seltipo, 'change', function(evt){ cambiaTipo(evt.target); }); } var confActual = initValoresSitio(props, getData('confpag', '')); selConf.value = escape(confActual); setEvt(selConf, 'change', function(evt){ initValoresSitio(props, unescape(evt.target.value)); }); setEvt('wcr_btn_add_extra', 'click', function(evt){ var p = 'extra_'+Number(new Date()); trExtraConfSitio(p, props.extra); var seltipo = get('wcr_sitio_tipo_'+p); cambiaTipo(seltipo); }); } //rellena la tabla de conf del sitio con los valores de una conf especifica function initValoresSitio(props, conf){ var pag = null; if(conf != 'new'){ //si es nuevo me quedo con los valores q ya estaban pag = getConfPagina(conf); for(var p in props){ if(p=='extra'){// es un arreglo, meterse a cada uno try{ var extrasViejos = xpath('//tr[@class="wcr_extras"]', document, true); for(var i=0; i<extrasViejos.length; i++) extrasViejos[i].parentNode.removeChild(extrasViejos[i]); }catch(e){} if(pag && pag[p]){ for(i=0; i<pag[p].length; i++){ var p2 = p+'_'+i; trExtraConfSitio(p2, props[p]); var seltipo = get('wcr_sitio_tipo_'+p2); rellenarValores(pag[p][i], p2, seltipo); cambiaTipo(seltipo); } } } else{ seltipo = get('wcr_sitio_tipo_'+p); rellenarValores(pag ? pag[p] : undefined, p, seltipo); cambiaTipo(seltipo); } } } get('wcr_btn_delconfpag').style.display = (pag && pag.nombre && pag.nombre[0]=='c') ? '' : 'none'; get('wcr_btn_editconfpag').style.display = (pag && pag.nombre && pag.nombre[0]=='d') ? '' : 'none'; var dis = conf=='dis' || conf=="" || (pag && pag.nombre && pag.nombre[0]=='d'); var inputs = xpath('//table[@id="wcr_sitio_tabla"]//input | //table[@id="wcr_sitio_tabla"]//textarea | //table[@id="wcr_sitio_tabla"]//select', document, true); for(i=0; i<inputs.length; i++){ var inp = inputs[i]; inp.disabled = dis; inp.style.backgroundColor = dis ? '#eee' : '#fff'; } var botones = xpath('//table[@id="wcr_sitio_tabla"]//button', document, true); for(i=0; i<botones.length; i++){ botones[i].disabled = dis; } return pag ? pag.nombre : conf; function rellenarValores(valor, p, seltipo){ try{ var base = 'wcr_sitio_valor_'+p; //si no existe la conf para esta pag/prop rellenar con default if(valor===undefined){ seltipo.value = 'def'; if(seltipo.value != 'def'){ seltipo.value = 'str'; get(base+'_str_val').value = ''; } } else{ if(p=='url' && typeof(valor)!='string' && !isArray(valor)) valor = [valor]; //tipos: str, re, xp, fn, bool, num? switch(typeof(valor)){ case 'string': //str seltipo.value = 'str'; get(base+'_str_val').value = valor; break; case 'object': //xp, css o re if(typeof(valor[0]) == 'string'){ //xp seltipo.value = 'xp'; get(base+'_xp_val').value = valor[0]; if(get(base+'_xp_arr')) get(base+'_xp_arr').value = valor.length>1 ? '1' : ''; if(valor.length>1) get(base+'_xp_glue').value = valor[1]; if(valor.length>2) get(base+'_xp_first').value = valor[2]; if(valor.length>3) get(base+'_xp_last').value = valor[3]; } else if(isArray(valor[0])){ //css valor = valor[0]; seltipo.value = 'css'; get(base+'_css_val').value = valor[0]; if(get(base+'_css_arr')) get(base+'_css_arr').value = valor.length>1 ? '1' : ''; if(valor.length>1) get(base+'_css_glue').value = valor[1]; if(valor.length>2) get(base+'_css_first').value = valor[2]; if(valor.length>3) get(base+'_css_last').value = valor[3]; } else{ //re seltipo.value = 're'; get(base+'_re_val').value = valor[0]; if(valor.length>1) get(base+'_re_grp').value = valor[1]; } break; case 'function': //fn seltipo.value = 'fn'; //sacar el "^func..{" y el "}$" var fn = valor.toString(); fn = fn.replace(/^.+?\{(\s*[\r\n]+)*|\s*\}$/g, ''); fn = fn.replace(new RegExp('^' + fn.match(/^\s*/), 'mg'), ''); get(base+'_fn_val').innerHTML = fn; break; case 'boolean': seltipo.value = 'bool'; get(base+'_bool_val').value = valor; break; case 'number': seltipo.value = 'num'; get(base+'_num_val').value = valor; break; } } } catch(e){ error('rellenarSitio.'+p+': '+e); } } } //mostrar los inputs q corresponden y esconder los q no al cambiar el tipo de selector para una prop de la conf de un sitio function cambiaTipo(sel){ var clave = sel.id.substr('wcr_sitio_tipo_'.length), tipo = sel.value; var elems = xpath('//*[starts-with(@id,"wcr_sitio_valor_'+clave+'")]', document, true); for(var i=0; i<elems.length; i++) elems[i].style.display = elems[i].id.indexOf('_'+tipo)>0 ? '' : 'none'; } //inicializar los valores y eventos de las teclas function initTeclas(teclas){ var input, inputaux, hiddens = ['keyCode', 'ctrlKey', 'shiftKey', 'altKey']; teclado = getTeclas(); //por si me cambiaron la conf desde otra pag for(var t in teclas){ var teclasAlternativas = teclado[t] || [{}]; if(!isArray(teclasAlternativas)) teclasAlternativas = [teclasAlternativas]; for(var i=0; i<2; i++){ input = get('wcr_tecla_'+i+'_'+t); var tecla = teclasAlternativas[i] || {}; input.value = tecla.name || ''; for(var h=0; h<hiddens.length; h++){ inputaux = document.createElement('input'); inputaux.type = 'hidden'; inputaux.id = input.id + '_' + hiddens[h]; inputaux.value = tecla[hiddens[h]] || 'false'; input.parentNode.insertBefore(inputaux, input); } setEvt(input, 'keydown', function(evt){ if(evt.keyCode >= 16 && evt.keyCode <= 18 || evt.keyCode == 27) return; //ctrl/shift/alt o ESC (funca raro) if(evt.keyCode == 8){ //BACKSPACE, dejo la accion sin tecla for(var h=0; h<hiddens.length; h++) get(evt.target.id+'_'+hiddens[h]).value = ''; evt.target.value = ''; } else{ for(h=0; h<hiddens.length; h++) get(evt.target.id+'_'+hiddens[h]).value = evt[hiddens[h]]; evt.target.value = nombreTecla(evt); } evt.stopPropagation(); evt.preventDefault(); }); setEvt(input, 'keypress', function(evt){ if(evt.keyCode != 8) evt.target.value = nombreTecla(evt); evt.stopPropagation(); evt.preventDefault(); }); } } } //inicializar los valores y eventos del updater function initUpdater(tiposUp){ get('wcr_dias_update').value = getData('updateDays', 1, 'default'); get('wcr_accion_update').value = getData('updateAction', 0, 'default'); var tipoUpdate = getData('updateFlags', (1<<16)-1, 'default'); for(t in tiposUp) get('wcr_cb_tipo_update_'+t).checked = tipoUpdate & t; var ultimoUpdate = Number(GM_getValue('SUC_last_update', '0')); if(ultimoUpdate) get('wcr_fecha_update').innerHTML = new Date(ultimoUpdate); setEvt('wcr_btn_check_update', 'click', function(){ updateCheck(true); get('wcr_fecha_update').innerHTML = new Date(); }); } //generar el html de la conf del layout function htmlLayout(ops, nombre){ var html = '<table id="wcr_'+nombre+'_tabla">'+ '<tr class="wcr_settings_group">'+ '<td></td>'+ '<td>Default settings</td>'+ '<td>Settings for '+document.location.host.replace(/^www\./, '')+'</td>'+ '</tr>'; for(var o in ops){ var op = ops[o]; if(!o.indexOf('_grp_')){ html += '<tr class="wcr_settings_group">'+ '<td colspan="3" title="'+(op.title || '')+'">'+op.desc+'</td>'+ '</tr>'; } else{ var opts = ''; if(op.vals) for(var v in op.vals){ opts += '<option value="'+v+'"'+ (o.indexOf('cursor_') ? '' : (' style="cursor:'+confCursor(null, null, v)+'"'))+ '>'+op.vals[v]+'</option>'; } html += '<tr>'+ '<td title="'+(op.title || '')+'">'+op.desc+'</td>'+ '<td>'+ (op.vals ? ('<select id="wcr_sel_layout_'+o+'_def">'+opts+'</select>') : ('<input id="wcr_sel_layout_'+o+'_def"/>') )+'</td>'+ '<td>'+ (op.vals ? ('<select id="wcr_sel_layout_'+o+'">'+ '<option value="">Use default settings</option>'+opts+ '</select>') : ('<input id="wcr_sel_layout_'+o+'" title="leave empty to use default settings"/>') )+'</td>'+ '</tr>'; } } html += '</table>'; //poder esconder divs/botones? (first/last, bookmarks, last visited, toggle layout) //si se esconden cosas, asegurarse q no falle al tratar de usarlas return html; } //generar el html de la conf del sitio function htmlSitio(props){ var html = '<div>Current site settings: '+ '<select id="wcr_sel_confpag">'+ '<option value="new">New custom settings</option>'+ '<option value="dis">Disable '+document.location.host.replace(/^www\./, '')+'</option>'+ '</select>'+ '<button id="wcr_btn_editconfpag">Edit</button>'+ '<button id="wcr_btn_delconfpag">Delete</button>'+ '</div><br/><table id="wcr_sitio_tabla">'; for(var p in props){ html += '<tr id="wcr_tr_sitio_'+p+'"><td title="'+(props[p].title || '')+'">'+props[p].desc+'</td>'; if(p=='extra') html += '<td><button id="wcr_btn_add_extra">Add extra content</button></td><td/></tr>'; else{ var tds = tdsConfSitio(p, props[p]); html += '<td>'+tds[0]+'</td><td style="width:400px">'+tds[1]+'</td></tr>'; } } html += '</table><br/>Hover over a textbox for its meaning and an explanation on how to use it<br/><br/>For a detailed guide on adding new sites, check <a href="http://userscripts.org/topics/86377#posts-380342">this thread</a> in the script site'; /*todo: agregar los tests 4° td con boton test y un tr invisible abajo para el resultado requestear link[posActual] y aplicarle ese getter poder exportar/importar esta cosa poder exportar este sitio o todos los customs para mergear repetidos preguntar si quedarse con el actual o el importado */ return html; } //retorna los innerhtmls de los tds para especificar el contenido function tdsConfSitio(p, prop){ var tds = ['', '']; for(var t in prop.tipos) tds[0] += '<option value="'+t+'">'+prop.tipos[t].desc+'</option>'; tds[0] = '<select id="wcr_sitio_tipo_'+p+'">'+tds[0]+'</select>'; for(t in prop.tipos) for(var v in prop.tipos[t]){ if(v=='desc') continue; tds[1] += '<'+prop.tipos[t][v].elem+' id="wcr_sitio_valor_'+p+'_'+t+'_'+v+'"'; for(var a in prop.tipos[t][v]) if(a!='elem' && a!='html') tds[1] += ' '+a+'="'+prop.tipos[t][v][a]+'"'; tds[1] += prop.tipos[t][v].html ? '>'+prop.tipos[t][v].html+'</'+prop.tipos[t][v].elem+'>' : (prop.tipos[t][v].elem == 'textarea' ? '></textarea>' : '/>'); } return tds; } //insertar un tr para agregar mas contenido extra function trExtraConfSitio(p, prop){ var tr = document.createElement('tr'); tr.className = 'wcr_extras'; tr.id = 'wcr_tr_sitio_'+p; var tds = [ document.createElement('td'), document.createElement('td'), document.createElement('td')]; var tdsConf = tdsConfSitio(p, prop); tds[0].innerHTML = '<div style="float:right">'+ '<button id="wcr_btn_up_'+p+'">/\\</button>'+ '<button id="wcr_btn_down_'+p+'">\\/</button>'+ '<button id="wcr_btn_del_'+p+'">Delete</button>'+ '</div>'; tds[1].innerHTML = tdsConf[0]; tds[2].innerHTML = tdsConf[1]; tr.appendChild(tds[0]); tr.appendChild(tds[1]); tr.appendChild(tds[2]); var trAfterExtra = get('wcr_tr_sitio_xelem'); trAfterExtra.parentNode.insertBefore(tr, trAfterExtra); var seltipo = get('wcr_sitio_tipo_'+p); setEvt(seltipo, 'change', function(evt){ cambiaTipo(evt.target); }); setEvt('wcr_btn_del_'+p, 'click', function(evt){ var tr = evt.target.parentNode.parentNode.parentNode; tr.parentNode.removeChild(tr); }); setEvt('wcr_btn_up_'+p, 'click', function(evt){ var tr = evt.target.parentNode.parentNode.parentNode; var otro = tr.previousSibling; if(otro.id.indexOf('wcr_tr_sitio_extra_')==0){ tr.parentNode.insertBefore(tr, otro); } }); setEvt('wcr_btn_down_'+p, 'click', function(evt){ var tr = evt.target.parentNode.parentNode.parentNode; var otro = tr.nextSibling; if(otro.id.indexOf('wcr_tr_sitio_extra_')==0){ tr.parentNode.insertBefore(otro, tr); } }); } //generar el html de la conf del teclado function htmlTeclas(teclas){ var html = '<table id="wcr_teclas_tabla">'+ '<tr class="wcr_settings_group">'+ '<td/>'+ '<td>Key</td>'+ '<td>Alternate Key</td>'+ '</tr>'; for(var t in teclas) html += '<tr>'+ '<td title="'+teclas[t][1]+'">'+teclas[t][0]+'</td>'+ '<td><input id="wcr_tecla_0_'+t+'"/></td>'+ '<td><input id="wcr_tecla_1_'+t+'"/></td>'+ '</tr>'; html += '</table><br/>Press BackSpace to unset a key'; return html; } //generar el html de la conf del updater function htmlUpdater(tiposUp){ var html = '<div>Automatically check for updates every <input id="wcr_dias_update" size="3" /> days (0 = never)</div>'+ '<div>When an update is found <select id="wcr_accion_update" >'+ '<option value="0">ask and take me to the main page on userscripts.org</option>'+ (isFirefox() ? '<option value="1">ask and directly download the latest version</option>' : '')+ '<option value="2">don\'t ask and take me to the main page on userscripts.org</option>'+ (isFirefox() ? '<option value="3">don\'t ask and directly download the latest version</option>' : '')+ '</select></div>'+ '<div id="wcr_tipos_update"><br/>Check for the following kind of updates:<br/>'; for(t in tiposUp) html += '<input type="checkbox" id="wcr_cb_tipo_update_'+t+'" value="'+t+'">'+ '<label for="wcr_cb_tipo_update_'+t+'">'+tiposUp[t]+'</label><br/>'; html += '</div><br/>Last check: <span id="wcr_fecha_update">Never</span><br/>'+ '<button id="wcr_btn_check_update">Check for updates now</button>'; return html; } //guardar todo lo de las pantallas de configuracion function guardarSettings(teclas, props, tiposUp, opsLayout){ try{ //guardar teclas var hiddens = ['keyCode', 'ctrlKey', 'shiftKey', 'altKey']; for(var t in teclas){ teclado[t] = []; for(var i=0; i<2; i++){ teclado[t][i] = { name: get('wcr_tecla_'+i+'_'+t).value, keyCode: get('wcr_tecla_'+i+'_'+t+'_keyCode').value }; for(var h=1; h<hiddens.length; h++) teclado[t][i][hiddens[h]] = get('wcr_tecla_'+i+'_'+t+'_'+hiddens[h]).value == 'true'; } } setData('teclas', teclado, 'default'); //guardar layout for(var o in opsLayout){ if(!o.indexOf('_')) continue; var valdef = get('wcr_sel_layout_'+o+'_def').value; var val = get('wcr_sel_layout_'+o).value; if(o.indexOf('prefetch_')<0 || valdef.match(/^\d+$/) && Number(valdef)>0) setData(o, valdef, 'default'); if(o.indexOf('prefetch_')<0 || val === '' || val.match(/^\d+$/) && Number(val)>0){ if(val != '') setData(o, val); else delData(o); } } //guardar updater if(GM_xmlhttpRequest){ var dias = Number(get('wcr_dias_update').value); if(!isNaN(dias) && dias>=0) setData('updateDays', dias, 'default'); setData('updateAction', Number(get('wcr_accion_update').value), 'default'); var tipoUpdate = 0; for(t in tiposUp) if(get('wcr_cb_tipo_update_'+t).checked) tipoUpdate += Number(t); setData('updateFlags', tipoUpdate, 'default'); } //guardar sitio var conf = unescape(get('wcr_sel_confpag').value); if(conf == '' || conf[0]=='d') setData('confpag', conf); else{ //es new o un custom var ok = true; var tipourl = get('wcr_sitio_tipo_url').value; var nombre = 'c'+tipourl[0]+':'+get('wcr_sitio_valor_url_'+tipourl+'_val').value; var customPag = {}; for(var p in props){ if(p=='extra'){ try{ var xx = []; var extras = selCss('tr.wcr_extras', document, true); for(i=0; i<extras.length; i++){ try{ var p2 = extras[i].id.match(/extra_\d+$/)[0]; var x = parsearElementoConfSitio(p2); if(x) xx.push(x); }catch(e){ ok = false; } } customPag[p] = xx; }catch(e){} } else{ try{ x = parsearElementoConfSitio(p); if(x) customPag[p] = x; }catch(e){ ok = false; } } } if(!ok) return false; var customs = getData('confpags', {}, 'custompages'); if(conf[0]=='c' && conf!=nombre) delete customs[conf]; customs[nombre] = customPag; setData('confpags', customs, 'custompages'); setData('confpag', nombre); } }catch(e){ alert('Error saving the settings: ' + e); return false; } return true; } //leer la configuracion ingresada en los inputs y convertirla en {tipo, valor} function parsearElementoConfSitio(p){ var ok = true; var tipo = get('wcr_sitio_tipo_'+p).value; if(tipo == 'def') return false; var valor; var elems = xpath('//*[starts-with(@id,"wcr_sitio_valor_'+p+'_'+tipo+'")]', document, true); //tipos: str, re, xp, fn, bool, num? switch(tipo){ case 'str': valor = elems[0].value; break; case 're': valor = []; try{ var re; if(!elems[0].value.match(/^\/.+\/[gmi]*$/)) elems[0].value = '/'+elems[0].value+'/'; eval('re = '+elems[0].value); var tipore = Object.prototype.toString.call(re); if(tipore != "[object RegExp]") throw tipore; valor.push(elems[0].value); }catch(e){ alert(p+': "'+elems[0].value+'" is not a valid regular expression ('+e+')'); ok = false; } if(elems.length>1){ if(!elems[1].value.match(/^\d+$/) || Number(elems[1].value)==0){ alert(p+': "'+elems[1].value+'" is not a valid number'); ok = false; } else valor.push(Number(elems[1].value)); } break; case 'xp': case 'css': valor = [elems[0].value]; if(elems[1] && elems[1].value){ //si es arreglo... valor.push(elems[2].value); if(elems[4].value && !elems[3].value) elems[3].value = '0'; if(elems[3].value){ var num = Number(elems[3].value); if(!elems[3].value.match(/^[-\d]+$/) || isNaN(num)){ alert(p+': "'+elems[3].value+'" is not a valid number'); ok = false; } else valor.push(num); } if(elems[4].value){ num = Number(elems[4].value); if(!elems[4].value.match(/^[-\d]+$/) || isNaN(num)){ alert(p+': "'+elems[4].value+'" is not a valid number'); ok = false; } else valor.push(num); } } if(tipo=='css') valor = [valor]; break; case 'fn': valor = xpath('//select[@id="wcr_sitio_tipo_'+p+'"]/option[@value="fn"]').innerHTML+'{'+ elems[0].value + '}'; try{ eval('f='+valor); } catch(e){ alert(p+': "'+valor+'" is not a valid function ('+e+')'); ok = false; } break; case 'bool': valor = elems[0].value == 'true'; break; case 'num': valor = Number(elems[0].value); if(isNaN(valor)){ alert(p+': "'+elems[0].value+'" is not a valid number'); ok = false; } break; } if(p=='url'){ if(!valor){ alert('url: this field is obligatory'); ok = false; } else{ if(tipo=='str') re = strToRegexp(valor); else eval('re = '+elems[0].value); if(!document.location.href.match(re)){ alert('url: the expression '+elems[0].value+' doesn\'t match the current URL'); ok = false; } } } if(!ok) throw 'error'; return {tipo: tipo, valor: valor}; } //esconder los otros tabs y mostrar el q corresponde function cambiarTabSettings(nombre){ var tabs = xpath('//div[@id="wcr_settings_content"]/div', document, true); for(var i=0; i<tabs.length; i++) tabs[i].style.display = 'none'; xpath('//div[@class="'+nombre+'"]').style.display = ''; var spans = xpath('//div[@id="wcr_settings_links"]/span', document, true); for(i=0; i<spans.length; i++){ spans[i].style.fontWeight = 'normal'; spans[i].style.backgroundColor = ''; } var span = xpath('//span[@class="'+nombre+'"]'); span.style.fontWeight = 'bold'; span.style.backgroundColor = '#ff0'; //setear el porte y posicion var popup = get('wcr_settings_popup'); var top = document.documentElement.scrollTop; if(!top) top = document.body.scrollTop; popup.style.top = (top+10) + 'px'; popup.style.marginLeft = -popup.offsetWidth/2 + 'px'; tabSettingActual = nombre; } //busca la configuracion correspondiente a esta pagina function getConfPagina(conf){ try{ var lista = conf=='lista'; if(conf===undefined) conf = getData('confpag', ''); if(conf == 'dis') return null; var url = document.location.href; var pags = []; var customs = getData('confpags', {}, 'custompages'); if(conf && !lista){ //se quiere una especifica if(customs[conf]){ var pu = conf.substr(3); if(conf[1] == 'r') eval('pu='+pu); else pu = strToRegexp(pu); if(url.match(pu)){ var pag = parsearPaginaCustom(customs[conf]); pag.nombre = conf; return pag; } } else{ for(var i = 0; i < paginas.length; i++){ pag = paginas[i]; pu = pag.url; pu = (typeof(pu)=='string' ? 'ds:' : 'dr:') + pu; if(pu == conf){ pag.nombre = conf; return pag; } } } //no encontre la q me pidieron. si era la q tenia configurada, reseteo la conf //if(conf == getData('confpag', '')) delData('confpag'); } //si no estaba configurada o no se encontro la conf q queria, busca primero en las customs for(var p in customs){ pu = p.substr(3); if(p[1] == 'r') eval('pu='+pu); else pu = strToRegexp(pu); if(url.match(pu)){ pag = parsearPaginaCustom(customs[p]); pag.nombre = p; if(!lista) return pag; pags.push(p); } } //si todavia no encuentro (o quiero la lista de todas las confs q matcheen) sigo buscando for(i = 0; i < paginas.length; i++){ pag = paginas[i]; pu = pag.url; if(typeof(pu)=='string') pu = strToRegexp(pu); if(url.match(pu)){ p = (typeof(pag.url)=='string' ? 'ds:' : 'dr:') + pag.url; pag.nombre = p; if(!lista) return pag; pags.push(p); } } if(!lista) return {nombre:''}; return pags; } catch(e){ error('getconfpag: ' + e); return {}; } } //para matchear una url, se convierte un valor en string a regexp function strToRegexp(url){ url = url.replace(/[-[\]{}()+?.,\\^$#\s]/g, "\\$&"); url = url.replace(/\*\\\./g, '([\\w-]+\\.)?'); //'*.hola.com' matchea 'asd.hola.com' y 'hola.com', pero no 'chao.com/hola.com' url = url.replace(/\*/g, '.*'); var urls = url.split('|'); for(var j=0; j<urls.length; j++){ if(!urls[j].match(/^https?:\/\//)){ if(urls[j].match(/^[^.\/]+\\\.\w*(\/|$)/)) urls[j] = '(www\\.)?' + urls[j]; urls[j] = '^https?://' + urls[j]; } urls[j] = '('+urls[j]+')'; } return new RegExp(urls.join('|')); } //recibe la pagina en el formato en q se guarda en la conf, y la retorna en el formato usado en paginas[i] function parsearPaginaCustom(custom){ var pag = {}; for(var p in custom){ if(p == 'extra'){ var x = []; for(var i=0; i<custom[p].length; i++) x.push(parsearPropCustom(custom[p][i], p)); pag[p] = x; } else pag[p] = parsearPropCustom(custom[p]); } return pag; } //leer una propiedad en formato jsoneable y dejarla en formato estandar function parsearPropCustom(prop, p){ var tipo = prop.tipo; var valor = prop.valor; switch(tipo){ case 're': eval('valor[0] = '+valor[0]); if(p=='url') valor=valor[0]; break; case 'fn': eval('valor = '+valor); break; } return valor; } //ver si usa el motor de chrome/safari function isWebKit(){ return navigator.userAgent.indexOf('WebKit/')>0; } //ver si usa el motor de firefox function isFirefox(){ return navigator.userAgent.indexOf('Gecko/')>0; } //pantalla de configuracion q sale cuando se habilita el zoom pero no esta configurado function mostrarSettingsZoom(){ try{ var html = ''; var cbs = { achw: 'Shrink wide images to fit in the width of the screen', achh: 'Shrink high images to fit in the height of the screen', agrw: 'Expand narrow images to use the width of the screen', agrh: 'Expand short images to use the height of the screen' }; for(var p in cbs) html += '<input type="checkbox" id="wcr_set_cb_'+p+'"/> '+ '<label for="wcr_set_cb_'+p+'">'+cbs[p]+'</label><br/>'; var txts = { bordex: 'Pixels to leave as a border to the left and right', bordey: 'Pixels to leave as a border above and below the image' }; for(p in txts) html += '<input id="wcr_set_txt_'+p+'" size="2"> '+txts[p]+'<br/>'; html += '<br/><input type="checkbox" id="wcr_set_cb_def"/> '+ '<label for="wcr_set_cb_def">Use these settings as the default for every site</label><br/>'; var divsets = document.createElement('div'); divsets.id = 'wcr_settings'; divsets.style.textAlign = 'center'; divsets.innerHTML = '<div style="position:fixed; z-index:232322; background:#000; top:0; left:0; right:0; bottom:0; opacity:0.8;"></div>'+ '<div id="wcr_settings_popup" style="position:absolute; left:50%; z-index:232323; background-color:#fff; color:#000; padding: 20px;">'+ '<div>How do you want the images to be fitted?</div><hr/>'+ '<div id="wcr_settings_content" style="text-align:left">'+html+'</div><br/>'+ 'These (and more) settings can be changed later by clicking the "Settings" button<hr/>'+ '<div>'+ '<button id="wcr_set_btn_guardar" style="width:100%">Save settings</button><br/>'+ '<button id="wcr_set_btn_disable">Disable script for this site</button>'+ '</div>'+ '</div>'+ '<style>'+ '#wcr_settings_popup *{color:#000;}'+ '#wcr_settings_popup input, #wcr_settings_popup select, #wcr_settings_popup textarea{background-color:#fff;}'+ 'div{position:static; float:none;}'+ '</style>'; document.body.appendChild(divsets); //setear el porte y posicion var popup = get('wcr_settings_popup'); var top = document.documentElement.scrollTop; if(!top) top = document.body.scrollTop; popup.style.top = (top+10) + 'px'; popup.style.marginLeft = -popup.offsetWidth/2 + 'px'; //inicializar los valores for(p in cbs){ eval('var x = '+p); get('wcr_set_cb_'+p).checked = x; } setEvt('wcr_set_btn_guardar', 'click', function(){ //guardar las confs y setear las variables var dom = get('wcr_set_cb_def').checked ? 'default' : undefined; for(var p in cbs){ eval(p+' = '+get('wcr_set_cb_'+p).checked); setData(p, get('wcr_set_cb_'+p).checked ? 1 : 0, dom); } for(p in txts){ var val = Number(get('wcr_set_txt_'+p).value); if(isNaN(val)) continue; eval(p+' = '+val); setData(p, val, dom); } document.body.removeChild(divsets); fitImagen(); scrollear(); }); setEvt('wcr_set_btn_disable', 'click', function(){ if(confirm('Are you sure you want to disable Webcomic Reader on this site?\n'+ '(It can be re-enabled later with the Greasemonkey menu)')){ setData('confpag', 'dis'); redirect(link[posActual]); } }); } catch(e){ alert('Error while initializing the zoom settings window: ' + e); if(get('wcr_settings')) document.body.removeChild(get('wcr_settings')); } } run_script(); })(); /* alert( 0*1+ //'Bug fixes (Firefox)', 0*2+ //'Bug fixes (Other browsers)', 0*4+ //'New features', 0*8+ //'New sites', 0*16+ //'Fixes for old sites', 0*32+ //'Graphic changes', 0*64+ //'New options', 0*128+ //??? 0 ); */ /*todo: forma facil de extraer varias paginas a partir de un solo request (blogs, reddit, pags ajaxeadas, etc) el img tendria q recuperar una lista de resultados se agrega una funcion extra_context: function(html, pos, relpos) q retorna el contexto sobre el q se buscan los extras para cada item las urls se rellenarian con ##pos-relativa-a-la-pag los back/next buscan el link normalmente el prefetcheador avanza los n de una poder definir un contenedor para cada extra [v2] extras: {selector: [cosas, mascosas]} poder hacer extras fijos (se llenan una vez y no se buscan ni se tocan mas) [v2] agregar un contenedor de extras fijos, rellenarlo en el js o con extras: {contendorfijo: [function(html, pos){if(pos)return ''; return selector;}]} poder leer extras por ajax? function(){request sincrono} en site settings, boton para exportar a formato copypasteable al script opcion para definir cuantos links se precargan, separado de cuantas imagenes se precargan los puros html, y en un proceso aparte las imagenes cargo link, if(!cargandoimg) cargarimgs -> carga primera no cargada y sigue hasta la N select con las pags cargadas, diferenciando las con img lista cambiar condicion de img cargada para cambiar pag btnback y btnnext no avanzan si no se ha cargado la pag q viene saltar directo a una pag si funciona, y empieza a cargar las imgs alrededor cambiar condicion para sacar un img de las cargadas (actualmente mantiene la actual +-23) usar el doc magico para parsear las cosas ajaxeadas, asi no carga las imgs hacer q las funciones parseadoras reciban el html y el doc hacer una funcion htmlToDoc en vez de mantener solo las imgs en la cosa de imgs cargadas, agregar los extras next/prev chapter (+ teclas) soportar AMR en minimalistic? tener una lista de selectores "no borrar" para cada elemento "no borrar", agregarlo a una lista junto con sus ancestros para cada elemento de la lista, borrar todos los hermanos q no esten en la lista tb podria soportar el Greased Webcomic Manager cambiar la forma en q se graban los datos (el objeto actual crece mucho, el mio pesa 50kb) 1 setting por sitio 1 setting con lo default 1 setting con la lista de todos los settings usar una variable "settings" q tenga toda la conf cargada, igual q defaultSettings reemplazar las variables random q se usan ahora usar los nombres q se usan para guardar mapear nombresCoherentes -> nombresGuardados rehacer el codigo OOPmente clase q maneje el script per se clase para la conf de una pag clase para los settings clase para la pantalla de settings poder listar todos los sitios q reviso de alguna forma al guardar ultima pag visitada, guardar: url, title, fecha, img.src y next lista con la pag y la ultima fecha q se reviso (à la GreasedWebcomicManager?) avisar q hay pag nueva si cambio el img.src o next boton para forzar q se revise una pag o todas las de la lista mostrar una estrella para las favoritas, clickeable para (des)favoritear poder deshabilitar sitios boton para cambiar entre ver todos/favoritos/no-favoritos checks para mostrar [favoritos], [no-favoritos], [deshabilitados], [nueva pag] boton para agregar/quitar de los favoritos boton para deshabilitar script en este sitio boton para forzar check de pag nueva en una/todas las pags solo checkea las q no tienen pag nueva tecla para pasar al sgte tecla para pasar a un random pagina "comics del dia" usar una pag especial para rehacerla (@include *wcr_latest_comics. en ffox about:blank?wcr_..., si no google.com/wcr_... (404)) con las imagenes del dia de mis comics cada una con back/next chico (a los lados y/o con click en img)? mostrar solo las nuevas? (marcar como leidas?) tener al lado (escondida?) la lista completa de pags modo fullchapterloader mostrar todas las imagenes una bajo otra avanzar solo hacia adelante avanzar (posActual++, cargar mas pags...) al ir scrolleando mostrar las imagenes y el extra en un div poner los botones (settings/cambiar de modo) arriba mensaje al final cuando no queden mas pags (o link a la pag sin img) ????: al ir para atras, revisar si el next es el mismo, y si no es cargarlo entremedio habria q ir shifteando todo para atras hasta llenar el hoyo... o algo asi... ta dificil... en vez de rellenar, avisar? ????: borrar los extras de la pag 0? hacer mas facil la agregacion de sitios poder cambiar entre modo @include * on/off on: solo iniciar en las pags incluidas explicitamente (if(!getConfPag) break;) off: tratar de iniciar siempre (como ahora) configuracion de sitios 4° columna con boton test en propsSitio tener un elemento test, puede ser una funcion o true para el default test default: convertir a getter y obtener contenido como string agregar tr con el resultado (td[1] "Test results:" align-right, td[2,3] contenido, td[4] boton hide) poder exportar/importar esta variable para mergear repetidos preguntar si quedarse con el actual o el importado poder exportar/importar todas las pags o solo esta poder importar desde otras paginas (foro de userscripts?) @include http://userscripts.org/topics/* persona random postea sus pags exportadas el script las encuentra y las hace clickeables, onclick se importan poder centralizar esto en una pagina? lemontecho? :P personas random suben sus settings se pueden mirar e importar tener una configuracion "oficial" mantenida por mi tener un autoupdater q baje esa version wizard para agregar sitios accesible desde el menu gm pide clickear la imagen y los links carga la pag anterior y sgte, y busca img/links q coincidan con los marcados buscar por atributos, patrones, etc? despues preguntar las cosas mas basicas pasar al editor de confs ir guardando los mensajes de los cambios de las versiones no notificadas? dejar el layout mas custom-ready-pa-lo-que-benga? arreglo de layouts funciones personalizadas para los "eventos" q modifican los botones en vez de boton "toggle", poner un select con los layouts agregar pags http://www.viruscomix.com/subnormality.html incluir subreddits en vez de todo reddit http://www.harrington-artwerkes.com/Lana5.htm http://eecomics.net/?strip_id=152 http://www.shadowgirlscomic.com/comics/maxmachine-interface/ http://www.pantheracomic.com/?p=214 http://dimensiondust.blogspot.com/search?updated-max=2010-06-16T02%3A38%3A00-05%3A00&max-results=1 http://www.joelcarroll.com/topaz/page-four/ http://www.yoshcomic.com/latest.php?i=20101201 http://agirlandherfed.com/1.833.html http://www.casualvillain.com/Unsounded/comic/ch02/ch02_27.html http://undertow.dreamshards.org/3/u3_13.html http://www.sisterclaire.com/comic/chapter-6-comic/chapter-6-the-trials/ http://sarahzero.com/sz_0588.html http://www.colourofivy.com/annyseed_webcomic8.htm http://flakypastry.runningwithpencils.com/comic.php?strip_id=326 */