Powerfap

Adds full screen lightbox feature (with preloading) for imagefap galleries. Just click on image thumbnail from the category or homepage.

Fra 10.05.2019. Se den seneste versjonen.

  1. // ==UserScript==
  2. // @name Powerfap
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3
  5. // @description Adds full screen lightbox feature (with preloading) for imagefap galleries. Just click on image thumbnail from the category or homepage.
  6. // @author Alekc
  7. // @match https://www.imagefap.com/*
  8. // @require https://cdn.jsdelivr.net/npm/simple-lightbox@2.1.0/src/simpleLightbox.min.js
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. const css_lightbox = `
  13. .slbOverlay, .slbWrapOuter, .slbWrap {
  14. position: fixed;
  15. top: 0;
  16. right: 0;
  17. bottom: 0;
  18. left: 0;
  19. }
  20.  
  21. .slbOverlay {
  22. overflow: hidden;
  23. z-index: 2000;
  24. background-color: #000;
  25. opacity: 0.7;
  26. -webkit-animation: slbOverlay 0.5s;
  27. -moz-animation: slbOverlay 0.5s;
  28. animation: slbOverlay 0.5s;
  29. }
  30.  
  31. .slbWrapOuter {
  32. overflow-x: hidden;
  33. overflow-y: auto;
  34. z-index: 2010;
  35. }
  36.  
  37. .slbWrap {
  38. position: absolute;
  39. text-align: center;
  40. }
  41.  
  42. .slbWrap:before {
  43. content: "";
  44. display: inline-block;
  45. height: 100%;
  46. vertical-align: middle;
  47. }
  48.  
  49. .slbContentOuter {
  50. position: relative;
  51. display: inline-block;
  52. vertical-align: middle;
  53. margin: 0px auto;
  54. padding: 0 1em;
  55. box-sizing: border-box;
  56. z-index: 2020;
  57. text-align: left;
  58. max-width: 100%;
  59. }
  60.  
  61. .slbContentEl .slbContentOuter {
  62. padding: 5em 1em;
  63. }
  64.  
  65. .slbContent {
  66. position: relative;
  67. }
  68.  
  69. .slbContentEl .slbContent {
  70. -webkit-animation: slbEnter 0.3s;
  71. -moz-animation: slbEnter 0.3s;
  72. animation: slbEnter 0.3s;
  73. background-color: #fff;
  74. box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.4);
  75. }
  76.  
  77. .slbImageWrap {
  78. -webkit-animation: slbEnter 0.3s;
  79. -moz-animation: slbEnter 0.3s;
  80. animation: slbEnter 0.3s;
  81. position: relative;
  82. }
  83.  
  84. .slbImageWrap:after {
  85. content: "";
  86. position: absolute;
  87. left: 0;
  88. right: 0;
  89. top: 5em;
  90. bottom: 5em;
  91. display: block;
  92. z-index: -1;
  93. box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.6);
  94. background-color: #FFF;
  95. }
  96.  
  97. .slbDirectionNext .slbImageWrap {
  98. -webkit-animation: slbEnterNext 0.4s;
  99. -moz-animation: slbEnterNext 0.4s;
  100. animation: slbEnterNext 0.4s;
  101. }
  102.  
  103. .slbDirectionPrev .slbImageWrap {
  104. -webkit-animation: slbEnterPrev 0.4s;
  105. -moz-animation: slbEnterPrev 0.4s;
  106. animation: slbEnterPrev 0.4s;
  107. }
  108.  
  109. .slbImage {
  110. width: auto;
  111. max-width: 100%;
  112. height: auto;
  113. display: block;
  114. line-height: 0;
  115. box-sizing: border-box;
  116. padding: 5em 0;
  117. margin: 0 auto;
  118. }
  119.  
  120. .slbCaption {
  121. display: inline-block;
  122. max-width: 100%;
  123. overflow: hidden;
  124. text-overflow: ellipsis;
  125. white-space: nowrap;
  126. word-wrap: normal;
  127. font-size: 1.4em;
  128. position: absolute;
  129. left: 0;
  130. right: 0;
  131. bottom: 0;
  132. padding: 0.71429em 0;
  133. color: #fff;
  134. color: rgba(255, 255, 255, 0.7);
  135. text-align: center;
  136. }
  137.  
  138. .slbCloseBtn, .slbArrow {
  139. margin: 0;
  140. padding: 0;
  141. border: 0;
  142. cursor: pointer;
  143. background: none;
  144. }
  145.  
  146. .slbCloseBtn::-moz-focus-inner, .slbArrow::-moz-focus-inner {
  147. padding: 0;
  148. border: 0;
  149. }
  150.  
  151. .slbCloseBtn:hover, .slbArrow:hover {
  152. opacity: 0.5;
  153. }
  154.  
  155. .slbCloseBtn:active, .slbArrow:active {
  156. opacity: 0.8;
  157. }
  158.  
  159. .slbCloseBtn {
  160. -webkit-animation: slbEnter 0.3s;
  161. -moz-animation: slbEnter 0.3s;
  162. animation: slbEnter 0.3s;
  163. font-size: 3em;
  164. width: 1.66667em;
  165. height: 1.66667em;
  166. line-height: 1.66667em;
  167. position: absolute;
  168. right: -0.33333em;
  169. top: 0;
  170. color: #fff;
  171. color: rgba(255, 255, 255, 0.7);
  172. text-align: center;
  173. }
  174.  
  175. .slbLoading .slbCloseBtn {
  176. display: none;
  177. }
  178.  
  179. .slbLoadingText {
  180. font-size: 1.4em;
  181. color: #fff;
  182. color: rgba(255, 255, 255, 0.9);
  183. }
  184.  
  185. .slbArrows {
  186. position: fixed;
  187. top: 50%;
  188. left: 0;
  189. right: 0;
  190. }
  191.  
  192. .slbLoading .slbArrows {
  193. display: none;
  194. }
  195.  
  196. .slbArrow {
  197. position: absolute;
  198. top: 50%;
  199. margin-top: -5em;
  200. width: 5em;
  201. height: 10em;
  202. opacity: 0.7;
  203. text-indent: -999em;
  204. overflow: hidden;
  205. }
  206.  
  207. .slbArrow:before {
  208. content: "";
  209. position: absolute;
  210. top: 50%;
  211. left: 50%;
  212. margin: -0.8em 0 0 -0.8em;
  213. border: 0.8em solid transparent;
  214. }
  215.  
  216. .slbArrow.next {
  217. right: 0;
  218. }
  219.  
  220. .slbArrow.next:before {
  221. border-left-color: #fff;
  222. }
  223.  
  224. .slbArrow.prev {
  225. left: 0;
  226. }
  227.  
  228. .slbArrow.prev:before {
  229. border-right-color: #fff;
  230. }
  231.  
  232. .slbIframeCont {
  233. width: 80em;
  234. height: 0;
  235. overflow: hidden;
  236. padding-top: 56.25%;
  237. margin: 5em 0;
  238. }
  239.  
  240. .slbIframe {
  241. position: absolute;
  242. top: 0;
  243. left: 0;
  244. width: 100%;
  245. height: 100%;
  246. box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.6);
  247. background: #000;
  248. }
  249.  
  250. @-webkit-keyframes slbOverlay {
  251. from {
  252. opacity: 0;
  253. }
  254. to {
  255. opacity: 0.7;
  256. }
  257. }
  258.  
  259. @-moz-keyframes slbOverlay {
  260. from {
  261. opacity: 0;
  262. }
  263. to {
  264. opacity: 0.7;
  265. }
  266. }
  267.  
  268. @keyframes slbOverlay {
  269. from {
  270. opacity: 0;
  271. }
  272. to {
  273. opacity: 0.7;
  274. }
  275. }
  276.  
  277. @-webkit-keyframes slbEnter {
  278. from {
  279. opacity: 0;
  280. -webkit-transform: translate3d(0, -1em, 0);
  281. }
  282. to {
  283. opacity: 1;
  284. -webkit-transform: translate3d(0, 0, 0);
  285. }
  286. }
  287.  
  288. @-moz-keyframes slbEnter {
  289. from {
  290. opacity: 0;
  291. -moz-transform: translate3d(0, -1em, 0);
  292. }
  293. to {
  294. opacity: 1;
  295. -moz-transform: translate3d(0, 0, 0);
  296. }
  297. }
  298.  
  299. @keyframes slbEnter {
  300. from {
  301. opacity: 0;
  302. -webkit-transform: translate3d(0, -1em, 0);
  303. -moz-transform: translate3d(0, -1em, 0);
  304. -ms-transform: translate3d(0, -1em, 0);
  305. -o-transform: translate3d(0, -1em, 0);
  306. transform: translate3d(0, -1em, 0);
  307. }
  308. to {
  309. opacity: 1;
  310. -webkit-transform: translate3d(0, 0, 0);
  311. -moz-transform: translate3d(0, 0, 0);
  312. -ms-transform: translate3d(0, 0, 0);
  313. -o-transform: translate3d(0, 0, 0);
  314. transform: translate3d(0, 0, 0);
  315. }
  316. }
  317.  
  318. @-webkit-keyframes slbEnterNext {
  319. from {
  320. opacity: 0;
  321. -webkit-transform: translate3d(4em, 0, 0);
  322. }
  323. to {
  324. opacity: 1;
  325. -webkit-transform: translate3d(0, 0, 0);
  326. }
  327. }
  328.  
  329. @-moz-keyframes slbEnterNext {
  330. from {
  331. opacity: 0;
  332. -moz-transform: translate3d(4em, 0, 0);
  333. }
  334. to {
  335. opacity: 1;
  336. -moz-transform: translate3d(0, 0, 0);
  337. }
  338. }
  339.  
  340. @keyframes slbEnterNext {
  341. from {
  342. opacity: 0;
  343. -webkit-transform: translate3d(4em, 0, 0);
  344. -moz-transform: translate3d(4em, 0, 0);
  345. -ms-transform: translate3d(4em, 0, 0);
  346. -o-transform: translate3d(4em, 0, 0);
  347. transform: translate3d(4em, 0, 0);
  348. }
  349. to {
  350. opacity: 1;
  351. -webkit-transform: translate3d(0, 0, 0);
  352. -moz-transform: translate3d(0, 0, 0);
  353. -ms-transform: translate3d(0, 0, 0);
  354. -o-transform: translate3d(0, 0, 0);
  355. transform: translate3d(0, 0, 0);
  356. }
  357. }
  358.  
  359. @-webkit-keyframes slbEnterPrev {
  360. from {
  361. opacity: 0;
  362. -webkit-transform: translate3d(-4em, 0, 0);
  363. }
  364. to {
  365. opacity: 1;
  366. -webkit-transform: translate3d(0, 0, 0);
  367. }
  368. }
  369.  
  370. @-moz-keyframes slbEnterPrev {
  371. from {
  372. opacity: 0;
  373. -moz-transform: translate3d(-4em, 0, 0);
  374. }
  375. to {
  376. opacity: 1;
  377. -moz-transform: translate3d(0, 0, 0);
  378. }
  379. }
  380.  
  381. @keyframes slbEnterPrev {
  382. from {
  383. opacity: 0;
  384. -webkit-transform: translate3d(-4em, 0, 0);
  385. -moz-transform: translate3d(-4em, 0, 0);
  386. -ms-transform: translate3d(-4em, 0, 0);
  387. -o-transform: translate3d(-4em, 0, 0);
  388. transform: translate3d(-4em, 0, 0);
  389. }
  390. to {
  391. opacity: 1;
  392. -webkit-transform: translate3d(0, 0, 0);
  393. -moz-transform: translate3d(0, 0, 0);
  394. -ms-transform: translate3d(0, 0, 0);
  395. -o-transform: translate3d(0, 0, 0);
  396. transform: translate3d(0, 0, 0);
  397. }
  398. }
  399. .lds-ellipsis {
  400. display: inline-block;
  401. position: relative;
  402. width: 64px;
  403. height: 64px;
  404. }
  405. .lds-ellipsis div {
  406. position: absolute;
  407. top: 27px;
  408. width: 11px;
  409. height: 11px;
  410. border-radius: 50%;
  411. background: #fff;
  412. animation-timing-function: cubic-bezier(0, 1, 1, 0);
  413. }
  414. .lds-ellipsis div:nth-child(1) {
  415. left: 6px;
  416. animation: lds-ellipsis1 0.6s infinite;
  417. }
  418. .lds-ellipsis div:nth-child(2) {
  419. left: 6px;
  420. animation: lds-ellipsis2 0.6s infinite;
  421. }
  422. .lds-ellipsis div:nth-child(3) {
  423. left: 26px;
  424. animation: lds-ellipsis2 0.6s infinite;
  425. }
  426. .lds-ellipsis div:nth-child(4) {
  427. left: 45px;
  428. animation: lds-ellipsis3 0.6s infinite;
  429. }
  430. @keyframes lds-ellipsis1 {
  431. 0% {
  432. transform: scale(0);
  433. }
  434. 100% {
  435. transform: scale(1);
  436. }
  437. }
  438. @keyframes lds-ellipsis3 {
  439. 0% {
  440. transform: scale(1);
  441. }
  442. 100% {
  443. transform: scale(0);
  444. }
  445. }
  446. @keyframes lds-ellipsis2 {
  447. 0% {
  448. transform: translate(0, 0);
  449. }
  450. 100% {
  451. transform: translate(19px, 0);
  452. }
  453. }
  454. #overlay {
  455.  
  456. display:none;
  457. }
  458. #overlay .lds-ellipsis {
  459. position: absolute;
  460. top: 50%;
  461. left: 50%;
  462. transform: translate(-50%, -50%);
  463. }
  464. `;
  465.  
  466. const loadingSplashScreenHtml = `<div id='overlay' class="slbOverlay"><div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div></div>`
  467. var $ = window.$;
  468. const galRegex = /\/photo\/(\d+)/m;
  469. const homeRegex = /image\.php\?id=(\d+)/m;
  470.  
  471. var preloadedImages = [];
  472. var lightBox;
  473. (function() {
  474. 'use strict';
  475.  
  476. //prepare lightBox
  477. $("body").append("<style>" + css_lightbox + "</style>" + loadingSplashScreenHtml);
  478.  
  479. //link from category page
  480. $("img.gal_thumb").parent("a").click(function(){
  481. event.preventDefault();
  482. showOverlay();
  483. var match = galRegex.exec($(this).attr("href"));
  484. if (match == null){
  485. alert("can't find photo id");
  486. return;
  487. }
  488.  
  489.  
  490. var galId = $(this).closest("tr[valign='top']").prev().attr("id");
  491. var photoId = match[1];
  492. run(photoId, galId,[]);
  493. });
  494.  
  495. $('a[href*="image.php?id="]').click(function(){
  496. event.preventDefault();
  497. showOverlay();
  498. var match = homeRegex.exec($(this).attr("href"));
  499. if (match == null){
  500. alert("can't find photo id");
  501. return;
  502. }
  503.  
  504. var galId = $(this).closest("tr:not([bgcolor])").prev().attr("id");
  505. var photoId = match[1];
  506. run(photoId, galId,[]);
  507. });
  508. //
  509. })();
  510.  
  511. function showOverlay(){
  512. $("#overlay").show();
  513. }
  514. function hideOverlay(){
  515. $("#overlay").hide();
  516. }
  517. function run(photoId, galId, result){
  518. var url = "https://www.imagefap.com/photo/"+ photoId +"/?gid=" + galId + "&idx=" + result.length + "&partial=true";
  519. $.ajax({
  520. url: url,
  521. type: "GET",
  522. dataType: "html",
  523. success: function(data) {
  524. var newLinks = [];
  525. $(data).find("a").each(function(){
  526. newLinks.push($(this).attr("href"));
  527. });
  528. result = result.concat(newLinks);
  529. if (newLinks.length == 0 || newLinks.length < 24) {
  530. //todo: generate library
  531. generateLightBox(result);
  532. return;
  533. }
  534. run(photoId, galId, result);
  535. },
  536. error: function(jqXHR, textStatus,errorThrown ){
  537. alert("Error: "+ textStatus + " (" + errorThrown + ")");
  538. hideOverlay();
  539. }
  540. });
  541. }
  542.  
  543. function generateLightBox(result){
  544. lightBox = SimpleLightbox.open({
  545. items: result
  546. });
  547.  
  548. //$(lightBox.$content).parent().find("button.next").click(preloadNextSlide);
  549. lightBox.next = function (event){
  550. this.showPosition(this.currentPosition + 1);
  551. var preloadCount = 5;
  552. if (this.currentPosition + preloadCount <= this.items.length){
  553. preloadImage(this.items[this.currentPosition + preloadCount]);
  554. }
  555. }
  556. //preload first x
  557. for (var i = 1; i<6;i++){
  558. preloadImage(result[i]);
  559. }
  560. hideOverlay();
  561. lightBox.show();
  562. }
  563. function preloadImage(href){
  564. if (href === 'undefined' || typeof(preloadedImages[href]) !== 'undefined'){
  565. return;
  566. }
  567. preloadedImages[href] = new Image();
  568. preloadedImages[href].src = href;
  569. }