JAVBUS larger thumbnails Test

replace thumbnails of javbus,javdb,javlibrary and avmoo with source images

Fra og med 01.06.2021. Se den nyeste version.

  1. // ==UserScript==
  2. // @name JAVBUS larger thumbnails Test
  3. // @name:zh-CN JAVBUS封面大图 测试
  4. // @namespace https://github.com/kygo233/tkjs
  5. // @version 20210601
  6. // @author kygo233
  7. // @description replace thumbnails of javbus,javdb,javlibrary and avmoo with source images
  8. // @description:zh-CN javbus,javdb,javlibrary,avmoo替换封面为源图
  9.  
  10. // @include *javbus.com/*
  11. // @include *javdb.com/*
  12. // @include *avmoo.cyou/*
  13. // @include *javlibrary.com/*
  14. // @include /^.*(javbus|busfan|fanbus|buscdn|cdnbus|dmmsee|seedmm|busdmm|busjav)\..*$/
  15. // @include /^.*(javdb)[0-9]?\..*$/
  16. // @include /^.*(avmoo)\..*$/
  17.  
  18. // @require https://cdn.jsdelivr.net/npm/vanilla-lazyload@17.3.0/dist/lazyload.min.js
  19.  
  20. // @grant GM_addStyle
  21. // @grant GM_xmlhttpRequest
  22. // @grant GM_getValue
  23. // @grant GM_setValue
  24. // @grant GM_download
  25. // @grant GM_setClipboard
  26. // @connect *
  27.  
  28. // 2021-06-01 修复多列布局下 图片样式失效的问题
  29. // 2021-05-31 JavDb添加磁力功能;解决已点击链接颜色失效问题;对大于标准宽高比的图片进行缩放;
  30. // 2021-05-06 适配javlibrary;添加标题全显样式控制;自动翻页开关无需刷新页面;删除高清图标的显示控制
  31. // 2021-04-04 适配JAVDB;点击图片弹出新窗口;标题默认显示一行;调整样式;增加英文显示
  32. // 2021-03-09 恢复高清字幕图标的显示
  33. // 2021-02-06 新增图片懒加载插件;重调样式;优化按钮效果,切换样式不刷新页面;磁力界面新增演员表样品图显示;
  34. // 2021-01-18 适配AVMOO网站;无码页面屏蔽竖图模式;调整域名匹配规则
  35. // 2021-01-01 新增宽度调整功能;
  36. // 2020-12-29 解决半图模式下 竖图显示不全的问题;
  37. // 2020-10-16 解决功能开关取默认值为undefined的bug
  38. // 2020-10-16 解决和"JAV老司机"同时运行时样式冲突问题,需关闭老司机的瀑布流
  39. // 2020-10-14 收藏界面只匹配影片;下载图片文件名添加标题;新增复制番号、标题功能;视频截图文件下载;封面显示半图;增加样式开关
  40. // 2020-09-20 收藏界面的适配
  41. // 2020-08-27 适配更多界面
  42. // 2020-08-26 修复查询结果为1个时,item宽度为100%的问题
  43. // 2020-08-26 添加瀑布流
  44. // 2020-08-24 第一版:封面大图、下载封面、查看视频截图
  45. // ==/UserScript==
  46.  
  47. (function () {
  48. 'use strict';
  49. let statusDefault = {
  50. autoPage: false,
  51. copyBtn :true,
  52. toolBar: true,
  53. avInfo:true,
  54. halfImg:false,
  55. fullTitle:false,
  56. waterfallWidth:100,
  57. columnNumFull:3,
  58. columnNumHalf:4
  59. };
  60. const IMG_SUFFIX = "-screenshot-tag";
  61. const AVINFO_SUFFIX = "-avInfo-tag";
  62. const blogjavSelector= "#content h2.entry-title>a";
  63. const fullImgCSS=`width: 100%!important;height:100%!important;`;
  64. const halfImgCSS=`position: relative;left: -112%;width: 212% !important;height: 100% !important;max-width: 212%;`;
  65.  
  66. const copy_Svg = `<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16" height="16" viewBox="0 0 16 16"><path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z"/></svg>`;
  67. const download_Svg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="tool-svg" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1 8a7 7 0 1 0 14 0A7 7 0 0 0 1 8zm15 0A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.5 4.5a.5.5 0 0 0-1 0v5.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V4.5z"/></svg>`;
  68. const picture_Svg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="tool-svg" viewBox="0 0 16 16"><path d="M6.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/><path d="M2.002 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2h-12zm12 1a1 1 0 0 1 1 1v6.5l-3.777-1.947a.5.5 0 0 0-.577.093l-3.71 3.71-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12V3a1 1 0 0 1 1-1h12z"/></svg>`;
  69. const magnet_Svg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="tool-svg" x="0px" y="0px" viewBox="0 0 1000 1000" ><g><g transform="translate(0.000000,460.000000) scale(0.100000,-0.100000)"><path d="M4171.6,3994c-183.9-13.4-515.3-67.1-706.9-113c-770.2-187.7-1448.4-563.3-2021.2-1118.8c-707-685.9-1130.3-1494.4-1299-2481c-59.4-358.3-59.4-1002,0-1360.2c157.1-923.4,546-1705.1,1172.5-2354.6c695.4-722.3,1534.6-1159.1,2548.1-1325.7c174.4-28.7,388.9-34.5,1643.8-40.2l1440.7-7.7v1302.8v1302.8l-1354.5,7.6c-1207,5.7-1369.8,9.6-1480.9,40.2c-448.3,116.9-785.5,335.3-1036.5,666.7c-252.9,339.1-364,666.7-364,1088.2s111.1,749.1,364,1088.2c241.4,318,595.8,551.8,1000.1,659.1c157.1,40.2,191.6,42.1,1517.3,47.9l1354.5,7.7v1302.8v1300.9l-1344.9-3.8C4863.3,4001.6,4219.5,3997.8,4171.6,3994z"/><path d="M7620.1,2704.6V1401.8h1139.9H9900v1302.8v1302.8H8760.1H7620.1V2704.6z"/><path d="M7620.1-3502.7v-1302.8h1139.9H9900v1302.8v1302.8H8760.1H7620.1V-3502.7z"/></g></g></svg>`;
  70.  
  71. const LOCALE = {
  72. zh: {
  73. menuText :'设置',
  74. menu_autoPage: '鼠标滚轮翻页',
  75. menu_copyBtn :'复制图标',
  76. menu_toolBar: '功能图标',
  77. menu_avInfo:'弹窗中的演员和样品图',
  78. menu_halfImg:'竖图模式',
  79. menu_fullTitle:'标题全显',
  80. menu_columnNum:'列',
  81. copyButton:'复制',
  82. copySuccess:'复制成功',
  83. getAvImg_norespond:'blogjav.net网站暂时无法响应',
  84. getAvImg_none:'未搜索到',
  85. tool_magnetTip:'磁力',
  86. tool_downloadTip:'下载封面',
  87. tool_pictureTip:'视频截图(blogjav.net)',
  88. scrollerPlugin_end:'完'
  89. },
  90. en: {
  91. menuText :'Settings',
  92. menu_autoPage:'turn pages by mouse wheel',
  93. menu_copyBtn:'copy icon',
  94. menu_toolBar:'tools icon',
  95. menu_avInfo:'actors and sample images in pop-ups',
  96. menu_halfImg:'Vertical image mode',
  97. menu_fullTitle:'Full Title',
  98. menu_columnNum:'columns',
  99. copyButton:'Copy',
  100. copySuccess:'Copy successful',
  101. getAvImg_norespond:'blogjav.net is temporarily unable to respond',
  102. getAvImg_none:'Not found',
  103. tool_magnetTip:'Magnet',
  104. tool_downloadTip:'Download cover',
  105. tool_pictureTip:'Video screenshot from blogjav.net',
  106. scrollerPlugin_end:'End'
  107. }
  108. }
  109. let getlanguage = () => {
  110. let local= navigator.language;
  111. local = local.toLowerCase().replace('_', '-');
  112. if (local in LOCALE){
  113. return LOCALE[local];
  114. }else if (local.split('-')[0] in LOCALE){
  115. return LOCALE[local.split('-')[0]];
  116. }else {
  117. return LOCALE.en;
  118. }
  119. }
  120. let lang = getlanguage();
  121.  
  122. function showAlert(msg){
  123. var $alert=$(`<div class="alert-zdy" ></div>`);
  124. $('body').append($alert);
  125. $alert.text(msg);
  126. $alert.show({start:function(){
  127. $(this).css({'margin-top': -$(this).height() / 2 });
  128. $(this).css({'margin-left': -$(this).width() / 2 });
  129. }}).delay(3000).fadeOut();
  130. }
  131.  
  132. let tool_Func = {
  133. autoPage: function () {
  134. if(scroller){
  135. scroller.destroy();
  136. scroller=null;
  137. }else{
  138. scroller= new ScrollerPlugin($('#waterfall-zdy'),lazyLoad);
  139. }
  140. },
  141. copyBtn: function () {
  142. $("#waterfall-zdy .copy-svg").toggle();
  143. },
  144. toolBar: function () {
  145. $("#waterfall-zdy .func-div").toggle();
  146. },
  147. halfImg:function () {
  148. let me = this;
  149. $("#waterfall-zdy .movie-box-b img.loaded").each(function (index,el) {
  150. me.imgCallback(el);
  151. });
  152. var columnNum = Status.getColumnNum();
  153. GM_addStyle('#waterfall-zdy .item-b{ width: ' + 100 / columnNum + '%;}');
  154. $("#columnNum_range").val(columnNum);
  155. $("#columnNum_range+span").text(columnNum);
  156. },
  157. fullTitle : function(){
  158. $("#waterfall-zdy a[name='av-title']").toggleClass("titleNowrap");
  159. },
  160. avInfo: function () { },
  161. columnNum: function (columnNum) {
  162. GM_addStyle('#waterfall-zdy .item-b{ width: ' + 100 / columnNum + '%;}');
  163. },
  164. waterfallWidth: function (width) {
  165. var widthSelctor=currentObj.widthSelector;
  166. $(widthSelctor).css("width", width + "%");
  167. $(widthSelctor).css("margin", "0 " + (width>100?(100-width)/2+"%":"auto"));
  168. },
  169. imgCallback:function (img) {
  170. if (Status.isHalfImg()) {
  171. if(img.height < img.width){
  172. img.style= halfImgCSS ;
  173. }else{
  174. img.style= fullImgCSS ;
  175. }
  176. }else{
  177. if(img.height/img.width>=0.7){
  178. img.style= `width:${img.width*67.25/img.height}%;` ;
  179. }else{
  180. img.style= fullImgCSS ;
  181. }
  182. }
  183. }
  184. };
  185.  
  186. let Status = {
  187. halfImg_block:false,
  188. set : function(key,value){
  189. if(key=="columnNum") {
  190. key=key+(this.isHalfImg()?"Half":"Full");
  191. }else if(key=="waterfallWidth"){
  192. key=key+"_"+currentWeb;
  193. }
  194. return GM_setValue(key, value);
  195. },
  196. get : function(key){
  197. return GM_getValue(key=="waterfallWidth"?(key+"_"+currentWeb):key, statusDefault[key]);
  198. },
  199. isHalfImg: function () {
  200. return this.get("halfImg") && (!this.halfImg_block);
  201. },
  202. getColumnNum: function () {
  203. var key= 'columnNum'+(this.isHalfImg()?"Half":"Full");
  204. return this.get(key);
  205. }
  206. };
  207.  
  208. class Popover{
  209. show(el){
  210. if(el) {$(el).removeClass("svg-loading")};
  211. document.documentElement.classList.add("scrollBarHide");
  212. this.element.show({duration:0,start:function(){
  213. var t=$(this).find('#modal-div');
  214. t.css({'margin-top': Math.max(0, ($(window).height() - t.height()) / 2) });
  215. }});
  216. }
  217. hide(){
  218. document.documentElement.classList.remove("scrollBarHide");
  219. this.element.hide();
  220. this.element.find('.pop-up-tag').hide();
  221. }
  222. init(){
  223. var me=this;
  224. me.element = $('<div id="myModal"><div id="modal-div" > </div></div>');
  225. me.element.on('click',function(e){
  226. if($(e.target).closest("#modal-div").length==0){
  227. me.hide();
  228. }
  229. });
  230. me.scrollBarWidth = me.getScrollBarWidth();
  231. GM_addStyle('.scrollBarHide{ padding-right: ' + me.scrollBarWidth + 'px;overflow:hidden;}');
  232. $('body').append(me.element);
  233. if(currentWeb=="javbus"){
  234. me.element.magnificPopup({
  235. delegate: 'a.sample-box-zdy:visible',
  236. type: 'image',
  237. closeOnContentClick: false,
  238. closeBtnInside: false,
  239. mainClass: 'mfp-with-zoom mfp-img-mobile',
  240. image: {
  241. verticalFit: true
  242. },
  243. gallery: {
  244. enabled: true
  245. },
  246. zoom: {
  247. enabled: true,
  248. duration: 300,
  249. opener: function (element) {
  250. return element.find('img');
  251. }
  252. }
  253. });
  254. }
  255. }
  256. append(elem){
  257. if(!this.element){ this.init();}
  258. this.element.find("#modal-div").append(elem);
  259. }
  260. getScrollBarWidth() {
  261. var el = document.createElement("p");
  262. var styles = {width: "100px",height: "100px",overflowY: "scroll" };
  263. for (var i in styles) {
  264. el.style[i] = styles[i];
  265. }
  266. document.body.appendChild(el);
  267. var scrollBarWidth = el.offsetWidth - el.clientWidth;
  268. el.remove();
  269. return scrollBarWidth;
  270. }
  271. }
  272.  
  273. function addMenu() {
  274. var columnNum = Status.getColumnNum();
  275. var $menu = $('<div id="menu-div" ></div>');
  276. $menu.append(creatCheckbox("autoPage", lang.menu_autoPage));
  277. $menu.append(creatCheckbox("copyBtn", lang.menu_copyBtn));
  278. $menu.append(creatCheckbox("toolBar", lang.menu_toolBar));
  279. $menu.append(creatCheckbox("halfImg", lang.menu_halfImg,Status.halfImg_block));
  280. if (currentWeb == 'javbus') {
  281. $menu.append(creatCheckbox("avInfo", lang.menu_avInfo));
  282. }
  283. $menu.append(creatCheckbox("fullTitle", lang.menu_fullTitle));
  284. $menu.append(creatRange("columnNum", lang.menu_columnNum, columnNum, 8));
  285. $menu.append(creatRange("waterfallWidth", '%', waterfallWidth, currentObj.maxWidth?currentObj.maxWidth:100));
  286. var $spanner = $(currentObj.menu.html);
  287. $spanner.append($menu);
  288. $spanner.mouseenter(()=>$menu.show()).mouseleave(()=>$menu.hide());
  289. $(currentObj.menu.position).append($spanner);
  290. }
  291.  
  292. function creatCheckbox(tagName, name,disabled) {
  293. var $checkbox = $(`<div class="switch-div"><input ${disabled?'disabled="disabled"':''} type="checkbox" id="${tagName}_checkbox" /><label for="${tagName}_checkbox" >${name}</label></div>`);
  294. $checkbox.find("input")[0].checked = Status.get(tagName);
  295. $checkbox.find("input").eq(0).click(function () {
  296. Status.set(tagName, this.checked);
  297. tool_Func[tagName]();
  298. });
  299. return $checkbox;
  300. }
  301. function creatRange(tagName, name, value, max) {
  302. var $range = $(`<div class="range-div"><input type="range" id="${tagName}_range" min="1" max="${max}" step="1" value="${value}" /><span name="value">${value}</span><span>${name}</span></div>`);
  303. $range.bind('input propertychange', function () {
  304. var val = $(this).find("input").eq(0).val();
  305. $(this).find("span[name=value]").html(val);
  306. Status.set(tagName, val);
  307. tool_Func[tagName](val);
  308. });
  309. return $range;
  310. }
  311.  
  312. function showMagnetTable(avid, href,elem) {
  313. if ($(elem).hasClass("svg-loading")) {return;}
  314. $(elem).addClass("svg-loading");
  315. let $el=$(`.pop-up-tag[name='${avid}${AVINFO_SUFFIX}']`);
  316. if ($el.length > 0) {
  317. $el.show();
  318. myModal.show(elem);
  319. } else {
  320. switch(currentWeb) {
  321. case "javbus": {
  322. getMagnet(avid).then(avInfo_c => {
  323. myModal.append(avInfo_c.avatar_waterfall);
  324. myModal.append(avInfo_c.sample_waterfall);
  325. myModal.append(avInfo_c.magnetTable);
  326. myModal.show(elem);
  327. });
  328. break;
  329. }
  330. case "javdb": {
  331. getMagnet4JavDB(avid,href).then(avInfo => {
  332. myModal.append(avInfo);
  333. myModal.show(elem);
  334. });;
  335. break;
  336. }
  337. }
  338. }
  339. }
  340. function getMagnet4JavDB(avid,href) {
  341. return fetch(href).then(response => response.text()).then(doc => {
  342. let $doc=$($.parseHTML(doc));
  343. let actors= $doc.find("div.video-meta-panel .panel-block").toArray().find(el=> $(el).find("a[href^='/actors/']").length>0);
  344. let preview_images= $doc.find(".columns").toArray().find(el=> $(el).find("div.tile-images.preview-images").length>0);
  345. $(preview_images).find("img[data-src]").each((i,el)=> $(el).attr("src",$(el).attr("data-src")));
  346. let magnetTable = $doc.find(`div[data-controller="review"]`);
  347. let info = $(`<div class="pop-up-tag" name="${avid}${AVINFO_SUFFIX}"></div>`);
  348. info.append(actors);info.append(preview_images);info.append(magnetTable);
  349. return info;
  350. })
  351. };
  352. function getMagnet(avid, src) {
  353. //有码和欧美 0 无码 1
  354. var uc_code = location.pathname.search(/(uncensored|mod=uc)/) < 1 ? 0 : 1;
  355. return avInfofetch(avid).then(avInfo_c => {
  356. var gid = avInfo_c.gid;
  357. var url = `${location.protocol}//${location.hostname}/ajax/uncledatoolsbyajax.php?gid=${gid}&lang=zh&img=${src}&uc=${uc_code}&floor=` + Math.floor(Math.random() * 1e3 + 1);
  358. return fetch(url).then(response => response.text())
  359. .then(doc => {
  360. var table_html = doc.substring(0, doc.indexOf('<script')).trim();
  361. var table_tag = $(`<table class="table pop-up-tag" name="${avid}${AVINFO_SUFFIX}" style="background-color:#FFFFFF;" ></table>`);
  362. table_tag.append($(table_html));
  363. table_tag.find("tr").each(function (i) { // 遍历 tr
  364. var me = this;
  365. if ($(me).find('a').length == 0) {
  366. return true;
  367. }
  368. var magent_url = $(me).find('a')[0].href;
  369. addCopybutton(me, magent_url);
  370. });
  371. avInfo_c.magnetTable = table_tag;
  372. return avInfo_c;
  373. })
  374. });
  375. };
  376.  
  377. function avInfofetch(avid) {
  378. return fetch(`${location.protocol}//${location.hostname}/`+avid) .then(response => response.text())
  379. .then(doc => {
  380. var str = /var\s+gid\s+=\s+(\d{1,})/.exec(doc);
  381. var gid = str[1];
  382. var avInfo_c={avid:avid};
  383. avInfo_c.gid=gid;
  384. if(Status.get("avInfo")){
  385. var sample_waterfall = $($.parseHTML(doc)).find("#sample-waterfall");
  386. var avatar_waterfall = $($.parseHTML(doc)).find("#avatar-waterfall");
  387. if(sample_waterfall.length>0){
  388. sample_waterfall[0].id = "";
  389. sample_waterfall.addClass("pop-up-tag");
  390. sample_waterfall.attr("name",avid + AVINFO_SUFFIX);
  391. sample_waterfall.find(".sample-box").removeClass("sample-box").addClass("sample-box-zdy");
  392. }
  393. if(avatar_waterfall.length>0){
  394. avatar_waterfall[0].id = "";
  395. avatar_waterfall.addClass("pop-up-tag");
  396. avatar_waterfall.attr("name",avid + AVINFO_SUFFIX);
  397. avatar_waterfall.find("a.avatar-box span").each((i,el)=> {
  398. let $copySvg = $(`<div style="width:24px;height:24px;display: flex;align-items: center;justify-content: center;">${copy_Svg}</div>`);
  399. $copySvg.click(function () {
  400. GM_setClipboard($(el).text());
  401. showAlert(lang.copySuccess);
  402. return false;
  403. });
  404. $(el).prepend($copySvg);
  405. });
  406. avatar_waterfall.find("a.avatar-box").attr("target","_blank").removeClass("avatar-box").addClass("avatar-box-zdy");
  407. }
  408. avInfo_c.sample_waterfall=sample_waterfall;
  409. avInfo_c.avatar_waterfall=avatar_waterfall;
  410. }
  411. return avInfo_c;
  412. }).catch(err => alert(err));
  413. };
  414.  
  415. function addCopybutton(tag, text) {
  416. var copyButton = $(`<button class="center-block">${lang.copyButton}</button>`);
  417. copyButton.click(function () {
  418. var btn = this;
  419. GM_setClipboard(text);
  420. showAlert(lang.copySuccess);
  421. });
  422. var td_tag = $('<td></td>');
  423. td_tag.append(copyButton);
  424. $(tag).prepend(td_tag);
  425. }
  426.  
  427. function showBigImg(avid,elem) {
  428. let $selector = $(`.pop-up-tag[name='${avid}${IMG_SUFFIX}']`);
  429. if ($selector.length > 0) {
  430. $selector.show();
  431. myModal.show();
  432. } else {
  433. getAvImg(avid,elem);
  434. }
  435. }
  436.  
  437. function getAvImg(avid, elem) {
  438. if ($(elem).hasClass("svg-loading")) {return;}
  439. $(elem).addClass("svg-loading");
  440. GM_xmlhttpRequest({
  441. method: "GET",
  442. url: 'http://blogjav.net/?s=' + avid,
  443. onload: function (result) {
  444. if (result.status !== 200) {
  445. showAlert(lang.getAvImg_norespond);
  446. $(elem).removeClass("svg-loading");
  447. return;
  448. }
  449. var doc = result.responseText;
  450. let a_array = $($.parseHTML(doc)).find(blogjavSelector);
  451. let imgUrl;
  452. if(a_array.length){
  453. imgUrl= a_array[0].href;
  454. for (let i = 0; i < a_array.length; i++) {
  455. let tempUrl = a_array[i].href;
  456. if (tempUrl.search(/FHD/i) > 0) {
  457. imgUrl = tempUrl;
  458. break;
  459. }
  460. }
  461. }
  462. if (!imgUrl) {
  463. showAlert(lang.getAvImg_none);
  464. $(elem).removeClass("svg-loading");
  465. return;
  466. }
  467. GM_xmlhttpRequest({
  468. method: "GET",
  469. url: imgUrl,
  470. headers: {
  471. referrer: "http://pixhost.to/"
  472. },
  473. onload: function (XMLHttpRequest) {
  474. var bodyStr = XMLHttpRequest.responseText;
  475. var img_src_arr = /<img .*data-src="https:\/\/.*pixhost.to\/thumbs\/.*>/.exec(bodyStr);
  476. if (img_src_arr) {
  477. var src = $(img_src_arr[0]).attr("data-src").replace('thumbs', 'images').replace('//t', '//img').replace('"', '');
  478. console.log(src);
  479. var height = $(window).height();
  480. var img_tag = $(`<div name="${avid}${IMG_SUFFIX}" class="pop-up-tag" ><img style="min-height:${height}px;width:100%" src="${src}" /></div>`);
  481. var downloadBtn = $(`<span class="download-icon" >${download_Svg}</span>`);
  482. downloadBtn.click(function () {
  483. GM_download(src, avid + ".jpg");
  484. });
  485. $(img_tag).prepend(downloadBtn);
  486. myModal.append(img_tag);
  487. myModal.show();
  488. }else if(bodyStr.match("404 Not Found")){
  489. showAlert(lang.getAvImg_norespond);
  490. }
  491. $(elem).removeClass("svg-loading");
  492. }
  493. });
  494. }
  495. });
  496. };
  497.  
  498. let myModal;
  499. let currentWeb ;
  500. let currentObj ;
  501. let ConstCode = {
  502. javbus: {
  503. domainReg: /(javbus|busfan|fanbus|buscdn|cdnbus|dmmsee|seedmm|busdmm|busjav)\./i,
  504. excludePages: ['/actresses', 'mdl=favor&sort=1', 'mdl=favor&sort=2', 'mdl=favor&sort=3', 'mdl=favor&sort=4', 'searchstar'],
  505. halfImg_block_Pages:['/uncensored','javbus.one','mod=uc'],
  506. menu:{
  507. position:'#navbar ul:first',
  508. html:`<li class='dropdown'><a class='dropdown-toggle'>${lang.menuText}</a></li>`
  509. },
  510. gridSelector: 'div#waterfall',
  511. itemSelector: 'div#waterfall div.item',
  512. widthSelector : '#waterfall-zdy',
  513. pageNext:'a#next',
  514. pageSelector:'.pagination',
  515. getAvItem: function (elem) {
  516. var photoDiv = elem.find("div.photo-frame")[0];
  517. var href = elem.find("a")[0].href;
  518. var img = $(photoDiv).children("img")[0];
  519. var src = img.src;
  520. if (src.match(/pics.dmm.co.jp/)) {
  521. src = src.replace(/ps.jpg/, "pl.jpg");
  522. } else {
  523. src = src.replace(/thumbs/, "cover").replace(/thumb/, "cover").replace(/.jpg/, "_b.jpg");
  524. }
  525. var title = img.title;
  526. var AVID = elem.find("date").eq(0).text();
  527. var date = elem.find("date").eq(1).text();
  528. var itemTag = "";elem.find("div.photo-info .btn").toArray().forEach( x=> itemTag+=x.outerHTML);
  529. return {AVID: AVID,href: href,src: src,title: title,date: date,itemTag:itemTag};
  530. }
  531. },
  532. javdb: {
  533. domainReg: /(javdb)[0-9]?\./i,
  534. excludePages: ['/users/'],
  535. halfImg_block_Pages:['/uncensored','/western','/video_uncensored','/video_western'],
  536. menu:{
  537. position:'#navbar-menu-hero .navbar-start',
  538. html:`<div class='navbar-item' >${lang.menuText}</div>`
  539. },
  540. gridSelector: 'div#videos>.grid',
  541. itemSelector: 'div#videos>.grid div.grid-item',
  542. widthSelector : '#waterfall-zdy',
  543. pageNext: 'a.pagination-next',
  544. pageSelector:'.pagination-list',
  545. init_Style: function(){
  546. var local_color=$(".box").css("background-color");
  547. if(local_color=="rgb(18, 18, 18)"){
  548. GM_addStyle(`.scroll-request span{background:white;}a[name="av-title"]:link {color : inherit;}#waterfall-zdy .movie-box-b{background-color:${local_color};}.alert-zdy {color: black;background-color: white;}`);
  549. }
  550. },
  551. maxWidth: 150,
  552. getAvItem: function (elem) {
  553. var href = elem.find("a")[0].href;
  554. var img = elem.find("div.item-image>img").eq(0);
  555. var src = img.attr("data-src").replace(/thumbs/, "covers") ;
  556. var title = elem.find("div.video-title").eq(0).text();
  557. if(!title) {title = elem.find("div.video-title2").eq(0).text()};
  558. var AVID = elem.find("div.uid").eq(0).text();
  559. if(!AVID) {AVID = elem.find("div.uid2").eq(0).text()};
  560. var date = elem.find("div.meta").eq(0).text();
  561. var itemTag = elem.find(".tags.has-addons").html();
  562. return {AVID: AVID,href: href,src: src,title: title,date: date,itemTag:itemTag};
  563. }
  564. //init: function(){ if(location.href.includes("/users/")){ this.widthSelector="div.section";} }
  565. },
  566. avmoo: {
  567. domainReg: /avmoo\./i,
  568. excludePages: ['/actresses'],
  569. menu:{
  570. position:'#navbar ul:first',
  571. html:`<li class='dropdown'><a class='dropdown-toggle'>${lang.menuText}</a></li>`
  572. },
  573. gridSelector: 'div#waterfall',
  574. itemSelector: 'div#waterfall div.item',
  575. widthSelector : '#waterfall-zdy',
  576. pageNext: 'a[name="nextpage"]',
  577. pageSelector:'.pagination',
  578. getAvItem: function (elem) {
  579. var photoDiv = elem.find("div.photo-frame")[0];
  580. var href = elem.find("a")[0].href;
  581. var img = $(photoDiv).children("img")[0];
  582. var src = img.src.replace(/ps.jpg/, "pl.jpg");
  583. var title = img.title;
  584. var AVID = elem.find("date").eq(0).text();
  585. var date = elem.find("date").eq(1).text();
  586. var itemTag = "";elem.find("div.photo-info .btn").toArray().forEach( x=> itemTag+=x.outerHTML);
  587. return {AVID: AVID,href: href,src: src,title: title,date: date,itemTag:itemTag};
  588. }
  589. },
  590. javlibrary: {
  591. domainReg: /javlibrary\./i,
  592. menu:{
  593. position:'div#rightcolumn',
  594. html:`<div style="position: absolute;top: -1em;right: 10px;color: #000000;background: #ffffff;padding: 5px 5px 5px 5px;font-weight: bold;font-family: Arial;">${lang.menuText}</div>`
  595. },
  596. gridSelector: 'div.videothumblist',
  597. itemSelector: 'div.videos div.video',
  598. widthSelector : '#waterfall-zdy',
  599. pageNext: 'a.page.next',
  600. pageSelector:'.page_selector',
  601. getAvItem: function (elem) {
  602. var href = elem.find("a")[0].href;
  603. var src = elem.find("img")[0].src;
  604. if(src.indexOf("pixhost")<0){//排除含有pixhost的src
  605. src= src.replace(/ps.jpg/, "pl.jpg");
  606. }
  607. var title = elem.find("div.title").eq(0).text();
  608. var AVID = elem.find("div.id").eq(0).text();
  609. return {AVID: AVID,href: href,src: src,title: title,date: '',itemTag:''};
  610. },
  611. init_Style: function(){
  612. GM_addStyle(`#menu-div{right:0} #waterfall-zdy div{box-sizing: border-box;}`);
  613. },
  614. }
  615. };
  616.  
  617. function oldDriverBlock(){
  618. if(['javbus','avmoo'].includes(currentWeb)){ //屏蔽老司机脚本,改写id
  619. if ($('.masonry').length > 0) {
  620. $('.masonry').removeClass("masonry");
  621. }
  622. let $waterfall = $('#waterfall');
  623. if($waterfall.length){
  624. $waterfall.get(0).id = "waterfall-destroy";
  625. }
  626. if($waterfall.find("#waterfall").length){ //javbus首页有2个'waterfall' ID
  627. $waterfall.find("#waterfall").get(0).id = "";
  628. }
  629. //解决 JAV老司机 $pages[0].parentElement.parentElement.id = "waterfall_h";
  630. //女优作品界面此代码会把id设置到class=row层
  631. if ($('#waterfall_h.row').length > 0) {
  632. $('#waterfall_h.row').removeAttr("id");
  633. }
  634. let $waterfall_h= $('#waterfall_h');
  635. if ($waterfall_h.length) {
  636. $waterfall_h.get(0).id = "waterfall-destroy";
  637. }
  638. if(location.pathname.search(/search/) > 0){//解决"改写id后,搜索页面自动跳转到无码页面"的bug
  639. $('body').append('<div id="waterfall"></div>');
  640. }
  641. currentObj.gridSelector = "#waterfall-destroy";
  642. }
  643. if(['javlibrary'].includes(currentWeb)){ //屏蔽老司机脚本,改写id
  644. let $waterfall = $('div.videothumblist');
  645. if($waterfall.length){
  646. $waterfall.removeClass("videothumblist");
  647. $waterfall.find(".videos").removeClass("videos");
  648. $waterfall.get(0).id = "waterfall-destroy";
  649. }
  650. currentObj.gridSelector = "#waterfall-destroy";
  651. }
  652. }
  653. function pageInit() {
  654. for (var key in ConstCode) {
  655. var domainReg = ConstCode[key].domainReg;
  656. if (domainReg && domainReg.test(location.href)) {
  657. currentWeb = key;
  658. currentObj = ConstCode[key];
  659. //排除页面的判断
  660. if (ConstCode[key].excludePages) {
  661. for (var page of ConstCode[key].excludePages) {
  662. if (location.pathname.includes(page)) return;
  663. }
  664. }
  665. //调用初始化方法 未使用 if (ConstCode[key].init) { ConstCode[key].init();}
  666. //屏蔽竖图模式的页面判断
  667. if (ConstCode[key].halfImg_block_Pages) {
  668. for (var blockPage of ConstCode[key].halfImg_block_Pages) {
  669. if (location.href.includes(blockPage)) {
  670. Status.halfImg_block = true;
  671. break;
  672. };
  673. }
  674. }
  675. break;
  676. }
  677. }
  678. let $items = $(currentObj.itemSelector);
  679. if (currentWeb && $items.length) {
  680. oldDriverBlock();
  681. $(currentObj.gridSelector).hide();
  682. var waterfall=$(`<div id= 'waterfall-zdy'></div>`);
  683. $(currentObj.gridSelector).eq(0).before(waterfall);
  684. addStyle();//全局样式
  685. if(currentObj.init_Style){currentObj.init_Style()};
  686. addMenu(); //添加菜单
  687. myModal = new Popover();//弹出插件
  688. //加载图片懒加载插件
  689. lazyLoad = new LazyLoad({
  690. callback_loaded: function (img) {
  691. $(img).removeClass("minHeight-200");
  692. tool_Func.imgCallback(img);
  693. }
  694. });
  695. let elems=getItems($items);
  696. waterfall.append(elems);
  697. lazyLoad.update();
  698. if(Status.get("autoPage") && $(currentObj.pageSelector).length ){
  699. scroller=new ScrollerPlugin(waterfall,lazyLoad);
  700. }
  701. }
  702. }
  703. let lazyLoad;
  704. let scroller;
  705. class ScrollerPlugin{
  706. constructor(waterfall,lazyLoad){
  707. let me=this;
  708. me.waterfall=waterfall;
  709. me.lazyLoad=lazyLoad;
  710. let $pageNext=$(currentObj.pageNext);
  711. me.nextURL = $pageNext.attr('href');
  712. me.scroller_status=$(`<div class = "scroller-status" style="text-align:center;display:none"><div class="scroll-request"><span></span><span></span><span></span><span></span></div><h2 class="scroll-last">${lang.scrollerPlugin_end}</h2></div>`);
  713. me.waterfall.after(me.scroller_status);
  714. me.locked=false;
  715. me.canLoad=true;
  716. me.$page=$(currentObj.pageSelector);
  717. me.wheelFunc=me.wheelWatch.bind(me);
  718. document.addEventListener('wheel',me.wheelFunc);
  719. }
  720. wheelWatch (){
  721. let me = this;
  722. if (me.$page.get(0).getBoundingClientRect().top - $(window).height() < 300 && (!me.locked) && (me.canLoad)) {
  723. me.locked=true;
  724. me.loadNextPage(me.nextURL).then(()=>{me.locked=false});
  725. }
  726. }
  727. async loadNextPage(url){
  728. this.showStatus('request');
  729. console.log(url);
  730. let respondText = await fetch(url, { credentials: 'same-origin' }).then(respond=>respond.text());
  731. let $body = $(new DOMParser().parseFromString(respondText, 'text/html'));
  732. let elems = getItems($body.find(currentObj.itemSelector));
  733. if (currentWeb != "javdb" && location.pathname.includes('/star/') && elems) {
  734. elems=elems.slice(1);
  735. }
  736. this.scroller_status.hide();
  737. this.waterfall.append(elems);
  738. this.lazyLoad.update();
  739. this.nextURL = $body.find(currentObj.pageNext).attr('href');
  740. if(!this.nextURL){
  741. this.canLoad=false;
  742. this.showStatus("last");
  743. }
  744. }
  745. showStatus(status){
  746. this.scroller_status.children().each( (i,e)=>{$(e).hide()});
  747. this.scroller_status.find(`.scroll-${status}`).show();
  748. this.scroller_status.show();
  749. }
  750. destroy (){
  751. this.scroller_status.remove();
  752. document.removeEventListener('wheel',this.wheelFunc);
  753. }
  754. }
  755.  
  756. function getItems(elems) {
  757. var elemsHtml = "";
  758. var imgStyle = Status.isHalfImg() ? halfImgCSS : fullImgCSS;
  759. var parseFunc = currentObj.getAvItem;
  760. for (let i = 0; i < elems.length; i++) {
  761. elemsHtml = elemsHtml + getItem(elems.eq(i), parseFunc,imgStyle);
  762. }
  763. var $elems = $(elemsHtml);
  764. if (!Status.get("toolBar")) {
  765. $elems.find(".func-div").css("display","none");
  766. }
  767. if(!(['javbus','javdb'].includes(currentWeb))){
  768. $elems.find(".func-div span[name='magnet']").remove();
  769. }
  770. if (!Status.get("copyBtn")) {
  771. $elems.find(".copy-svg").css("display","none");
  772. }
  773. if (Status.get("fullTitle")) {
  774. $elems.find(".titleNowrap").removeClass("titleNowrap");
  775. }
  776. $elems.find("span[name='copy']").click(function () {
  777. GM_setClipboard($(this).next().text());
  778. showAlert(lang.copySuccess);
  779. return false;
  780. });
  781. $elems.find(".func-div span[name='download']").click(function () {
  782. GM_download($(this).attr("src"), $(this).attr("src-title")+".jpg");
  783. });
  784. $elems.find(".func-div span[name='magnet']").click(function () {
  785. showMagnetTable($(this).attr("AVID").replace(/\./g, '-'),$(this).attr("data-href"),this);
  786. });
  787. $elems.find(".func-div span[name='picture']").click(function () {
  788. showBigImg($(this).attr("AVID"),this);
  789. });
  790. return $elems;
  791. }
  792.  
  793. function getItem(tag,parseFunc,imgStyle) {
  794. if (currentWeb!="javdb" && tag.find(".avatar-box").length) {
  795. tag.find(".avatar-box").addClass("avatar-box-b").removeClass("avatar-box");
  796. return `<div class='item-b'>${tag.html()}</div>`;
  797. }
  798. var AvItem = parseFunc(tag);
  799. return `<div class="item-b">
  800. <div class="movie-box-b">
  801. <div class="photo-frame-b">
  802. <a href="${AvItem.href}" target="_blank"><img style="${imgStyle}" class="lazy minHeight-200" data-src="${AvItem.src}" ></a>
  803. </div>
  804. <div class="photo-info-b">
  805. <a name="av-title" href="${AvItem.href}" target="_blank" title="${AvItem.title}" class="titleNowrap"><span class="svg-span copy-svg" name="copy">${copy_Svg}</span> <span>${AvItem.title}</span></a>
  806. <div class="info-bottom">
  807. <div class="info-bottom-one">
  808. <span class="svg-span copy-svg" name="copy">${copy_Svg}</span><date name="avid">${AvItem.AVID}</date>${AvItem.date?` / ${AvItem.date}`:""}
  809. </div>
  810. <div class="info-bottom-two">
  811. <div class="item-tag">${AvItem.itemTag}</div>
  812. <div class="func-div">
  813. <span name="magnet" class="svg-span" title="${lang.tool_magnetTip}" AVID="${AvItem.AVID}" data-href="${AvItem.href}">${magnet_Svg}</span>
  814. <span name="download" class="svg-span" title="${lang.tool_downloadTip}" src="${AvItem.src}" src-title="${AvItem.AVID} ${AvItem.title}">${download_Svg}</span>
  815. <span name="picture" class="svg-span" title="${lang.tool_pictureTip}" AVID="${AvItem.AVID}" >${picture_Svg}</span>
  816. </div>
  817. </div>
  818. </div>
  819. </div>
  820. </div>
  821. </div>`;
  822. }
  823.  
  824. let waterfallWidth = 100;
  825. function addStyle() {
  826. var columnNum = Status.getColumnNum();
  827. waterfallWidth=Status.get("waterfallWidth");
  828. var css_waterfall = `
  829. ${currentObj.widthSelector}{
  830. width:${waterfallWidth}%;
  831. margin:0 ${waterfallWidth>100?(100-waterfallWidth)/2+'%':'auto'};
  832. transition:.5s ;
  833. }
  834. /*#waterfall-zdy img.lazy{transition: width .3s ;}*/
  835. #waterfall-zdy{
  836. display:flex;
  837. flex-direction:row;
  838. flex-wrap:wrap;
  839. }
  840. #waterfall-zdy .item-b{
  841. padding:5px;
  842. width:${100 / columnNum}%;
  843. transition:.5s ;
  844. animation: fadeInUp .5s ease-out;
  845. }
  846. #waterfall-zdy .movie-box-b {
  847. border-radius: 5px;
  848. background-color:white;
  849. border: 1px solid rgba(0, 0, 0, 0.2);
  850. box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.1);
  851. overflow: hidden;
  852. }
  853. a[name="av-title"]:link { color : black;}
  854. a[name="av-title"]:visited { color : gray;}
  855. .minHeight-200{
  856. min-height:200px;
  857. }
  858. #waterfall-zdy .movie-box-b .photo-frame-b {
  859. text-align: center;
  860. }
  861. #waterfall-zdy .movie-box-b .photo-info-b {
  862. padding: 7px;
  863. }
  864. #waterfall-zdy .movie-box-b .photo-info-b a {
  865. display: block;
  866. }
  867. #waterfall-zdy .info-bottom,.info-bottom-two{
  868. display: flex;
  869. justify-content: space-between;
  870. align-items: center;
  871. flex-wrap: wrap;
  872. }
  873. #waterfall-zdy .avatar-box-b {
  874. display: flex;
  875. flex-direction: column;
  876. background-color:white;
  877. border-radius: 5px;
  878. align-items: center;
  879. border: 1px solid rgba(0, 0, 0, 0.2);
  880. }
  881. #waterfall-zdy .avatar-box-b p {
  882. margin: 0 !important
  883. }
  884. #waterfall-zdy date:first-of-type {
  885. font-size: 18px !important
  886. }
  887. #waterfall-zdy .func-div {
  888. float: right;padding: 2px;
  889. white-space:nowrap;
  890. }
  891. #waterfall-zdy .func-div span {
  892. margin-right: 2px;
  893. }
  894. #waterfall-zdy .copy-svg {
  895. vertical-align: middle;
  896. display: inline-block
  897. }
  898. #waterfall-zdy span.svg-span {
  899. cursor: pointer;
  900. opacity: .3;
  901. }
  902. #waterfall-zdy span.svg-span:hover {
  903. opacity: 1
  904. }
  905. #waterfall-zdy .item-tag {
  906. display: inline-block;
  907. white-space:nowrap;
  908. }
  909. #myModal {
  910. overflow-x: hidden;
  911. overflow-y: auto;
  912. display: none;
  913. position: fixed;
  914. top: 0;
  915. left: 0;
  916. right: 0;
  917. bottom: 0;
  918. z-index: 1050;
  919. background-color: rgba(0, 0, 0, 0.5);
  920. }
  921. #myModal #modal-div {
  922. position: relative;
  923. width: 80%;
  924. margin: 0 auto;
  925. background-color: rgb(6 6 6 / 50%);
  926. border-radius: 8px;
  927. animation: fadeInDown .5s;
  928. }
  929. #modal-div .pop-up-tag {
  930. border-radius: 8px;
  931. overflow: hidden
  932. }
  933. #modal-div .sample-box-zdy,.avatar-box-zdy {
  934. display: inline-block;
  935. border-radius: 8px;
  936. background-color: #fff;
  937. overflow: hidden;
  938. margin: 5px;
  939. width: 140px
  940. }
  941. #modal-div .sample-box-zdy .photo-frame {
  942. overflow: hidden;
  943. margin: 10px
  944. }
  945. #modal-div .sample-box-zdy img {
  946. height: 90px
  947. }
  948. #modal-div .avatar-box-zdy .photo-frame {
  949. overflow: hidden;
  950. height: 120px;
  951. margin: 10px
  952. }
  953. #modal-div .avatar-box-zdy img {
  954. height: 120px
  955. }
  956. #modal-div .avatar-box-zdy span {
  957. font-weight: bold;
  958. text-align: center;
  959. word-wrap: break-word;
  960. display: flex;
  961. justify-content: center;
  962. align-items: center;
  963. padding: 5px;
  964. line-height: 22px;
  965. color: #333;
  966. background-color: #fafafa;
  967. border-top: 1px solid #f2f2f2
  968. }
  969. svg.tool-svg {
  970. fill: currentColor;
  971. width: 22px;
  972. height: 22px;
  973. vertical-align: middle
  974. }
  975. span.svg-loading {
  976. display: inline-block;
  977. animation: svg-loading 2s infinite;
  978. }
  979. #menu-div {
  980. white-space: nowrap;
  981. background-color: white;
  982. color:black;
  983. display: none;
  984. min-width: 200px;
  985. position: absolute;
  986. top: 100%;
  987. border-radius: 5px;
  988. padding: 5px;
  989. box-shadow: 0 10px 20px 0 rgb(0 0 0 / 50%)
  990. }
  991. #menu-div>div:hover{
  992. background-color:gainsboro;
  993. }
  994. #menu-div .switch-div,#menu-div .switch-div *{
  995. margin: 3px;
  996. }
  997. #menu-div .switch-div label{
  998. display: inline;
  999. }
  1000. #menu-div .range-div {
  1001. display: flex;
  1002. flex-direction: row;
  1003. flex-wrap: nowrap;
  1004. }
  1005. #menu-div .range-div input {
  1006. cursor: pointer;
  1007. width: 80%;max-width:200px;
  1008. }
  1009. .alert-zdy {
  1010. position: fixed;
  1011. top: 50%;
  1012. left: 50%;
  1013. padding: 12px 20px;
  1014. font-size: 20px;
  1015. color: white;
  1016. background-color: rgb(0,0,0,.75);
  1017. border-radius: 4px;
  1018. animation: itemShow .3s;
  1019. z-index: 1051;
  1020. }
  1021. .titleNowrap{
  1022. white-space:nowrap;text-overflow: ellipsis;overflow:hidden;
  1023. }
  1024. .download-icon {
  1025. position: absolute;
  1026. right: 0;
  1027. z-index: 2;
  1028. cursor: pointer
  1029. }
  1030. .download-icon>svg {
  1031. width: 30px;
  1032. height: 30px;
  1033. fill: aliceblue;
  1034. }
  1035. @keyframes fadeInUp {
  1036. 0% {transform: translate3d(0, 10%, 0);opacity: .5; }
  1037. 100% {transform: none; opacity: 1;}
  1038. }
  1039. @keyframes fadeInDown {
  1040. 0% {transform: translate3d(0, -100%, 0);opacity: 0; }
  1041. 100% {transform: none; opacity: 1;}
  1042. }
  1043. @keyframes itemShow {
  1044. 0% {transform:scale(0);}
  1045. 100% {transform:scale(1);}
  1046. }
  1047.  
  1048. @keyframes svg-loading{
  1049. 0% {transform:scale(1);opacity:1;}
  1050. 50% {transform:scale(1.2);opacity:1;}
  1051. 100% {transform:scale(1);opacity:1;}
  1052. }
  1053. .scroll-request {text-align: center;height: 15px; margin: 15px auto;}.scroll-request span {display: inline-block;width: 15px;height: 100%;margin-right: 8px;border-radius: 50%; background: rgb(16, 19, 16); animation: load 1s ease infinite;} @keyframes load { 0% ,100%{transform:scale(1); }50% {transform:scale(0);}}.scroll-request span:nth-child(2) {animation-delay: 0.125s;}.scroll-request span:nth-child(3) {animation-delay: 0.25s;}.scroll-request span:nth-child(4){animation-delay: 0.375s;}
  1054. `;
  1055. GM_addStyle(css_waterfall);
  1056. }
  1057. pageInit();
  1058. })();